title: Catching exceptions in Spring Web Flux
body: <p>I have the following class for invoking a time-consuming operation via web-service:</p>
  
  <pre><code>@Service
  public class InferenceService {
  
      @Autowired
      private final WebClient inferenceClient;
  
      public ByteArrayResource invoke(FileSystemResource resource) throws HttpException {
          Mono&lt;ByteArrayResource&gt; mono = inferenceClient
                  .post()
                  .uri(INFERENCE_URI)
                  .contentType(MediaType.valueOf("application/zip"))
                  .body(BodyInserters.fromResource(resource))
                  .accept()
                  .retrieve()
                  .bodyToMono(ByteArrayResource.class);
  
          ByteArrayResource zip = mono.block();
          return zip;
      }
  }
  </code></pre>
  
  <p>If an exception occurs during web service invocation, like UnknownHostException, it is wrapped in a ReactiveException. I want my class to catch the original exception and rethrow it as a HttpException, so that I'm able to log it, handle by Spring exception handler, return 500 status from my controller and not to have a difficult to read stacktrace with suppressed exceptions in my log. I wrote something like this:</p>
  
  <pre><code>@Service
  public class InferenceService {
  
      @Autowired
      private final WebClient inferenceClient;
  
      public ByteArrayResource invoke(FileSystemResource resource) throws HttpException {
          Mono&lt;ByteArrayResource&gt; mono = inferenceClient
                  .post()
                  .uri(INFERENCE_URI)
                  .contentType(MediaType.valueOf("application/zip"))
                  .body(BodyInserters.fromResource(resource))
                  .accept()
                  .retrieve()
                  .onStatus(HttpStatus::is5xxServerError, this::getStatus500Error)
                  .bodyToMono(ByteArrayResource.class);
  
          try {
              ByteArrayResource zip = mono.block();
              return zip;
          } catch (RuntimeException e) {
              throw extractFromReactiveException(e);
          }
      }
  
      private Mono&lt;? extends Throwable&gt; getStatus500Error(ClientResponse clientResponse) {
          return Mono.error(new InternalServerError(getStatusErrorMsg(clientResponse)));
      }
  
      private HttpException extractFromReactiveException(RuntimeException e) {
          if (e.getCause() instanceof HttpException) {
              return (HttpException) e.getCause();
          } else {
              return new InternalServerError(e);
          }
      }
  }
  </code></pre>
  
  <p>But I feel that either there's a better way, or what i'm trying to achieve is wrong. What's the proper way?</p>