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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With