How to intercept and handle errors globally in WebFlux when they are being thrown from WebFilter
chain?
It is clear how to handle errors thrown from controllers: @ControllerAdvice
and @ExceptionHandler
help great.
This approach does not work when an exception is thrown from WebFilter
components.
In the following configuration GET /first
and GET /second
responses intentionally induce exceptions thrown. Although @ExceptionHandler
methods handleFirst
, handleSecond
are similar, the handleSecond
is never called. I suppose that is because MyWebFilter
does not let a ServerWebExchange
go to the stage where GlobalErrorHandlers
methods could be applied.
Response for GET /first
:
HTTP 500 "hello first" // expected
HTTP 500 "hello first" // actual
Response for GET /second
:
HTTP 404 "hello second" // expected
HTTP 500 {"path": "/second", "status": 500, "error": "Internal Server Error" } // actual
@RestController
class MyController {
@GetMapping("/first")
String first(){
throw new FirstException("hello first");
}
}
@Component
class MyWebFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange swe, WebFilterChain wfc) {
var path = swe.getRequest().getURI().getPath();
if (path.contains("second")){
throw new SecondException("hello second")
}
}
}
@ControllerAdvice
class GlobalErrorHandlers {
@ExceptionHandler(FirstException::class)
ResponseEntity<String> handleFirst(FirstException ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.message)
}
@ExceptionHandler(SecondException::class)
ResponseEntity<String> handleSecond(SecondException ex) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.message)
}
}