Before the deprecation of WebClient.exchange
method I used to get ClientResponse body as Flux<DataBuffer>
and manipulated it.
In Spring 5.3 the exchange()
method is deprecated and I would like to change the implementation as recommended:
@deprecated since 5.3 due to the possibility to leak memory and/or connections; please, use {@link #exchangeToMono(Function)}, {@link #exchangeToFlux(Function)}; consider also using {@link #retrieve()} ...
Tried to do the same call in the lambda passed to exchangeToMono
, but clientResponse.bodyToFlux(DataBuffer::class.java)
always return an empty flux; other experiments (i.e. getting body as mono string) also could not help to get the body.
What is the standard way to get the ClientResponse body in Spring 5.3 ?
I am looking for a low-level body representation: something like "data buffer", "byte array" or "input stream"; to avoid any kind of parsing/deserialisation.
Before Spring 5.3:
webClient
.method(GET)
.uri("http://somewhere.com")
.exchange()
.flatMap { clientResponse ->
val bodyRaw: Flux<DataBuffer> = clientResponse.bodyToFlux(DataBuffer::class.java)
// ^ body as expected
// other operations
}
After Spring 5.3
webClient
.method(GET)
.uri("http://somewhere.com")
.exchangeToMono { clientResponse ->
val bodyRaw: Flux<DataBuffer> = clientResponse.bodyToFlux(DataBuffer::class.java)
// ^ always empty flux
// other operations
}
The new exchangeToMono
and exchangeToFlux
methods expect the body to be decoded inside the callback. Check this GitHub issue for details.
Looking at your example, probably you could use retrieve
, that is safer alternative, with bodyToFlux
webClient
.method(GET)
.uri("http://somewhere.com")
.retrieve()
.bodyToFlux(DataBuffer.class)
or toEntityFlux
if you need access to response details like headers and status
webClient
.method(GET)
.uri("http://somewhere.com")
.retrieve()
.toEntityFlux(DataBuffer.class)
Handling errors
Option 1. Use onErrorResume
and handle WebClientResponseException
webClient
.method(GET)
.uri("http://somewhere.com")
.retrieve()
.bodyToFlux(DataBuffer.class)
.onErrorResume(WebClientResponseException.class, ex -> {
if (ex.getStatusCode().equals(HttpStatus.NOT_FOUND)) {
// ignore 404 and return empty
return Mono.empty();
}
return Mono.error(ex);
});
Option 2. Use onStatus
convenience method to get access to response.
webClient
.method(GET)
.uri("http://somewhere.com")
.retrieve()
.onStatus(status -> status.equals(HttpStatus.NOT_FOUND), res -> {
// ignore 404 and return empty
return Mono.empty();
})
.bodyToFlux(DataBuffer.class)
Both methods could be used to deserialize error response Getting the response body in error case with Spring WebClient