When using @ControllerAdvice
and @ExceptionHandler
annotations, along with some handler methods, I'm able to catch events from Exceptions thrown both by myself as by Spring Boot internally. For the handler to know which exception event to catch, I can use both the specific nested Exception class as a generic Exception class, as argument, at the handler... and it will catch the corresponding event.
I've not managed to catch one specific Exception event though, the one in which the user requests resources from a REST endpoint or path that doesn't exist at the @RestController... a "bad path". It just returns a 404 NOT FOUND response payload as a JSON, but I can't catch that at my @ControllerAdvice
@ExceptionHandler method in order to change the Response for that specific Exception event. Not even when using the top-level Exception.class can I catch this event... and I don't know the specific nested Exception class that Spring Boot uses when it throws this specific event, either.
Does anyone know what's the Exception class type whose instance Spring Boot throws when the user requests a "bad path" (inexistent endpoint) to the @RestController
of an application ?
Finally I was able to adapt successfully 2 solutions for this use-case exceptional flow !! :D
SOLUTION 1: By creating an ErrorController and implementing a method for the /error servlet mapping path. Inside, you can create and return your ResponseEntity already, or, in my case, I chose to throw an instance of my custom PathNotFoundException, so that later I could catch its event at my @AdviceController @ExceptionHandler method and mount my response payload data there. The disadvantage to this solution is that you can't get the path the user tried to access from the HttpServletRequest, as the path available will be the intermediate "/error" path from the ErrorController and not the original path the user tried to get any resources from. But, at least, with this solution, you can catch the exception event (at the ErrorController) and direct the flux to your custom handler to create and return a custom ResponseEntity and payload data from there.
.
.
.
SOLUTION 2:
This is the best solution.
For avoiding the redirectioning to and from the ErrorController, and for not having to implement a custom /error method there, you can simply:
2.1: add these two props at the application.properties:
spring.mvc.throw-exception-if-no-handler-found=true
spring.web.resources.add-mappings=false
2.2: at your @AdviceController @ExceptionHandler method you then will be able to catch the NoHandlerFoundException event, as when catching any other exception event there, then mounting your ResponseEntity and payload data. And, most importantly, as there won't be the redirectioning to and from the ErrorController (/error), you'll be able to get the original path the user tried to access from the HttpServletRequest.
Thanks to everyone who helped solve this simple, although recurring, issue, so that others can learn from it and not waste 24h, searching for a solution, as I just did ;D
See ya.
Daniel Pinheiro
danielpm1982.com