To read Part 2 in this series, click here
New to Spring MVC ?
or maybe you’re experienced ?
or maybe you have just used it a bit, you know, here and there.
Whatever the case, Spring MVC can cater for anyones web development appetite, if it be a simple site using the defaults, or a complex custom configuration utilizing local resolvers, custom handler mappers, and various view resolvers for jstl, freemarker and pdf.
In this post I would like to talk specifically about handling exceptions in your Spring web based application and different ways you can cater for the unexpected (although, if you plan for the unexpected aren’t you then expecting and thus planning for the expected?). Exceptions can occur throughout your application, from your domain layer to your web controllers, and handling them correctly is very important for everyone involved, especially the person on the end of the browser using the application.
As to keep this post readable, as I waffle a bit, I have broken it up into a few different posts, most likely two (but I will see how I go), so I can discuss what you get out of the box with a servlet container, Springs pre-made offerings, and options for building your own and customization.
web.xml and the servlet container
If you are familiar with the servlet spec you will already know that servlet containers can handle exceptions and error codes, all with just a simple declaration within your web.xml. This declaration can look something like this:
Ok then, well, if the servlet container can handle the exceptions (and error codes), why do we need to bother setting up Spring to handle them? Well, there are some good reasons why, but before I explain them I need to explain the difference between an ‘error code’ and exception.
Error codes, or status codes as they are better known, are part of the http rfc spec and are not treated as an exception, per se. Spring does not catch error codes, in fact, it can’t, it can write error codes by calling response.sendError but does not catch them as they are only handled by the servlet container. Some well known status codes include 404 (page not found), 408 (request time-out), 500 (internal server error) and 503 (service unavailable). Status codes can either be caught and handled by the servlet container, which happens in most cases, and have a pretty html page served to the client, or a response can be sent which just contains the status code leaving the client (web browser) to display a page or message to the person on the other end of it. This is not new information, and it is fair to say that since Spring can not handle error codes being raised (as in some cases Spring will be raising them), the web.xml is the best place to handle these error codes.
So then, if web.xml is handling our error codes, why not let it handle our exceptions as well? There are some good reasons (as mentioned before) and they are :
- Filters are by-passed – This was a problem which appeared in a development another team was working on in my organization. Sitemesh decorates the pages by working as a servlet filter, if the application came upon an error code or exception, the servlet container would by-pass the filters and just render the jsp. In Spring this would not happen as it would catch the exception and not let it propagate up to the servlet container.
- Reference Data - Since the servlet container will just render a page, it will not allow for business logic to run, for example, not populate the model with some reference data.
- Logging and Auditing - Again, since only a page is rendered no extra logging, auditing or notifcation can be added cleanly.
- and last of all, generally these are Application exceptions and should be handled by the application not a third party.
It sounds like I am advocating Spring should do everything and you should just let the web.xml do only what Spring can’t. Well, thats a combination of yes and no, both Spring and the servlet container need to work together to handle status codes and exceptions properly, but it is also important that each should be used to capture errors and exceptions which they are responsible for.
handling exceptions in Spring
When you declare a DispatcherServlet you get several components out of the box, for example you get a bean name handler mapper, an annotation handler mapper, three or four handler adapters and a view resolver, to name a few of them.
One thing you don’t get is a HandlerExceptionResolver set up for you, but it only takes a second to set one up.
If you’re familiar with the workflow involved with handling a request, you will know that a try catch block surrounds the HandleAdapter method handle in the DispatcherServlets doDispatch method. If an exception occurs the DispatcherServlet will call processHandlerException which will then see if a HandlerExceptionResolver is registered. You can have any number of HandlerExceptionResolvers registered, be it one (which suits for most cases), two, 10, or more, and because they implement the Ordered interface you get to decide which one gets the chance to try and handle the exception first.
The HandlerExceptionResolver is an interface which contains only one method :
ModelAndView resolveException(HttpServletRequest request,
Spring is nice enough to give you a simple implementation which should be of use to most applications from the get go, its a simple exception resolver (SimpleMappingExceptionResolver) which maps exception types to error pages. Its configuration looks something like :
<entry key="DataAccessException" value="data-error"/>
<property name="defaultErrorView" value="general-error" />
As you can see all you need to do is create a list of exception types and link them to error pages, a very similar setup to SimpleUrlHandlerMapping.
The SimpleMappingExceptionResolver is a nice stable basic implementation which provides a good solid foundation for building and extending upon. In fact, the Spring team themselves recommend this as they provide many hooks for doing so. This is my first recommendation, use the SimpleMappingExceptionResolver in some shape or form, if it be for your main exception resolver or for extending upon, it provides a good solid base to work from and is very functional.
a quick summary
So far we know that the web.xml can do some things Spring can’t, like catch 404 or 500 status codes, but Spring on the other hand provides a HandlerExceptionResolver implementation which exposes many hooks ready for extension. Should one be used over another, no, should they be used together, well, yes, but its about using them together correctly, a topic I would like to leave until my next post, including possible ways to extend the SimpleMappingExceptionResolver, as this one is getting a bit long.
Thanks for reading
To read Part 2 in this series, click here