Reputation: 10580
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
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 anexception-type
fits using the class-hierarchy match, and the exception thrown is aServletException
or subclass thereof, the container extracts the wrapped exception, as defined by theServletException.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
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