Search code examples
spring-bootreactive-programmingspring-webfluxwebclientspring-webclient

Exception Handling for async WebClient request


Recently I have been working with WebClient. I am creating both a sync request and an async request. In a sync request, I am able to catch WebClientResponseException whereas when I try to catch WebClientResponseException (tried with generic Exception as well, didn't work) in an async request, it cannot be caught. I couldn't find any example on the internet. I am not sure if such exception handling is possible in async WebClient requests.

Here are the code examples:

Sync Request (Where the exception can be caught)

{
webClient
.post()
.uri(POST_ENDPOINT)
.bodyValue(cloudEvent)
.header("Authorization", token)
.retrieve()
.toEntity(String.class)
.block();
 
}
catch(final WebClientResponseException e)
{
log.error(String.valueOf(e));
throw new MyCustomException ("");
} 

Async Request (Where the exception cannot be caught)

try
{
stream=
webClient
.get()
.uri(GET_ENDPOINT)
.header("Authorization", token)
.retrieve()
.bodyToFlux(Any_Parametrized_Type_Reference);
}
catch(ffinal WebClientResponseException e)
{
log.error(String.valueOf(e));
throw new MyCustomException ("");
}

Thanks in advance for any response.


Solution

  • Async means that the process will be transferd to another thread. bodyToFlux will do this and finish the execution, but you don´t have any control over that thread because, in your current thread, the function was executed and it doesn't trigger an issue.

    This is similar to Promises in JS, where you should have a callback in case of any exception.

    after bodyToFlux, you can add those callbacks.

    webClient.get()
      .uri("https://baeldung.com/path")
      .retrieve()
      .bodyToFlux(JsonNode.class)
      .timeout(Duration.ofSeconds(5))
      .onErrorMap(ReadTimeoutException.class, ex -> new HttpTimeoutException("ReadTimeout"))
      .onErrorReturn(SslHandshakeTimeoutException.class, new TextNode("SslHandshakeTimeout"))
      .doOnError(WriteTimeoutException.class, ex -> log.error("WriteTimeout"))
    

    onErrorMap, onErrorReturn and doOnError receive your callbacks and will execute the lambda methods in case of exception.

    More info here: https://www.baeldung.com/spring-webflux-timeout#exception-handling