I have a simple (Servlet, JSP, and JSTL) web app whose main functionality is displaying images retrieved from a back-end server. The controller servlet forwards the user to a JSP that in turn uses another Servlet to display the resulting image on that same JSP. Further down, the JSP has a line similar to:
<a href="<c:out value='${imageURL}'/>"><img src="<c:out value='${imageURL}'/>" alt="image view" border="1"></a>
which invokes a GET request on the image-generating servlet causing it to generate the image.
My question is: how do I handle Exceptions thrown by this image-generating servlet?
I already have an error page defined (in web.xml) to handle ServletException within my web app but this doesn't work for this image-generat开发者_C百科ing Servlet, and results in the following errors showing up in my Tomcat server logs:
SEVERE: Exception Processing ErrorPage[exceptionType=javax.servlet.ServletException, location=/WEB-INF/ExceptionPage.jsp]
java.lang.IllegalStateException: Cannot reset buffer after response has been committed
What's my recourse in this situation?
I'd like to be able to handle Exceptions thrown from this image-generating Servlet, and display some error on the main UI or forward the user to another error page.
You can't change the response to redirect to an error page while sending the response. It's already too late to change the entire response then. You can't ask those already sent bytes back from the client side. That's what the IllegalStateException
stands for here. It's a point of no return.
Best what you can do is to just log the exception, or to rewrite the code so that it doesn't write any bit to the response (also not setting the response headers) while the business logic hasn't finished its task yet. Once you've determined that the business logic didn't throw any exception, then start writing (and thus indirectly also committing) the response. If the business logic has thrown an exception while the response isn't touched yet, then you can just safely throw it through so that it ends up in an error page. Although in case of an image servlet, you may also want to stream some standard 404.gif
to the response instead. This because you can't display another HTML (error) page in an <img>
element and you also can't change the URL of the parent JSP/HTML page as well since that concerns a different request.
According to the servlet API no servlet should call the getWriter() and getOutputStream() on the same response object as it causes the IllegalStateException. Usually this is the source of this exception. If you're outputing binary data like and image file you should use getOutputStream().
Looks like the problem you have is within your ExceptionPage.jsp, not your servlet code.
And this
java.lang.IllegalStateException: Cannot reset buffer after response has been committed
Means that you've already have tried to send a response. Probably you've opened an output stream directly and wrote some data to it. Once you've done it you cannot try to set headers and such on a response ( they are already on their way to the client ).
You need to do a better state management. Best way to do this is to separate request preprocessing from the response generation. Once you are writing response, you can only do or die. For this, check that you are not catching IOExceptions from the response output, wrapping them to ServletException and redirect them to your error page. You really cannot handle them in the context of the current request.
First, identify why the Illegal State exception is being thrown. Rather than dealing with a thrown exception, you probably just want to fix your code so that it goes away.
You should catch the exception and forward the request using RequestDispatcher to the required page:
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// The following piece of code results in NumberFormatException which will
// be detected by the container. The RequestDispatcher object will forward
// the same request to the other resource, here the file: forwardedJSP.jsp
try {
int test = Integer.parseInt("abc");
} catch (NumberFormatException nfe) {
RequestDispatcher rd = request.getRequestDispatcher("/forwardedJSP.jsp");
rd.forward(request, response);
}}
精彩评论