tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Alex Cruikshank <a...@epitonic.com>
Subject [PATCH] JSP Exception handling after buffer flush
Date Thu, 30 Dec 1999 22:51:23 GMT
Currently, when a JSP page throws an Exception after the JspWriter's buffer 
has been flushed (after 8192 characters in the default configuration), one 
of two things happen:

1) If no error page exists, it will throw a new ServletException that wraps 
the original exception.  This would be fine, except that the 
ServletException is caught and displayed (as a stack trace) to the user by 
ServletWrapper (which BTW seems to need a lot of work) without ever 
displaying or logging the underlying exception.

2) If an error page exists, the page tries to forward to it.  Since the 
buffer has already been flushed, it throws a IllegalStateException.  The 
ISE is also caught and displayed to the user by ServletWrapper, and the 
underlying exception still goes unreported.

Three things are wrong with both these scenarios:  The actual page 
exception (and its stack trace info) is suppressed by the error trying to 
handle the exception (making debugging extremely difficult).  No trace of 
either of the errors is left on the server (good luck trying to get debug 
info from the end user).  And the end user gets to see a nasty stack trace 
which only serves to make the programmers look bad.

Granted, this behavior is entirely according to specification, but that 
doesn't mean that it is acceptable.  Since part of the page has already 
been sent to the page, there aren't a lot of good options.  It's no longer 
possible to forward or redirect to an error page, and the exception likely 
occurred in the middle of an HTML table, so there's no guarantee that a 
message sent to the user will even be seen.   Nonetheless, It should 
recover better than it does, so I propose the following changes to the page 
logic.  In the case where handleException throws an exception, a simple 
"ERROR in page" message should be sent to the user, and both the page 
exception and the new exception should be logged (Using the 
GenericServlet.log() method until something better comes along):

Index: JspParseEventListener.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-tomcat/src/share/org/apache/jasper/compiler/JspParse 
EventListener.java,v
retrieving revision 1.5
diff -u -r1.5 JspParseEventListener.java
--- JspParseEventListener.java  1999/12/21 16:32:31     1.5
+++ JspParseEventListener.java  1999/12/30 21:54:49
@@ -313,10 +313,34 @@
      //writer.println("} catch (Throwable t) {");
      writer.println("} catch (Exception ex) {");
      writer.pushIndent();
-    writer.println("if (out.getBufferSize() != 0)");
-    writer.pushIndent(); writer.println("out.clear();"); writer.popIndent();
-    writer.println("pageContext.handlePageException(ex);");
-    writer.popIndent();
+    writer.println( "try" );
+    writer.println( "{" );
+    writer.pushIndent(); writer.println("if (out.getBufferSize() != 0)");
+    writer.pushIndent(); writer.println("out.clear();"); writer.popIndent();
+    writer.println("pageContext.handlePageException(ex);");
+    writer.popIndent();
+    writer.println( "} catch (ServletException se) {" );
+    writer.pushIndent();
+    writer.println( "out.println( \""
+        + Constants.getString( "jsp.message.error_in_page" )
+        + "\" + ex.getMessage() );" );
+    writer.println( "log( \""
+        + Constants.getString("jsp.message.error_in_page") + "\", ex);" );
+    writer.println( "log( \""
+        + Constants.getString("jsp.error.se_from_handle_ex") + "\", se );" );
+    writer.popIndent();
+    writer.println( "} catch ( IllegalStateException ise ) {" );
+    writer.pushIndent();
+    writer.println( "out.println( \""
+        + Constants.getString( "jsp.message.error_in_page" )
+        + "\" + ex.getMessage() );" );
+    writer.println( "log( \""
+        + Constants.getString("jsp.message.error_in_page") + "\", ex);" );
+    writer.println( "log( \""
+        + Constants.getString("jsp.error.ise_from_handle_ex") + "\", ise 
);" );
+    writer.popIndent();
+    writer.println( "}" );
+    writer.popIndent();
      writer.println("} finally {");
      writer.pushIndent();
      /* Do stuff here for finally actions... */


Index: messages.properties
===================================================================
RCS file: 
/home/cvspublic/jakarta-tomcat/src/share/org/apache/jasper/resources/message 
s.properties,v
retrieving revision 1.7
diff -u -r1.7 messages.properties
--- messages.properties 1999/12/28 13:25:32     1.7
+++ messages.properties 1999/12/30 22:39:29
@@ -6,6 +6,7 @@
  jsp.message.scratch.dir.is=Scratch dir for the JSP engine is: {0}
  jsp.message.parent_class_loader_is=Parent class loader is: {0}
  jsp.message.dont.modify.servlets=IMPORTANT: Do not modify the generated 
servlets
+jsp.message.error_in_page=ERROR in Page:
  jsp.error.not.impl.comments=Internal error: Comments not implemented
  jsp.error.not.impl.directives=Internal error: Directives not implemented
  jsp.error.not.impl.declarations=Internal error: Declarations not implemented
@@ -135,4 +136,6 @@
  jsp.error.unable.to_introspect=Unable to introspect on tag handler class: 
{0} because of {1}
  jsp.error.invalid_attributes=Attributes are invalid according to TagInfo
  jsp.error.bad_tag=No such tag {0} in the tag library imported with prefix {1}
+jsp.error.se_from_handle_ex=ServletException thrown while trying to handle 
page exception
+jsp.error.ise_from_handle_ex=IllegalStateException throws while trying to 
handle page exception
  jsp.warning.compiler.notfound=Specified compiler {0} not found. Will 
default to Sun Java Compiler.

NOTE: These changes will NOT work unless the GenericServlet.log() methods 
are fixed.  I sent a patch for this earlier.

Thanks,
Alex

Mime
View raw message