Reputation: 1584
I'm trying to make a POST call to an api through WebClient
without a request body (the api does not need a body):
webClient.post()
.uri("url")
.retrieve()
.bodyToMono(CustomResponse.class);
But the call returns an exception:
The underlying HTTP client completed without emitting a response.java.lang.IllegalStateException: The underlying HTTP client completed without emitting a response.
For another API which requires a request body, I can successfully make a POST call with no issue:
webClient.post()
.uri("url")
.bodyValue("value")
.retrieve()
.bodyToMono(CustomResponse.class);
Is the problem related to the WebClient’s request body? How do I fix it?
UPDATE
The error happens because I added a ContentType
header for Webclient through .defaultHeader("ContentType", JSON)
.
The problem has gone after I've removed the header.
Upvotes: 3
Views: 11871
Reputation: 1
The problem we solved involved handling scenarios where the WebClient reactive flow terminates with an IllegalStateException: The underlying HTTP client completed without emitting a response. This issue can occur when the server responds with an HTTP 204 (No Content) status, and the WebClient is not correctly configured to manage empty response bodies.
It an issue in certain versions of the Spring (like 2.7.4). This occurs because the library incorrectly tries to read the body even when there is none.
If you need body, it was possible to solve it with the help of configuration
@Bean
public WebClient webClientWithTimeout(
WebClient.Builder webClientBuilder) {
HttpClient httpClient = HttpClient.create();
return webClientBuilder
.clientConnector(new ReactorClientHttpConnector(httpClient))
.filter((request, next) -> next.exchange(request)
.flatMap(clientResponse -> {
if (clientResponse.statusCode() == HttpStatus.NO_CONTENT) {
// Replace the original response with an empty one (NO_CONTENT status preserved)
return Mono.just(ClientResponse.create(HttpStatus.NO_CONTENT).build());
}
// Pass through all other responses unchanged
return Mono.just(clientResponse);
}))
.build();}
I hope this helps.
Upvotes: 0
Reputation: 1171
It looks like the downstream webservice responding too slow and exceeding connection timeout hence you're getting this issue.
In case you don't need (or response doesn't have body) you can use .toBodilessEntity()
instead. So you code snippet can be rewritten:
webClient.post()
.uri("url")
.retrieve()
.toBodilessEntity();
Why should you use it? Because you're always responsible for resources release. Please, read NOTE section.
When using exchange(), it is the responsibility of the application to consume any response content regardless of the scenario (success, error, unexpected data, etc). Not doing so can cause a memory leak. See ClientResponse for a list of all the available options for consuming the body.
Upvotes: 5