title: Spring 5 reactive exception handling
body: <p>I'am writing a complex application as an experiment with Spring 5 Webflux. I'm planning to use lot's of techniques in this application. I'm familiar with the "old style" @RestController, but now, I'm writing functional endpoints. E.g. the backend of a company registration service.I was after something like the @ControllerAdvice in the "old world". But I wasn't really able to find anything similar as a reactive equivalent. (Or anything what worked out for me.)</p>
  
  <p>I have a very basic setup. A routing function, a reactive Cassandra repository, a handler and a test class. The repository operation can throw IllegalArgumentException, and I'd like to handle it by returning HTTP Status BadRequest to client. Just as an example of I'm capable to do it. :-) The exception is taken care by the handler class. Here is my code.</p>
  
  <p><strong>RouterConfig</strong></p>
  
  <pre><code>@Slf4j
  @Configuration
  @EnableWebFlux
  public class RouterConfig {
  
  @Bean
  public RouterFunction&lt;ServerResponse&gt; route(@Autowired CompanyHandler handler) {
      return RouterFunctions.route()
              .nest(path("/company"), bc -&gt; bc
                      .GET("/{id}", handler::handleGetCompanyDataRequest)                     
                      .before(request -&gt; {
                          log.info("Request={} has been received.", request.toString());
                          return request;
                      })
              .after((request, response) -&gt; {
                  log.info("Response={} has been sent.", response.toString());
                  return response;
              }))
              .build();       
      }
  }
  </code></pre>
  
  <p><strong>CompanyHandler</strong></p>
  
  <pre><code>@Slf4j
  @Component
  public class CompanyHandler {
  
      @Autowired
      private ReactiveCompanyRepository repository;
  
      // Handle get single company data request
      public Mono&lt;ServerResponse&gt; handleGetCompanyDataRequest(ServerRequest request) {
          //Some validation ges here
  
          return repository.findById(Mono.just(uuid))
              .flatMap(this::ok)
              .onErrorResume(IllegalArgumentException.class, e -&gt; ServerResponse.badRequest().build())
              .switchIfEmpty(ServerResponse.notFound().build());
      }
  
      private Mono&lt;ServerResponse&gt; ok (Company c) {
          return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
              .body(BodyInserters.fromPublisher(Mono.just(c), Company.class));
      }
  }
  </code></pre>
  
  <p><strong>ReactiveCompanyRepository</strong></p>
  
  <pre><code>@Component
  public interface ReactiveCompanyRepository extends ReactiveCassandraRepository&lt;Company, UUID&gt;{
  
      Mono&lt;Company&gt; findByName(String name);
  
      Mono&lt;Company&gt; findByEmail(String email);
  }
  </code></pre>
  
  <p>My problem is that <strong>.onErrorResume(IllegalArgumentException.class, e -> ServerResponse.badRequest().build())</strong> is never called and in the test case:</p>
  
  <pre><code>@SuppressWarnings("unchecked")
  @Test
  public void testGetCompanyExceptionDuringFind() {
  
      Mockito.when(repository.findById(Mockito.any(Mono.class))).thenThrow(new IllegalArgumentException("Hahaha"));       
  
      WebTestClient.bindToRouterFunction(routerConfig.route(companyHandler))
          .build()
          .get().uri("/company/2b851f10-356e-11e9-a847-0f89e1aa5554")
          .accept(MediaType.APPLICATION_JSON_UTF8)
          .exchange()
          .expectStatus().isBadRequest()
          .returnResult(Company.class)
          .getResponseBody();
  }
  </code></pre>
  
  <p>I always get HttpStatus 500 instead of 400. So it fails.Any help would be appreciated!</p>