I am trying to use Webflux to stream a generated file to another location, however, if the generation of the file ran into an error, the api returns success, but with a DTO detailing the errors while generating the file instead of the file itself. This is using a very old and poorly designed api so please excuse the use of post and the api design.
The response from the api call (exchange()) is a ClientResponse. From here I can either convert to a ByteArrayResource using bodyToMono which can be streamed to a file, or, if there is an error in creating the file, then I can convert to the DTO also using bodyToMono. However, I cannot seem to do either or depending on the contents of the header of ClientResponse.
In run time I get an IllegalStateException caused by
block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-client-epoll-12
I think my issue is that I cannot call block() twice in the same function chain.
My code snippet is like so:
webClient.post()
.uri(uriBuilder -> uriBuilder.path("/file/")
.queryParams(params).build())
.exchange()
.doOnSuccess(cr -> {
if (MediaType.APPLICATION_JSON_UTF8.equals(cr.headers().contentType().get())) {
NoPayloadResponseDto dto = cr.bodyToMono(NoPayloadResponseDto.class).block();
createErrorFile(dto);
}
else {
ByteArrayResource bAr = cr.bodyToMono(ByteArrayResource.class).block();
createSpreadsheet(bAr);
}
}
)
.block();
Basically I want to process the ClientResponse differently based on the MediaType which is defined in the header.
Is this possible?
subscribe
. There should be no reason to callblock
. If you are using WebFlux you are doing so because you want to build a reactive pipeline, if you are callingblock
you are not doing that. Put another way, if you are callingblock
, just use a plain oldRestTemplate
- you code looks very procedural and side-effecty anyway, so shoehorning it into Reactor won't make it magically reactive. – Karmen