Handing Web Exceptions
We have know when exposing RESTful APIs, we can choose between @RestController
and RouterFunction
.
The former is simple. If you have some experience with Spring WebMvc, it is easy to update your knowledge. Just need to use newer Reactor specific Mono
and Flux
instead in your codes.
The exception handling in reactive @RestController
is similar to the one in WebMVC.
-
Create an
Exception
class.public class PostNotFoundException extends RuntimeException { public PostNotFoundException(Long id) { super("Post:" + id +" is not found."); } }
-
Throw exception in your codes.
@GetMapping(value = "/{id}") public Mono<Post> get(@PathVariable(value = "id") Long id) { return this.posts.findById(id).switchIfEmpty(Mono.error(new PostNotFoundException(id))); }
-
Create a standalone
@ControllerAdvice
annotated class or@ExceptionHandler
annotated method in your controller class to handle the exceptions.@RestControllerAdvice @Slf4j class RestExceptionHandler { @ExceptionHandler(PostNotFoundException.class) ResponseEntity postNotFound(PostNotFoundException ex) { log.debug("handling exception::" + ex); return notFound().build(); } }
@RestControllerAdvice
only works for @RestController
.
If you are using RouterFunction
, create a WebExceptionHandler
bean to handle it manually.
@Bean
public WebExceptionHandler exceptionHandler() {
return (ServerWebExchange exchange, Throwable ex) -> {
if (ex instanceof PostNotFoundException) {
exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
return exchange.getResponse().setComplete();
}
return Mono.error(ex);
};
}
}
NOTE:
WebExceptionHandler
is a low-level API, also works well for the exception handling in the former controller case.
For the complete codes, check spring-reactive-sample/exception-handler and spring-reactive-sample/boot-exception-handler .