Question

I have a web-app developed with servlet & JSP. I configured my app to throw an IllegalArgumentException if I insert bad parameters. Then I configured my web.xml file in this way:

<error-page>
    <error-code>404</error-code>
    <location>/error.jsp</location>
</error-page>
<error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/error.jsp</location>
</error-page>

When I rise a 404 error, then it works and calls error.jsp, but when I rise a java.lang.IllegalArgumentException, then it does not work and I've a blank page instead of error.jsp. Why?

The server is Glassfish, and logs show really IllegalArgumentException rised.

Was it helpful?

Solution

You should not catch and suppress it, but just let it go.

I.e. do not do:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        doSomethingWhichMayThrowException();
    } catch (IllegalArgumentException e) {
        e.printStackTrace(); // Or something else which totally suppresses the exception.
    }
}

But rather just let it go:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doSomethingWhichMayThrowException();
}

Or, if you actually intented to catch it for logging or so (I'd rather use a filter for that, but ala), then rethrow it:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        doSomethingWhichMayThrowException();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
        throw e;
    }
}

Or, if it's not an runtime exception, then rethrow it wrapped in ServletException, it will be automatically unwrapped by the container:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        doSomethingWhichMayThrowException();
    } catch (NotARuntimeException e) {
        throw new ServletException(e);
    }
}

See also:

OTHER TIPS

Another (simplified) approach is not to declare multiple handlers for various <error-code> and <exception-type> situations but rather have one, sort of catch-all sink, e.g.

<error-page>
    <location>/error-page.jsp</location>
</error-page>

Inside your error-page.jsp you can determine the cause, be it a return status code or an exception as described here: https://www.tutorialspoint.com/servlets/servlets-exception-handling.htm These constants are a part of the standard Servlet 3.0 API.

For instance a primitive error-page.jsp response handler placed into the root of your webapp can look like this:

Server encountered a situation
Status code: <%=(Integer) request.getAttribute(javax.servlet.RequestDispatcher.ERROR_STATUS_CODE)%>
<br>
Exception: <%=(Throwable) request.getAttribute(javax.servlet.RequestDispatcher.ERROR_EXCEPTION)%>

For security reasons I wouldn't recommend sending the exact exception type to the client; this is just an example of how to handle different types of errors and response statuses inside a JSP handler; a servlet can be used instead of JSP.

One common catch-all handler vs one per status code is certainly dependent on the situation and requirements.

I have today the same issue. (JavaEE 7 and Glassfish 4.0)

The problem seems that the framework check it as String instead with the Class.

String based check (the hypothesis)

When a Exception is twrown, e.getClass() is compared with <exception-type> as string. So you can't use inheritance.

Note that nested classes must be pointed as '$' instead '.' (same as getClass() method).

Class based check

The framework create an instance of the class, and <exception-type> text refer to it, and the class.isInstance() is used to check.

This will need reflection and policy file could break it.

I hope that this response solves future issues.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top