Spring Webflux : Webclient : Get body on error Spring Webflux : Webclient : Get body on error spring spring

Spring Webflux : Webclient : Get body on error


I prefer to use the methods provided by the ClientResponse to handle http errors and throw exceptions:

WebClient.create()         .post()         .uri( url )         .body( bodyObject == null ? null : BodyInserters.fromValue( bodyObject ) )         .accept( MediaType.APPLICATION_JSON )         .headers( headers )         .exchange()         .flatMap( clientResponse -> {             //Error handling             if ( clientResponse.statusCode().isError() ) { // or clientResponse.statusCode().value() >= 400                 return clientResponse.createException().flatMap( Mono::error );             }             return clientResponse.bodyToMono( clazz )         } )         //You can do your checks: doOnError (..), onErrorReturn (..) ...         ...

In fact, it's the same logic used in the DefaultResponseSpec of DefaultWebClient to handle errors. The DefaultResponseSpec is an implementation of ResponseSpec that we would have if we made a retrieve() instead of exchange().


Don't we have onStatus()?

    public Mono<Void> cancel(SomeDTO requestDto) {        return webClient.post().uri(SOME_URL)                .body(fromObject(requestDto))                .header("API_KEY", properties.getApiKey())                .retrieve()                .onStatus(HttpStatus::isError, response -> {                    logTraceResponse(log, response);                    return Mono.error(new IllegalStateException(                            String.format("Failed! %s", requestDto.getCartId())                    ));                })                .bodyToMono(Void.class)                .timeout(timeout);    }

And:

    public static void logTraceResponse(Logger log, ClientResponse response) {        if (log.isTraceEnabled()) {            log.trace("Response status: {}", response.statusCode());            log.trace("Response headers: {}", response.headers().asHttpHeaders());            response.bodyToMono(String.class)                    .publishOn(Schedulers.elastic())                    .subscribe(body -> log.trace("Response body: {}", body));        }    }


You could also do this

return webClient.getWebClient() .post() .uri("/api/Card") .body(BodyInserters.fromObject(cardObject)) .exchange() .flatMap(clientResponse -> {     if (clientResponse.statusCode().is5xxServerError()) {        clientResponse.body((clientHttpResponse, context) -> {           return clientHttpResponse.getBody();        });     return clientResponse.bodyToMono(String.class);   }   else     return clientResponse.bodyToMono(String.class);});

Read this article for more examples link, I found it to be helpful when I experienced a similar problem with error handling