HandlerExceptionResolvers


In the beginning of this chapter we reviewed the single method specified on the Controller interface:

public ModelAndView handle(   HttpServletRequest request, HttpServletResponse response) throws Exception;

As you can see, while implementing this method, you can throw any exception you like. We've chosen to allow this — like most other web application frameworks — because we don't want to limit you while implementing controllers and force you to throw a Spring-specific exception. This does not mean that we regard declaring methods in your application to throw Exception as a good practice.

Important 

The handle method throws a java.lang.Exception. Good IDEs offer support for automatically overriding methods from a superclass and, while doing this, they often include the throws clause from the overridden method. Remember that you can, and normally should, narrow the throws clause for such a method. This is generally a good thing to do because it prevents you from throwing unspecified checked exceptions (if java.lang.Exception is not mentioned in the throws clause, compilation will fail). Second, including specific exceptions you throw in the throws clause of the method automatically documents your controllers. When reviewing the JavaDoc, for example, you can then easily collect information about all exceptions thrown from controllers, which will be useful in applying a consistent policy for dealing with them.

Imagine a controller that has to reserve a seat for us in the performance venue. It's a simple controller that takes a request parameter identifying the show. It uses a service object to look up the show and throws a ShowNotFoundException if the show does not exist. In other words, the method signature of the controller looks like this (assuming the developer who wrote this code has correctly narrowed down the throws clause of the method):

protected ModelAndView handleRequestInternal(   HttpServletRequest request, HttpServletResponse response) throws ShowNotFoundException;

Maybe you can imagine that in other controllers, similar error conditions might arise where ShowNotFoundExceptions are also thrown. Because we probably want to deal with the error in the same way in our entire application, it's a good idea to separate the error handling from the throwing of the error itself.

Spring offers HandlerExceptionResolvers that allow for controller-independent behavior when an exception is thrown. HandlerExceptionResolvers, just as LocaleResolvers, MultipartResolvers, HandlerMappings, and some of Spring Web MVC's other infrastructural components are automatically picked up by the DispatcherServlet. The HandlerExceptionResolver offers one method:

ModelAndView resolveException(   HttpServletRequest request, HttpServletResponse response,   Object handler, Exception ex); 

Note that this method is not allowed to throw an exception. The handler argument represents the controller or interceptor from which the exception originated and the exception is also passed to the method.

Of course, you can implement a HandlerExceptionResolver yourself, offering custom behavior when an exception is thrown, but before doing that, first have a look at the Spring SimpleMappingExceptionResolver. It offers you parameters to specify the status code and also can include the exception in the model while redirecting to a specific view that should be rendered.

Let's configure the SimpleMappingExceptionResolver. We'll of course begin with the class name:

 <bean     > 

We'll first set up the exceptionMapping. This is a properties object that contains class name patterns and view names. If the class name of the exception thrown matches the specified pattern, the corresponding view name will be used. The pattern does not support wildcards — merely a substring matching the class name. Therefore, you have to carefully think about what pattern you're going to use. Using "Exception" as the pattern will almost always match, as exceptions tend to have this string in their class name. Of course, using the FQCN is also possible and will always produce the expected result. In the following example, a ShowNotFoundException will result in the shownotfound logical view name being used.

 <property name="exceptionMapping">   <props>     <prop key="ShowNotFoundException">       <value>showNotFound</value>     </prop>   </props> </property> 

Next, we'll tell the resolver to include the exception in the model. The exception attribute is customizable. All of this, by the way, resembles the error handling mechanism offered by the Servlet specification. The difference is that it's more tailored to the environment you're developing your web application in. For instance, it gives you access to the object (handler) the exception originated from.

 <property name="exceptionAttribute">   <value>showNotFoundException</value> </property> 

We'll also set the status code. This is the response code the client will get if an exception is thrown. Furthermore, we'll set the default error view. If none of the mapped patterns matches the class name of the exception thrown, this is the view name that will be used, as some kind of a last resort.

   <property name="statusCode"><value>500</value></property>   <property name="defaultErrorView"><value>genericError</value></property> </bean> 

Providing two error JSPs (or Velocity templates, FreeMarker macros, or Excel views if that's what you like) is the last thing we need to do. We'll show you one here:

# /WEB-INF/jsp/showNotFound.jsp      <h1>Ooops, an exception has occurred</h1> <p>   It seems you have selected a show that does not exist (anymore).       Just to be sure, we’ll   <c:out value="${showNotFoundException.message}"/> </p>

The last thing you need to know about the HandlerExceptionResolvers is that you can add more than one of them to your application context, and order them, using the order property. The SimpleMappingExceptionResolver adds an additional feature in case you define multiple resolvers: the mappedHandlers property, which is a collection of all handlers this exception resolver should be applied to. If the mappedHandlers property is not set, it will apply to all handlers in your application. This feature is especially useful in a complex application where multiple HandlerMappings are used. Generally, one exception resolver is tied to one handler mapping.

Important 

You should be able to see the consistency in Spring MVC's overall approach to extension points such as exception resolves, view resolvers, and so forth. The Spring project probably places more emphasis on consistency than any other application framework: partly the result of Spring's genesis from Expert One-on-One J2EE Design and Development, which provided a consistent overall vision, but also due in large part to the thoroughness of Spring co-lead Juergen Hoeller, who always strives for consistent naming and usage patterns throughout the framework.

This consistency will benefit you as you work with all parts of the framework — for example, by enabling you to build on the Spring understanding you've previously gained as you come to grips with framework features that are new to you.



Professional Java Development with the Spring Framework
Professional Java Development with the Spring Framework
ISBN: 0764574833
EAN: 2147483647
Year: 2003
Pages: 188

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net