To handle any exceptions thrown outside your flow you need to implement a Spring MVC exception resolver (or several resolvers if you have the need to handle some error cases distinctly) and register it (them) in your servlet XML.
1) In your-app-servlet.xml, add the following definition:
Code:
<!--
insert any exception resolver definitions for more specific exceptions
if you need to distinctly handle some specific cases; the lower the
order property value, the higher the handler's precedence
-->
<!-- Generic system/programming error resolver that handles the rest of the exceptions not handled by the app; it must have the highest order -->
<bean id="genericErrorHandler" class="com.yourcompany.yourapp.whatever.exceptionresolvers.SystemErrorResolver">
<property name="order" value="10"/>
</bean>
Exceptions that are thrown during the request processing and not caught anywhere else go to the hander exception resolver chain. Spring looks at all registered handler exception resolvers (beans that implement the appropriate HandlerExceptionResolver interface) in the application context. Any instances that implement the Ordered interface are sorted (lowest order first), and others are added at the end of the list. (per Spring documentation.)
2) Implement the exception resolver class. Here's an example of the ultimate resolver that handles all previously uncaught system errors and displays the standard system error view.
Code:
package com.yourcompany.yourapp.whatever.exceptionresolvers;
import org.apache.log4j.Logger;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* This class implements an exception resolver that redirects to the designated error view in cases of any exceptions that
* <i>have not been previously caught and handled</i> by the application or framework (including any Spring Webflow error
* handlers registered with the application).
*/
public class SystemErrorResolver implements HandlerExceptionResolver, Ordered {
private static final String ERROR_VIEW = "yourerrorpage";
private int order; // prioritization order number for this Ordered object
private static final Logger logger = Logger.getLogger(SystemErrorResolver.class);
private static final String ERR_MESSAGE =
"Unrecoverable error occurred in the application. See the nested exception stack trace for details. Redirecting to the Error View.";
/** {@inheritDoc} */
public ModelAndView resolveException(HttpServletRequest req, HttpServletResponse response, Object handler,
Exception e) {
// return the Error Page view in case of any unhandled exception
if (e != null) {
logger.error(ERR_MESSAGE, e); // log msg and complete error stack trace
return new ModelAndView(ERROR_VIEW);
} else {
return null;
}
}
/** {@inheritDoc} */
public int getOrder() {
return order;
}
/**
* Sets the prioritization order number for this Ordered object.
*
* @param num order number
*/
public void setOrder(int num) {
this.order = num;
}
This is the error resolver for all exceptions that should not - and must not - be caught anywhere else. The only exceptions that must be caught and handled by the application individually are the ones that have specific use cases associated with them. To ensure that all your errors correctly propagate to the designated handler(s) - unaltered! - use runtime exceptions. Checked exceptions are nothing more than glorified error codes that force programmers to mishandle errors before they reach the only place in the application that knows how to handle them properly. Runtime exceptions ensure the exact behavior the exceptions mechanism was invented for: instantly unwind the call stack all the way from the source of the error to the designated handler. It is the job of the programmer to decide where to place such handlers, not the job of the compiler. What to handle and how is dictated by the application requirements only - and nothing else. It was a horrible idea to suggest that the compiler should be advising on error handling.
So, once you have implemented your SWF and Spring MVC resolvers, use RT exceptions (wrap any JDK and 3rd party checked exceptions into your custom RTEs) and they will be caught and handled by these resolvers. You won't have to do anything else. In other words, throughout your application, you only need to worry about throwing new exceptions when it is appropriate (i.e. when wrapping annoying checked exceptions that you can't handle immediately at their source) and never worry about catching and handling them - since you already have registered the handlers that will do their job - as long as the errors are not intercepted (by incorrect code and a use of checked exceptions.)
HTH,
Constantine