About Eugen Paraschiv

Exception Handling for REST with Spring 3.2

1. Overview

This article will focus on how to implement Exception Handling with Spring for a REST API. We’ll look at the older solutions available before Spring 3.2 and then at the new Spring 3.2 support.

The main goal of this article is to show how to best map Exceptions in the application to HTTP Status Codes. Which status codes are suitable for which scenarios is not in the scope of this article, neither is the syntax of REST Error Representation.

Before Spring 3.2, the two main approaches to handling exceptions in a Spring MVC application were: HandlerExceptionResolver and the @ExceptionHandler annotation. Spring 3.2 introduced the new @ControllerAdvice annotation to address the limitations of the previous two solutions.

All of these do have one thing in common – they deal with the separation of concerns very well: the standard application code can throw exception normally to indicate a failure of some kind – exceptions which will then be handled via any of the following.

2. Via Controller level @ExceptionHandler

Defining a Controller level method annotated with @ExceptionHandler is very easy:

That’s all well and good, but this approach does have one major drawback – the @ExceptionHandler annotated method is only active for that particular Controller, not globally for the entire application. Of course, this makes it not well suited for a generic exception handling mechanism.

A common solution for this is to have all Controllers in the application extending a Base Controller class – however, this can be a problem for applications where, for whatever reasons, the Controllers cannot be made to extend from such a class. For example, the Controllers may already extend from another base class which may be in another jar or not directly modifiable, or may themselves not be directly modifiable.

Next, we’ll look at another way to solve the exception handling problem – one that is global and does not include any changes to existing artifacts such as Controllers.

3. Via HandlerExceptionResolver

In order to implement a uniform exception handling mechanism in our REST API, we’ll need to work with an HandlerExceptionResolver – this will resolve any exceptions thrown at runtime by the application. Before going for a custom resolver, let’s go over the existing implementations.

3.1. ExceptionHandlerExceptionResolver

This resolver was introduced in Spring 3.1 and is enabled by default in the DispatcherServlet. This is actually the core component of how the @ExceptionHandler mechanism presented earlier works.

3.2. DefaultHandlerExceptionResolver

This resolver was introduced in Spring 3.0 and is enabled by default in the DispatcherServlet. It is used to resolve standard Spring exceptions to their corresponding HTTP Status Codes, namely Client error – 4xx and Server error – 5xx status codes. Here is the full list of the Spring Exceptions it handles, and how these are mapped to status codes.

While it does set the Status Code of the Response properly, one limitation of this resolver is that it doesn’t set anything to the body of the Response. However, in the context of a REST API, the Status Code is really not enough information to present to the Client – the response has to have a body as well, to allow the application to give additional information about the cause of the failure.

This can be solved by configuring View resolution and rendering error content through ModelAndView, but the solution is clearly not optimal – which is why a better option has been made available with Spring 3.2 – we’ll talk about that in the latter part of this article.

3.3. ResponseStatusExceptionResolver

This resolver was also introduced in Spring 3.0 and is enabled by default in the DispatcherServlet. It’s main responsibility is to use the @ResponseStatus annotation available on custom exceptions and to map these exceptions to HTTP status codes.

The SimpleMappingExceptionResolver has been around for quite some time – it comes out of the older Spring MVC model and is not very relevant for a REST Service. It is used to map exception class names to view names.

The AnnotationMethodHandlerExceptionResolver was introduced in Spring 3.0 to handle exceptions through the @ExceptionHandler annotation, but has been deprecated by ExceptionHandlerExceptionResolver as of Spring 3.2.

3.5. Custom HandlerExceptionResolver

The combination of DefaultHandlerExceptionResolver and ResponseStatusExceptionResolver goes a long way towards providing a good error handling mechanism for a Spring RESTful Service – but the major limitation – no control over the body of the response – justifies creating a new exception resolver.

So, one goal for the new resolver is to enable setting a more informative response body – one that would also conform to the type of representation requested by the client (as specified by the Accept header):

One detail to notice here is the Request itself is available, so the application can consider the value of the Accept header sent by the client. For example, if the client asks for application/json then, in case of an error condition, the application should still return a response body encoded with application/json.

The other important implementation detail is that a ModelAndView is returned – this is the body of the response and it will allow the application to set whatever is necessary on it.

This approach is a consistent and easily configurable mechanism for the error handling of a Spring REST Service. It is does however have limitations: it’s interacting with the low level HtttpServletResponse and it fits into the old MVC model which uses ModelAndView – so there’s still room for improvement.

4. Via new @ControllerAdvice (Spring 3.2 Only)

Spring 3.2 brings support for a global @ExceptionHandler with the new @ControllerAdvice annotation. This enables a mechanism that breaks away from the older MVC model and makes use of ResponseEntity along with the type safety and flexibility of @ExceptionHandler:

The new annotation allows the multiple scattered @ExceptionHandler from before to be consolidated into a single, global error handling component.

The actual mechanism is extremely simple but also very flexible:

it allows full control over the body of the response as well as the status code

it allows mapping of several exceptions to the same method, to be handled together

it makes good use of the newer RESTful ResposeEntity response

5. Conclusion

This tutorial discussed several ways to implement an exception handling mechanism for a REST API in Spring, starting with the older mechanism and continuing with the new Spring 3.2 support. For a full implementation of these exception handling mechanisms working in a real-world REST Service, check out the github project.

Newsletter

Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

Email address:

Join Us

With 1,240,600 monthly unique visitors and over 500 authors we are placed among the top Java related sites around. Constantly being on the lookout for partners; we encourage you to join us. So If you have a blog with unique and interesting content then you should check out our JCG partners program. You can also be a guest writer for Java Code Geeks and hone your writing skills!

Disclaimer

All trademarks and registered trademarks appearing on Examples Java Code Geeks are the property of their respective owners. Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries. Examples Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.