Lives in the UK. Likes blogging, cycling and eating lemon drizzle cake. Roger is a DZone MVB and is not an employee of DZone and has posted 142 posts at DZone. You can read more from them at their website. View Full User Profile

Using Spring's SimpleMappingExceptionHandler

02.21.2012
| 8933 views |
  • submit to reddit
My last few blogs have talked about Spring’s @ExceptionHandler annotation and how you can use it to deal with errors on a controller by controller basis to give you fine-grained control over how you handle errors in your code. The question to consider now is whether or not you always want such fine grained control, to which I’m guessing that in certain circumstances the answer will be no, and so to accommodate this Spring have provided us with the SimpleMappingExceptionHandler.

The SimpleMappingExceptionHandler is an implementation of Springs HandlerExceptionResolver class, which, as I’ve mentioned before, Spring uses to manage exceptions thrown by your code. Spring has a limitation (if that’s what it is) in that it only loads one HandlerExceptionResolver implementation at any one time. The default implementation is AnnotationMethodHandlerExceptionResolver as mentioned in my previous blogs, which forces you to make a choice between using fine-grained exception handling as provided by AnnotationMethodHandlerExceptionResolver and more coarse grain exception handling provided by SimpleMappingExceptionHandler.

The Guy’s at Spring have made adding a SimpleMappingExceptionHandler to your app fairly straight forward. To demonstrate this I first of all need a flakey controller that will throw an exception for us. The code below, lifted from my previous blog, throws an IOException when called...

  @RequestMapping(value = "/ioexception", method = RequestMethod.GET)
  public String throwAnIOException(Locale locale, Model model)
      throws IOException {

    logger.info("This will throw an IOException");

    boolean throwException = true;

    if (throwException) {
      throw new IOException("This is my IOException");
    }

    return "home";
  }

...and is guaranteed to break a webapp1

If you were intending to keep things ultra-simple, the final step would be to add the following XML to your Spring config file:

 <beans:bean id="exceptionResolver"
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
  <beans:property name="exceptionMappings">
   <beans:map>
    <beans:entry key="java.io.IOException" value="io-exception" />
    <beans:entry key="java.lang.Exception" value="generic-error" />
   </beans:map>
  </beans:property>
 </beans:bean>

The XML above shows a very familiar Spring bean definition. The bean name is “exceptionResolver”, implemented by the SimpleMappingExceptionResolver class. This class has a map property, which is the most interesting part of this definition as it maps an exception class to a view name. In the sample I’m mapping IOException to a view called ‘io-exception’ and all other exceptions to a view called ‘generic-error’. Note that SimpleMappingExceptionHandler follows the standard Java exception handling rules, so when I say ‘all other exceptions’ I really mean all exceptions except IOException and its subclasses.

Although that about wraps it up for a trivial implementation. I’d like to add that I prefer to extend SimpleMappingExceptionHandler so that I can add in additional functionality, such as application specific error logging:

public class SampleExceptionHandler extends SimpleMappingExceptionResolver {

  private static final Logger logger = LoggerFactory.getLogger(SampleExceptionHandler.class);

  /**
   * Log the exception.
   *
   * @see org.springframework.web.servlet.handler.SimpleMappingExceptionResolver#doResolveException(javax.servlet.http.HttpServletRequest,
   *      javax.servlet.http.HttpServletResponse, java.lang.Object,
   *      java.lang.Exception)
   */
  @Override
  protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
      Exception ex) {
    logger.error("A " + ex.getClass().getSimpleName() + " has occured in the application", ex);

    return super.doResolveException(request, response, handler, ex);
  }

}

Once you’ve written your own exception handler, then all you have to do is to modify your Spring config so that it’s picked up by Spring when the webapp loads:

<!-- Definition(s) for the SimpleMappingExceptionResolver -->
 <beans:bean id="exceptionResolver"
  class="com.captaindebug.exceptions.SampleExceptionHandler">
  <beans:property name="exceptionMappings">
   <beans:map>
    <beans:entry key="java.io.IOException" value="io-exception" />
    <beans:entry key="java.lang.Exception" value="generic-error" />
   </beans:map>
  </beans:property>
 </beans:bean>



1 The full code for this blog is available from:

git://github.com/roghughe/captaindebug.git

 

 

From http://www.captaindebug.com/2012/02/using-springs-simplemappingexceptionhan.html

Published at DZone with permission of Roger Hughes, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags: