How could we use @ExceptionHandler with spring web flux?

Now it is possible to use the @ExceptionHandler as well as @RestControllerAdvice or even @ControllerAdvice in Spring WebFlux.

Example:

  1. Add the webflux dependency

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    
  2. Create your class ExceptionHandler

    @RestControllerAdvice
    public class ExceptionHandlers {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionHandlers.class);
    
        @ExceptionHandler(Exception.class)
        @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        public String serverExceptionHandler(Exception ex) {
            LOGGER.error(ex.getMessage(), ex);
            return ex.getMessage();
        }
    }
    
  3. Create a Controller

    @GetMapping(value = "/error", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Mono<String> exceptionReturn() {
        return Mono.error(new RuntimeException("test error"));
    }
    

Example extracted here:

https://ddcode.net/2019/06/21/spring-5-webflux-exception-handling/


You can use @ExceptionHandler annotated methods to handle errors that happen within the execution of a WebFlux handler (e.g., your controller method). With MVC you can indeed also handle errors happening during the mapping phase, but this is not the case with WebFlux.

Back to your exception propagation question, the article you're sharing is not accurate.

In reactive applications, the request processing can indeed hop from one thread to another at any time, so you can't rely on the "one thread per request" model anymore (think: ThreadLocal).

You don't have to think about exception propagation or how threads are managed, really. For example, the following samples should be equivalent:

@GetMapping("/test")
public Mono<User> showUser() {
  throw new IllegalStateException("error message!");
}


@GetMapping("/test")
public Mono<User> showUser() {
  return Mono.error(new IllegalStateException("error message!"));
}

Reactor will send those Exceptions as error signals as expected in the Reactive Streams contract (see the "error handling" documentation section for more on that).


not an exact answer to the original question, but a quick way to map your exceptions to http response status is to throw org.springframework.web.server.ResponseStatusException / or create your own subclasses...

Full control over http response status + spring will add a response body with the option to add a reason.

{
    "timestamp": 1529138182607,
    "path": "/api/notes/f7b.491bc-5c86-4fe6-9ad7-111",
    "status": 400,
    "error": "Bad Request",
    "message": "For input string: \"f7b.491bc\""
}