13

What is the expected behavior when WebClient bodyToMono encounters an empty body? In my specific example we are checking the status returned from a post call, and if it's an error converting it to our custom error format. If the conversion to the custom error format fails, we create a new error in our custom format stating that. But when a response came in that was an error with an empty body, it failed to send any error back at all because bodyToMono didn't fail as I had expected. See the below code block:

.retrieve()
.onStatus(HttpStatus::isError) { response ->
    response.bodyToMono(ErrorResponse::class.java)
        .doOnError {
            throw APIException(
                code = UNEXPECTED_RESPONSE_CODE,
                reason = it.message ?: "Could not parse error response from Inventory Availability",
                httpStatus = response.statusCode()
            )
        }
        .map {
            throw APIException(
                reason = it.errors.reason,
                code = it.errors.code,
                httpStatus = response.statusCode()
            )
        }
}

To fix this we added the switchIfEmpty.

.retrieve()
.onStatus(HttpStatus::isError) { response ->
    response.bodyToMono(ErrorResponse::class.java)
        .switchIfEmpty { throw RuntimeException("Received Empty Response Body") }
        .doOnError {
            throw APIException(
                code = UNEXPECTED_RESPONSE_CODE,
                reason = it.message ?: "Could not parse error response from Inventory Availability",
                httpStatus = response.statusCode()
            )
        }
        .map {
            throw APIException(
                reason = it.errors.reason,
                code = it.errors.code,
                httpStatus = response.statusCode()
            )
        }
}

My question is this: Is this expected behavior from bodyToMono? Since I'm explicitly asking to map the response body to my object of ErrorResponse, I would expect an empty body to error and then hit the doOnError block, but instead it just "succeeds"/returns an empty mono...hence us adding the switchIfEmpty block. If the object we were mapping to had nullable fields, I could see it not having an error, but since all fields are required why does bodyToMono not throw an error when trying to map "nothing" to my object?

chas spenlau
  • 325
  • 1
  • 2
  • 12

1 Answers1

9

This is correct. A Mono can produce 0..1 elements and an empty body just produces a mono that completes without emitting a value, much like Mono.empty().

If no body is an error in your use case you can call .single() on your mono.

Adam Bickford
  • 1,216
  • 12
  • 14