The current way Struts tags try to store the root exception is to store the
exception as a request attribute. This is done primarily in the taglib
because the tags must all throw JspException which doesn't allow for a
nested or root exception to be stored along with the message. My concern
with the exceptions being put in the request object is that they can get
overwritten when tags are nested.

Couldn't we extend JspException and throw that instead and pass the
exception that caused the problem as an optional argument to the
constructor? That would make it behave like ServletException. When the
exception was eventually caught the error handling code could call
getRootCause() on all ServletExceptions or "StrutsJspExceptions". This would
involve looping through exceptions because the nesting could be n levels
deep. This code would be application specific. Changing cases of throw
JspExeption to throw StrutsJspException would involve lots of modifications
to the code but they would be straightforward and I don't think it would
break anything as long as the code that puts the exception in the request
was left alone.

Below are a couple of the many examples where JspExceptions are caught and
re-thrown and in one example put in the request object. I also included a
possible implementation of StrutsJspException. Am I off base? Am I missing
something? I would like to hear some feedback about whether this is
something worth doing or why it isn't necessary.

Thanks, Hal

>From Action.java:
/**
  * The request attributes key under which Struts custom tags might store
  * a <code>Throwable</code> that caused them to report a JspException at
  * runtime.  This value can be used on an error page to provide more
  * detailed information about what really went wrong.
  */
public static final String EXCEPTION_KEY =
"org.apache.struts.action.EXCEPTION";

>From Include.java
        // Include the contents of the corresponding actual page
        try {
            pageContext.include(forward.getPath());
        } catch (Exception e) {
            throw new JspException
                (messages.getMessage("includeTag.include",
                                     name, e.toString()));
        }

>From IncludeTag.java
        URLConnection conn = null;
        try {
            conn = url.openConnection();
            conn.setAllowUserInteraction(false);
            conn.setDoInput(true);
            conn.setDoOutput(false);
            conn.connect();
        } catch (Exception e) {
            pageContext.setAttribute(Action.EXCEPTION_KEY, e,
                                     PageContext.REQUEST_SCOPE);
            throw new JspException
                (messages.getMessage("include.open",
                                     url.toString(), e.toString()));
        }

File: StrutsJspException.java
/****************************************************************
 * org.apache.struts.util.StrutsJspException                    *
 *                                                              *
 ****************************************************************/
package org.apache.struts.util;

import javax.servlet.jsp.JspException;

public class StrutsJspException extends JspException
{
    /**
     * Nested error
     */
    private Throwable nested;

    /**
     * Constructor
     */
    public StrutsJspException()
    {
    }

    /**
     * Constructor
     *
     * @param nested Exception from actual Exception
     */
    public StrutsJspException(Throwable nested)
    {
        this.nested = nested;
    }

    /**
     * Constructor
     *
     * @param s Description of error
     * @param nested Exception from actual Exception
     */
    public StrutsJspException(String s, Throwable nested)
    {
        super(s);
        this.nested = nested;
    }

    /**
     * Constructor
     *
     * @param s Description of error
     */
    public StrutsJspException(String s)
    {
        super(s);
    }

    /**
     * Retrieves nested error
     *
     * @return Nested error message
     */
    public Throwable getRootCause()
    {
        return nested;
    }
}

Reply via email to