I am trying to set up a large-scale REST services server. We're using Spring Boot 1.2.1 Spring 4.1.5, and Java 8. Our controllers are implementing @RestController and the standard @RequestMapping annotations.
My problem is that Spring Boot sets up a default redirect for controller exceptions to /error
. From the docs:
Spring Boot provides an /error mapping by default that handles all errors in a sensible way, and it is registered as a ‘global’ error page in the servlet container.
Coming from years writing REST applications with Node.js, this is, to me, anything but sensible. Any exception a service endpoint generates should return in the response. I can't understand why you'd send a redirect to what is most likely an Angular or JQuery SPA consumer which is only looking for an answer and can't or won't take any action on a redirect.
What I want to do is set up a global error handler that can take any exception - either purposefully thrown from a request mapping method or auto-generated by Spring (404 if no handler method is found for the request path signature), and return a standard formatted error response (400, 500, 503, 404) to the client without any MVC redirects. Specifically, we are going to take the error, log it to NoSQL with a UUID, then return to the client the right HTTP error code with the UUID of the log entry in the JSON body.
The docs have been vague on how to do this. It seems to me that you have to either create your own ErrorController implementation or use ControllerAdvice in some fashion, but all the examples I've seen still include forwarding the response to some kind of error mapping, which doesn't help. Other examples suggest that you'd have to list every Exception type you want to handle instead of just listing "Throwable" and getting everything.
Can anyone tell me what I missed, or point me in the right direction on how to do this without suggesting up the chain that Node.js would be easier to deal with?
@RestControllerAdvice is a new feature of Spring Framework 4.3 to handle Exception with RestfulApi by a cross-cutting concern solution:
With Spring Boot 1.4+ new cool classes for easier exception handling were added that helps in removing the boilerplate code.
A new
@RestControllerAdvice
is provided for exception handling, it is combination of@ControllerAdvice
and@ResponseBody
. You can remove the@ResponseBody
on the@ExceptionHandler
method when use this new annotation.i.e.
For handling 404 errors adding
@EnableWebMvc
annotation and the following to application.properties was enough:spring.mvc.throw-exception-if-no-handler-found=true
You can find and play with the sources here:
https://github.com/magiccrafter/spring-boot-exception-handling
For REST controllers, I would recommend to use
Zalando Problem Spring Web
.https://github.com/zalando/problem-spring-web
If Spring Boot aims to embed some auto-configuration, this library does more for exception handling. You just need to add the dependency:
And then define one or more advice traits for your exceptions (or use those provided by default)
Then you can defined the controller advice for exception handling as: