Improve Your Spring REST API, Part III

Some time ago, I wrote about how the error response of a Spring based REST API can be enhanced, in order to provide the clients with a better understanding of why a request error occurred. In the first post I explained how a server-side exception triggered by an incoming request can be translated into a generic ErrorMessage class, which in turn was serialized to the response body. In the second part, the solution was generalized, to prevent the @ExceptionHandler methods from being duplicated to all controllers. However, the release of Spring 3.2 last December provides a new feature which greatly simplifies the general solution.


The @ControllerAdvice is a new TYPE annotation that was added as part of the release. A class annotated with it will act as a global helper class for all controllers. In other words, any local, controller specific @ExceptionHandler method that is moved from the @Controller class to a class annotated with @ControllerAdvice, will be applicable for the entire application. Consequently, all the boiler plate code that was created in the generic solution in my last post can be removed. The revisited solution can be as simple as:

The previous posts contained error handling examples of some Spring MVC exceptions, namely the MethodArgumentNotValidException, the HttpMediaTypeNotSupportedException and the HttpMessageNotReadableException. A corresponding Spring 3.2 based implementation can be found in the GlobalControllerExceptionHandler, or continue reading for yet another implementation.


The above example works well, but it can be hard to identify the Spring MVC specific exceptions to implement a common error response handling strategy for them. One way of overcoming this problem is to extend the ResponseEntityExceptionHandler class, which was also added to the Spring 3.2 release. Similarly to the DefaultHandlerExceptionResolver, it provides methods for handling the exceptions, but it allows the developer to specify ResponseEntitys as return values (as opposed to the ModelAndViews that are returned by the methods in the DefaultHandlerExceptionResolver). The implementation is still straight forward, create a class, annotate it with the @ControllerAdvice, extend the ResponseEntityExceptionHandler class and override the methods with the exception types that you are interested in:


  • The @ControllerAdvice annotation is an @Component. As such, an annotated class will be registered as a Spring bean if the package in which it is located in is subject to component scanning.
  • The @ControllerAdvice also supports methods annotated with @InitBinder and @ModelAttribute.


Mattias Severson

Mattias is a senior software engineer specialized in backend architecture and development with experience of cloud based applications and scalable solutions. He is a clean code proponent who appreciates Agile methodologies and pragmatic Test Driven Development. Mattias has experience from many different environments, including everything between big international projects that last for years and solo, single day jobs. He is open-minded and curious about new technologies. Mattias believes in continuous improvement on a personal level as well as in the projects that he is working on. Additionally, Mattias is a frequent speaker at user groups, companies and conferences.

This Post Has 15 Comments

  1. Phani

    Thank you boss,
    U saved me

  2. forumssj

    Thanks for the great post! Can you give an example to create a Exception handler using the @ControllerAdvice annotation, to return JSON or Modelview depending on whether the request is ajax or non-ajax

    1. Mattias Severson

      Since the ErrorMessage class is annotated with @XmlRootElement it is eligible for XML serialization. However, if you use <mvc:annotation-driven /> (or @EnableWebMvc), then there a range of different HttpMessageConverters enabled for you automatically. Additionally, if you add Jackson to your classpath then you can get JSON as well. Which converter will be used is controlled by the client by specifying the accept in the server request (use application/json for JSON). More information can be found in the Spring reference docs, e.g. enable mvc config and message conversion.

      1. forumssj

        I have no problem with configuration for returning JSON. I have already done that. I am working on an application where the Spring controller returns Modelview or JSON depending on the request type. eg for ajax reguest return JSON and for a non-ajax request return a ModelView and I am looking for a common way to handle exceptions in both cases. But I think this is not possible with ResponseEntityExceptionHandler.

        1. Mattias Severson

          I have not looked into any details, but here are a some suggestions that may help you:

          • Extend the DefaultHandlerExceptionResolver which methods returns ModelAndView (instead of my example in which the CustomResponseEntityExceptionHandler‘s methods return ResponseEntity).
          • Try including a ModelAndView when returning an ResponseEntity from the ResponseEntityExceptionHandler, e.g.
            new ResponseEntity(new ModelAndView(...), headers, status)
          • If different resources are involved, perhaps you can use custom @ExceptionHandler for each controller.
          • Have you read Paul Chapman’s blog post about Content Negotiation Using Views? Perhaps you will find some ideas there.
          • Otherwise, I suggest that you post a question on the Spring Forum or on Stack Overflow.
  3. Pranay

    I am still facing the issue..Unable to hit the breakpoint after getting bad request error with the above mentioned changes.

    1. Mattias Severson

      @csf: Yes that is nice solution if you are using Spring Hateoas. Side note, if you look at the history at the Spring Hateoas GitHub repo you will find that VndErrors was created a couple of months after I wrote the blogpost.

  4. midstr

    Best Practices!!!

  5. Lace Frontal

    Awesome explanation. Very helpful.
    Keep it up.
    Thank you.

  6. Sanjay

    i am using jersey , will it work if i use jersey RestExceptionHandler doesnt seems to work any idea how can i make it work ?

    1. Mattias Severson

      @Sanjay: Thank you for your question. The @ControllerAdvice, ResponseEntityExceptionHandler and other annotations above are all part of the Spring MVC framework and thus tie into the Spring MVC exception handling. I guess that it is possible to make them work with Jersey as well, but I have not tried. I suggest that you choose to implement your controller logic in either Spring MVC or Jersey / JAXR-RS rather than mixing the two since both have the capability of solving the problem.

Leave a Reply