We have a complex web application with lots of JSPs and a considerable
amount of servlets for various purposes. Our app runs in Tomcat 5.5 and
among other custom error handling techniques we also used the Servlet
API mechanism of placing the following directive in our web.xml:


Due to the complexity of our application, it is unpredictable if the
unhandled exception occurs before or after the response has already been
committed. One example where the exception definitely occurs after the
response has been committed is a class that serves download requests. If
the user downloads a big amount of data, pressing the cancel button
while waiting for the download is normal and must be dealt with in the
server application. (Note that i'm using this only as an example, of
course the server-side errors that are caused by cancelled user requests
can be safely ignored, but this is a totally different discussion
outside the scope of this thread.)

So, here's what's happening:

- user clicks download link
- servlet starts writing (say) 100 MB of data to the response
- user grows impatient and clicks cancel
- servlet encounters a SocketException or similar because it is
  unable to write further data
- while trying to handling the error situation, tomcat calls the
  reset() method on the response. This causes an
  IllegalStateException because the servlet has already written
  and flushed the response.

According to the Servlet API, trying to "undo" a response in any way
*after* already having written physical data to the HTTP client is a
"no-no", hence the IllegalStateException. In this light, it may or may
not be OK to actually call the reset() method as is done now (talking of
Tomcat 5.5.12) in StandardHostValve.custom().

[Try googling for "StandardHostValve.custom(", the numerous results tell
you that this error situation occurs frequently out there...]

However, the mechanism of a standard error page is of somewhat meager
use for a complex application because, as the scenario above shows, it
does only work if the response is "clean" i.e. has not yet been written
to physically.

We decided to work around this as follows:

- Our JSPs will be augmented with a JavaScript redirect to
  the error page instead of the web.xml error page directive.
- Our Struts Action classes will handle all Throwables by
  redirecting to the error page
- Our servlets will handle all Throwables internally

So, effectively, no Throwable ever travels outside of the application.
(Note of course that browsers w/o JavaScript will probably see an ugly
IllegalStateException error instead of our carefully designed error
page. Since our app checks that JavaScript is enabled, this is no
problem for us.)

We're not 100% sure if our approach was actually intended by the Servlet
API gurus, so we'd like to know what others think about this and how
this issue is dealt with in other nontrivial apps.

The most important (and simple) lesson to learn probably is that if your
app once has committed data to the client, then it must find a clean
method of saying "Oops, sorry, there was a problem" *together* with the
already written data.

Any other ideas / suggestions?

Robert Graf-Waczenski
LISTSERV Maestro Core Development Team
L-Soft Germany GmbH

Knowledge is just a click away: http://www.lsoft.com/optin.html

To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to