I'm using Spring Declarative HTTP Clients and I'm having a hard time being siloed with WebClient. Seems that it still has very poor documentation and few examples over the internet.
I'm trying to transform the response body with a filter to remove some boilerplate json from it. Here's what I tried:
private ExchangeFilterFunction responseUnwrapper() {
return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
if (clientResponse.statusCode().is2xxSuccessful()) {
return clientResponse
.bodyToMono(DataDTO.class)
.map(DataDTO::data)
.flatMap(mappedResponse -> Mono.just(ClientResponse.create(clientResponse.statusCode())
.headers(httpResponse -> clientResponse.headers().asHttpHeaders())
.body(mappedResponse)
.build()));
} else {
return Mono.just(clientResponse);
}
});
}
So basically the server response wraps the body in a "data": {}
attribute which I'm trying to remove here.
The above code doesn't compile because the body function of ClientReponse.Builder
expects one of the following:
Builder body(Function<Flux<DataBuffer>, Flux<DataBuffer>> transformer);
Builder body(Flux<DataBuffer> body);
Builder body(String body);
It is not clear to me how to use those, and if I just do .body(mappedResponse.toString())
I get an IllegalStateException: Timeout on blocking read for 5000000000 NANOSECONDS
So how do I properly transform a response body using WebClient?
EDIT: this is DataDTO code
public record DataDTO<T>(T data) {}
You have to serialize your data into a String
a pass it to the Builder body(String body)
. Probably you want to build a json, however technically mappedResponse.toString()
also fits. Your IllegalStateException
is not related to that part of code. Looks like you are calling block()
somewhere on a webclient's response Mono.
By the way, you don't need flatMap
here, map
is enough:
ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
if (clientResponse.statusCode().is2xxSuccessful()) {
return clientResponse
.bodyToMono(DataDTO.class)
.map(DataDTO::data)
.map(dtoData -> ClientResponse.create(clientResponse.statusCode())
.headers(httpResponse -> clientResponse.headers().asHttpHeaders())
.body(dtoData.toString()) // probably Jackson's objectMapper.writeValueAsString()
.build());
} else {
return Mono.just(clientResponse);
}
});