Improve Your Spring REST API, Part II

In the previous blog post, I explained how a custom @ExceptionHandler can be used to return feedback to REST API clients when they are submitting erroneous requests. However, the suggested implementation does not scale, because an @ExceptionHandler method is only applicable for a specific controller. In a real project, it is likely that we would like consistent error handling across multiple controllers. The easiest way to overcome this problem is to create a common super class that can be extended by all other controllers. To create a more generic solution to the problem, we can look under the hood of Spring itself and get inspired.

Edit

Feb 3rd, 2013: The @ControllerAdvice and the ResponseEntityExceptionHandler in the Spring 3.2 release effectively obsoletes the implementation below. Please read the updated solution in next blog unless you are stuck with an older version of Spring.

Goal

The intent of this blog post is to implement a custom HandlerExceptionResolver that in addition to the HTTP status codes also writes useful data to the response body when an exception occurs. The idea is to create a pluggable solution that generates error messages consistently by reusing the ErrorMessage class introduced in the previos blog post. The content of an error message depends on the specific exception and it should be derived by implementing a factory interface:

Spring Classes

Before getting to work, there are a couple of Spring classes that we need to get acquainted with:

DefaultHandlerExceptionResolver

Like many other Spring classes, the DefaultHandlerExceptionResolver has a long and rather self explanatory name. Its purpose as quoted from the javadoc:

Default implementation of the HandlerExceptionResolver interface that resolves standard Spring exceptions and translates them to corresponding HTTP status codes.
This exception resolver is enabled by default in the org.springframework.web.servlet.DispatcherServlet.

Take a look at the implementation of its doResolveException() method available at GitHub. As can be seen, it delegates to the many handle*() methods depending on the type of exception that occurs, and then the HTTP Status code is assigned accordingly. Both the doResolveException() method and all handle*() methods are protected which means that here is an opportunity to extend the class and provide alternative implementations. This also suggests that any subclass should be specific about which handle methods to override, which makes it less suitable for a generic solution.

AnnotationMethodHandlerExceptionResolver

Have you ever wondered what makes a custom @ExceptionHandler method tick? The implementation is handled by the AnnotationMethodHandlerExceptionResolver. In contrast to the previously mentioned DefaultHandlerExceptionResolver, it is able to serialize return values annotated with the @ResponseBody into the HTTP response body, something that will be necessary for our project at hand. A closer look at the handleResponseBody() method at GitHub reveals the implementation details.

Custom HandlerExceptionResolver

Another observation of the DefaultHandlerExceptionResolver and the AnnotationMethodHandlerExceptionResolver classes is that they extend the same parent class, namely the AbstractHandlerExceptionResolver. With this knowledge, we can implement a custom ErrorMessageHandlerExceptionResolver:

Implementation Comments

  • The setOrder() method is called by the constructor. The AbstractHandlerExceptionResolver implements the Ordered interface that Spring uses to prioritize between different exception handlers if there is more than one implementation in the current application context.
  • The setErrorMessageFactories() is where the different ErrorMessageFactorys are supplied.
  • The setMessageConverters() is used to provide the necessary HttpMessageConverters needed for the serialization of the ErrorMessages.

ErrorMessageFactory implementations

Now, we create different implementations of the ErrorMessageFactory interface for various exceptions. For example, the @ExceptionHandler for the MethodArgumentNotValidException that was implemented in the previous blog post can be implemented as an MethodArgumentNotValidExceptionErrorMessageFactory:

Other examples include a HttpMediaTypeNotSupportedExceptionErrorMessageFactory for generating error messages for unsupported media types and a HttpMessageNotReadableExceptionErrorMessageFactory for cases when the reading of a request message body fails, e.g. due to a parse exception. These are just some examples, it is easy to implement more factories if necessary.

Putting it together

The last piece of the solution is to create a WebApplicationContext in which the ErrorMessageHandlerExceptionResolver bean, the ErrorMessageFactory beans and the HttpMessageConverters are wired together. Several options are available, e.g. Java based configuration, adding @Component and @Autowire annotations (or their JSR-330 counterparts) to the provided snippets and let component scanning take care of the rest, or to use the more traditional XML based configuration. The choice is not different from any other Spring MVC project configuration, it is just a matter of personal preference.

Future Improvements

The suggested solution is based on Spring 3.1, and it is very likely that the suggested solution will be obsoleted by the Spring 3.2 release. Spring has also recognized the advantages of returning a response body in conjunction with an HTTP error code. Issue SPR-8406 – Create separate handler stereotype for RESTful web services in the Spring Jira addresses the problem, a solution based on the new ResponseEntityExceptionHandler class and the new @ControllerAdvice annotation has been implemented and is available as part of the Spring 3.2 M2 release.

Dependencies

  • Spring 3.1.2.RELEASE
  • jackson-databind 2.0.5

References

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 3 Comments

  1. Hi Mattias,

    Could you please provide an application based on Spring 3.2 and REST services with the following
    1) REST service to expose some data in XML and Json format
    2) Secure the REST service using SSL certificates or any other mechanism
    3)Exposing a Javabean or ArrayList in XML
    4) How to consume the REST service if it contains an object like ArrayList or ResultSet etc

    I have experience consuming REST service(using Ajax calls or Apache Abdera etc) but never have created one!

    If you dont have time to do this then if you can spend some time and guide me then I would be happy to develop this as well and you can post it in your site! And I am sure there are lot of guys learning REST services will appreciate this a lot!

    Thanks!

    1. Hi Pap,

      It is quite a lot that you ask for, especially for a blog post. However, there are several resources online that you can look at, for example Josh Long (Spring Developer Advocate) posted a webinar on Youtube the other day entitled Building REST-ful services with Spring which deals with Bean Config, REST, Security, etc. Some other links that you may find interesting are @EnableWebMvc or <mvc:annotation-driven /> for XML and JSON serialization, the Spring Security project for securing the application, @ResponseBody or HttpEntity for message serialization, and RestTemplate for consuming a REST service.

Leave a Reply

Close Menu