bluefoot
bluefoot

Reputation: 10580

Error Handler Servlet: how to get exception cause

I have an error servlet configured in my web.xml:

<error-page>
    <exception-type>java.lang.Exception</exception-type>
    <location>/ExceptionHandler</location>
</error-page>

right?

In my (generically) servlet:

doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        ...
        ...
    } catch (Exception e) {
        throw new ServletException("some mesage", e);
    }
}

so, "e" will be the root cause in this case.

In my ExceptionHandler class, I have:

doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Throwable throwable = (Throwable) request.getAttribute("javax.servlet.error.exception");
    throwable.getCause() //NULL
}

this is the problem. throwable.getCause() is null.

Upvotes: 14

Views: 27318

Answers (2)

BalusC
BalusC

Reputation: 1109625

If the exception caught by the servletcontainer is a ServletException and the <error-page> is declared to catch an exception other than ServletException, then its cause will actually be unwrapped and stored as "javax.servlet.error.exception". So you basically already have it as throwable variable and you don't need to call getCause() on it.

See also 5th paragraph of chapter 9.9.2 of Servlet 2.5 specification:

If no error-page declaration containing an exception-type fits using the class-hierarchy match, and the exception thrown is a ServletException or subclass thereof, the container extracts the wrapped exception, as defined by the ServletException.getRootCause method. A second pass is made over the error page declarations, again attempting the match against the error page declarations, but using the wrapped exception instead.

By the way, it's better to use the RequestDispatcher#ERROR_EXCEPTION constant instead of hardcoding it.

Throwable throwable = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);

Upvotes: 26

Neeme Praks
Neeme Praks

Reputation: 9150

EDITED.

Ok, this might be wrong, I do not have personal experience with error handling servlets: Instead of getCause(), add an instanceof check for ServletException, if it passes, cast your Throwable to ServletException and use getRootCause(). (BalusC seems to have a better solution, for newer Servlet API versions)

See Exceptions Without Root Cause for in-depth discussion.

Newer Servlet API versions do not have this issue, but if you are using some old version (2.4 or older) you should also update your ServletException throwing code:

doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        ...
        ...
    } catch (Exception e) {
        ServletException se = new ServletException(e.getMessage(), e);
        se.initCause(e);
        throw se;
    }
}

Upvotes: -2

Related Questions