20030619 Thursday June 19, 2003

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. Posted in Java at Jun 19 2003, 05:55:20 PM MDT 3 Comments

Comments:

What was wrong with using the built-in ExceptionHandler rather than writing your own? I'd recommend using the built-in one if you can.

Posted by Erik Hatcher on June 19, 2003 at 06:17 PM MDT #

The problem I have with the built-in one is that it doesn't support chained exceptions. Rather it will only grab the message from the top-most exception. My chained exceptions implementation is derived from From Ted Husted's use chained exceptions tip. By doing this, the error displayed will not be simply, "Could not connect to database.", but rather:

* Could not connect to database.
* Cannot connect to MySQL server localhost:3307. Is there a MySQL
  server running the machine/port you are trying to connect to? 
  (java.net.ConnectException)

This gives the user the generic user-friendly message they desire (the first one), and also allows the support team to realize exactly what went wrong.

Posted by Matt Raible on June 19, 2003 at 06:43 PM MDT #

Ah.... gotcha. I don't want that much detail shown to our users though. Its just our own ValidationExceptions that get thrown to pages this way. If our SystemException happens, we bounce to error.jsp which has the full stack trace shown in an HTML comment.

Posted by Erik Hatcher on June 19, 2003 at 07:16 PM MDT #

Post a Comment:
  • HTML Syntax: Allowed
Click me to subscribe
Matt Raible is a Web Architecture Consultant specializing in open source frameworks.
« May 2012
SunMonTueWedThuFriSat
  
1
2
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
23
24
25
26
27
28
29
30
31
  
       
Today

Recent Entries

Tag Cloud