Using Struts' Declared Exceptions
With a little prodding from Erik Hatcher today, I took another look at Struts' Declared Exceptions feature. At the end of last year, I was wishing I could use declared exceptions to do chained exceptions for my Action classes. Basically, in each of my Actions, I have a try/catch wrapped around a call to the Business Delegate (example: UserAction.java). You'll notice that all the CRUD methods have the same catch block for exception handling:
} catch (Exception e) {
e.printStackTrace();
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("errors.general"));
while (e != null) {
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("errors.detail", e.getMessage()));
e = (Exception) e.getCause();
}
saveErrors(request, errors);
return mapping.getInputForward();
}
After talking with Erik this morning, I decided to create an ActionExceptionHandler for java.lang.Exception. In my struts-config.xml, I added:
<exception type="java.lang.Exception" key="errors.general"
handler="org.appfuse.webapp.action.ActionExceptionHandler"/>
I have "errors.general=The process did not complete. Details should follow." Here is the code for ActionExceptionHandler:
public final class ActionExceptionHandler extends ExceptionHandler { public ActionForward execute(Exception ex, ExceptionConfig ae, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request, HttpServletResponse response) throws ServletException { ActionForward forward = null; ActionError error = null; ActionErrors errors = new ActionErrors(); String property = null; // Build the forward from the exception mapping if it exists // or from the form input if (ae.getPath() != null) { forward = new ActionForward(ae.getPath()); } else { forward = mapping.getInputForward(); } ex.printStackTrace(); errors.add(ActionErrors.GLOBAL_ERROR, new ActionError(error.getKey())); while (ex != null) { errors.add(ActionErrors.GLOBAL_ERROR, new ActionError("errors.detail", ex.getMessage())); ex = (Exception) ex.getCause(); } // Store the errors and exception request.setAttribute(Globals.ERROR_KEY, errors); return forward; } }
This allows me to remove my generic try/catches from my action classes - very slick IMO (or at least better than the code smell I had)! Of course, I still have some catch blocks that catch specific exceptions, but I can either (1) leave those intact, or (2) create another declared exception for that particular action/exception. I dig it and will be adding it (in short order) to AppFuse.
Update (June 23, 2003): Here's a more thoroughly tested code sample of this same class.


. It's pretty easy to setup and offers a nice google-like search interface. I recently added