Author: rich Date: Wed Jan 5 23:00:33 2005 New Revision: 124349 URL: http://svn.apache.org/viewcvs?view=rev&rev=124349 Log: - Modified the unhandled-exception feature to avoid writing an error page to the response, except when: - the exception thrown is a PageFlowException (which knows how to write a descriptive error) - the server is not in production mode (as defined by the current ServerAdapter) In all other cases, normal exception-handling rules take effect for exceptions thrown.
- Changed to ensure that exceptions thrown during page rendering go through declarative exception handling, even when the page is hit directly (no forward through an action). DRT: netui (WinXP) BB: self (linux) Removed: incubator/beehive/trunk/netui/test/webapps/drt/coreWeb/errors/unhandledException/ incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/UnhandledException.xml Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/ExceptionsHandler.java incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultExceptionsHandler.java incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/PfExceptions.xml Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java?view=diff&rev=124349&p1=incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java&r1=124348&p2=incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java&r2=124349 ============================================================================== --- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java (original) +++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/FlowController.java Wed Jan 5 23:00:33 2005 @@ -31,13 +31,16 @@ import org.apache.struts.Globals; import org.apache.struts.util.TokenProcessor; import org.apache.struts.util.MessageResources; +import org.apache.struts.util.RequestUtils; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionServlet; import org.apache.struts.action.ActionMessages; +import org.apache.struts.action.RequestProcessor; import org.apache.struts.config.ActionConfig; import org.apache.struts.config.ModuleConfig; +import org.apache.struts.config.ControllerConfig; import javax.security.auth.login.LoginException; import javax.servlet.ServletContext; @@ -1311,8 +1314,8 @@ public synchronized ActionForward invokeExceptionHandler( Method method, Throwable ex, String message, Object formBean, ActionForm wrappedFormBean, ActionMapping actionMapping, HttpServletRequest request, HttpServletResponse response, boolean readonly ) + throws IOException, ServletException { - ActionForward result = null; PerRequestState prevState = setPerRequestState( new PerRequestState( request, response, actionMapping ) ); try @@ -1365,15 +1368,23 @@ } catch ( Throwable e ) { + _log.error( "Exception while handling exception " + ex.getClass().getName() + + ". The original exception will be thrown.", e ); + ExceptionsHandler eh = ContextCache.get( getServletContext() ).getExceptionsHandler(); - eh.sendUnhandledExceptionError( eh.unwrapException( e ), request, response, getServletContext() ); + if ( ! eh.eatUnhandledException( eh.unwrapException( e ), request, response, getServletContext() ) ) + { + if ( ex instanceof ServletException ) throw ( ServletException ) ex; + if ( ex instanceof IOException ) throw ( IOException ) ex; + throw new ServletException( ex ); + } + + return null; } finally { setPerRequestState( prevState ); } - - return result; } /** @@ -1796,5 +1807,35 @@ } return null; + } + + PageFlowRequestProcessor getRequestProcessor() + { + ModuleConfig mc = getModuleConfig(); + String key = Globals.REQUEST_PROCESSOR_KEY + mc.getPrefix(); + RequestProcessor rp = ( RequestProcessor ) getServletContext().getAttribute( key ); + + // + // The RequestProcessor may not have been initialized -- if so, just return a new (temporary) one. + // + if ( rp == null ) + { + if ( rp == null ) + { + try + { + ControllerConfig cc = mc.getControllerConfig(); + rp = ( RequestProcessor ) RequestUtils.applicationInstance( cc.getProcessorClass() ); + rp.init( InternalUtils.getActionServlet( getServletContext() ), mc ); + } + catch ( Exception e ) + { + _log.error( "Could not initialize request processor for module " + mc.getPrefix(), e ); + } + } + } + + assert rp == null || rp instanceof PageFlowRequestProcessor : rp.getClass().getName(); + return ( PageFlowRequestProcessor ) rp; } } Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java?view=diff&rev=124349&p1=incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java&r1=124348&p2=incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java&r2=124349 ============================================================================== --- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java (original) +++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowPageFilter.java Wed Jan 5 23:00:33 2005 @@ -33,6 +33,10 @@ import org.apache.struts.util.RequestUtils; import org.apache.struts.util.MessageResources; import org.apache.struts.action.ActionServlet; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.RequestProcessor; import org.apache.struts.config.ModuleConfig; import org.apache.struts.Globals; @@ -258,6 +262,27 @@ { chain.doFilter( request, response ); } + catch ( ServletException servletEx ) + { + // + // If a ServletException escapes out of the page, let the current FlowController handle it. + // + if ( ! handleException( servletEx, curJpf, request, response ) ) throw servletEx; + } + catch ( IOException ioe ) + { + // + // If an IOException escapes out of the page, let the current FlowController handle it. + // + if ( ! handleException( ioe, curJpf, request, response ) ) throw ioe; + } + catch ( Throwable th ) + { + // + // If a Throwable escapes out of the page, let the current FlowController handle it. + // + if ( ! handleException( th, curJpf, request, response ) ) throw new ServletException( th ); + } finally { curJpf.setPerRequestState( prevState ); @@ -276,6 +301,25 @@ chain.doFilter( request, response ); } } + + private boolean handleException( Throwable th, FlowController fc, HttpServletRequest request, + HttpServletResponse response ) + { + try + { + ActionMapping mapping = InternalUtils.getCurrentActionMapping( request ); + ActionForm form = InternalUtils.getCurrentActionForm( request ); + ActionForward fwd = fc.handleException( th, mapping, form, request, response ); + fc.getRequestProcessor().processActionForward( request, response, fwd ); + return true; + } + catch ( Throwable t ) + { + _log.error( "Exception while handling exception " + th.getClass().getName() + + ". The original exception will be thrown.", th ); + return false; + } + } private void initializeModule( HttpServletRequest request, HttpServletResponse response ) throws IOException, ServletException Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java?view=diff&rev=124349&p1=incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java&r1=124348&p2=incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java&r2=124349 ============================================================================== --- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java (original) +++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/PageFlowRequestProcessor.java Wed Jan 5 23:00:33 2005 @@ -589,15 +589,23 @@ private boolean handleException( Throwable th, FlowController fc, HttpServletRequest request, HttpServletResponse response ) - throws ServletException, IOException { if ( fc != null ) { - ActionMapping mapping = InternalUtils.getCurrentActionMapping( request ); - ActionForm form = InternalUtils.getCurrentActionForm( request ); - ActionForward fwd = fc.handleException( th, mapping, form, request, response ); - processForwardConfig( request, response, fwd ); - return true; + try + { + ActionMapping mapping = InternalUtils.getCurrentActionMapping( request ); + ActionForm form = InternalUtils.getCurrentActionForm( request ); + ActionForward fwd = fc.handleException( th, mapping, form, request, response ); + processForwardConfig( request, response, fwd ); + return true; + } + catch ( Throwable t ) + { + _log.error( "Exception while handling exception " + th.getClass().getName() + + ". The original exception will be thrown.", th ); + return false; + } } return false; @@ -1866,5 +1874,11 @@ } return ret; + } + + void processActionForward( HttpServletRequest request, HttpServletResponse response, ActionForward forward ) + throws IOException, ServletException + { + processForwardConfig( request, response, forward ); } } Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/ExceptionsHandler.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/ExceptionsHandler.java?view=diff&rev=124349&p1=incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/ExceptionsHandler.java&r1=124348&p2=incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/ExceptionsHandler.java&r2=124349 ============================================================================== --- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/ExceptionsHandler.java (original) +++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/handler/ExceptionsHandler.java Wed Jan 5 23:00:33 2005 @@ -47,6 +47,6 @@ void exposeException( Throwable ex, ActionMapping actionMapping, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext ); - void sendUnhandledExceptionError( Throwable ex, HttpServletRequest request, HttpServletResponse response, - ServletContext servletContext ); + boolean eatUnhandledException( Throwable ex, HttpServletRequest request, HttpServletResponse response, + ServletContext servletContext ); } Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultExceptionsHandler.java Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultExceptionsHandler.java?view=diff&rev=124349&p1=incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultExceptionsHandler.java&r1=124348&p2=incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultExceptionsHandler.java&r2=124349 ============================================================================== --- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultExceptionsHandler.java (original) +++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/pageflow/internal/DefaultExceptionsHandler.java Wed Jan 5 23:00:33 2005 @@ -36,8 +36,6 @@ import java.lang.reflect.Method; import java.util.Locale; import java.util.Collection; -import java.io.StringWriter; -import java.io.PrintWriter; import java.io.IOException; import org.apache.beehive.netui.pageflow.config.PageFlowExceptionConfig; @@ -136,8 +134,14 @@ StringBuilder msg = new StringBuilder( "Throwable " ).append( exClass.getName() ); _log.error( msg.append( " unhandled by the current page flow (and any shared flow)" ).toString(), ex ); } + + if ( ! eatUnhandledException( ex, request, response, servletContext ) ) + { + if ( ex instanceof ServletException ) throw ( ServletException ) ex; + if ( ex instanceof IOException ) throw ( IOException ) ex; + throw new ServletException( ex ); + } - sendUnhandledExceptionError( ex, request, response, servletContext ); return null; } @@ -352,8 +356,8 @@ } } - public void sendUnhandledExceptionError( Throwable ex, HttpServletRequest request, HttpServletResponse response, - ServletContext servletContext ) + public boolean eatUnhandledException( Throwable ex, HttpServletRequest request, HttpServletResponse response, + ServletContext servletContext ) { _log.error( "Unhandled Page Flow Exception", ex ); @@ -362,29 +366,20 @@ // // PageFlowExceptions know what to do in the unhandled case. // - if ( ex instanceof PageFlowException ) + boolean prodMode = ServerAdapterManager.getServerAdapter( servletContext ).isInProductionMode(); + + if ( ! prodMode && ex instanceof PageFlowException ) { ( ( PageFlowException ) ex ).sendError( request, response ); - } - else - { - StringWriter sw = new StringWriter(); - PrintWriter out = new PrintWriter( sw ); - ex.printStackTrace( out ); - out.close(); - - String msg = ex.getMessage(); - if ( msg == null ) msg = " "; - - InternalUtils.sendDevTimeError( "PageFlow_UnhandledException", ex, - HttpServletResponse.SC_INTERNAL_SERVER_ERROR, request, response, - servletContext, ex.getClass().getName(), msg, sw.toString() ); + return true; } } catch ( IOException ioEx ) { _log.error( ioEx.getMessage(), ioEx ); } + + return false; } /** Modified: incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml?view=diff&rev=124349&p1=incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml&r1=124348&p2=incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml&r2=124349 ============================================================================== --- incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml (original) +++ incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/config/testRecorder-tests.xml Wed Jan 5 23:00:33 2005 @@ -5685,20 +5685,6 @@ </features> </test> <test> - <name>UnhandledException</name> - <description>An Unhandled Exception error.</description> - <webapp>coreWeb</webapp> - <categories> - <category>bvt</category> - <category>bvt.struts11</category> - <category>errorTests</category> - </categories> - <features> - <feature>PageFlow</feature> - <feature>Exceptions</feature> - </features> - </test> - <test> <name>UrlBinding</name> <description>Test of binding to the {url} context.</description> <webapp>coreWeb</webapp> Modified: incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/PfExceptions.xml Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/PfExceptions.xml?view=diff&rev=124349&p1=incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/PfExceptions.xml&r1=124348&p2=incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/PfExceptions.xml&r2=124349 ============================================================================== --- incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/PfExceptions.xml (original) +++ incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/PfExceptions.xml Wed Jan 5 23:00:33 2005 @@ -1088,109 +1088,6 @@ <protocolVersion>1.1</protocolVersion> <host>localhost</host> <port>7001</port> - <uri>/coreWeb/pageFlowCore/exceptions/throwUnhandled.do</uri> - <method>GET</method> - - <parameters> - </parameters> - - <cookies> - <cookie> - <name>JSESSIONID</name> - <value>Ab2YhDfLK7xddv42utvWR0RnuzG87mcLi4sHI2ElbKynxiONcFz1!-125393018</value> - </cookie> - </cookies> - - <headers> - <header> - <name>Accept</name> - <value>text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,video/x-mng,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1</value> - </header> - <header> - <name>Accept-Charset</name> - <value>ISO-8859-1,utf-8;q=0.7,*;q=0.7</value> - </header> - <header> - <name>Accept-Encoding</name> - <value>gzip, deflate, x-gzip, compress, x-compress</value> - </header> - <header> - <name>Accept-Language</name> - <value>en-us,en;q=0.5</value> - </header> - <header> - <name>Connection</name> - <value>keep-alive, TE</value> - </header> - <header> - <name>Cookie</name> - <value>JSESSIONID=Ab2YhDfLK7xddv42utvWR0RnuzG87mcLi4sHI2ElbKynxiONcFz1!-125393018</value> - </header> - <header> - <name>Cookie2</name> - <value>$Version="1"</value> - </header> - <header> - <name>Host</name> - <value>localhost:7001</value> - </header> - <header> - <name>Keep-Alive</name> - <value>300</value> - </header> - <header> - <name>TE</name> - <value>trailers, deflate, gzip, compress</value> - </header> - <header> - <name>User-Agent</name> - <value>Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.4) Gecko/20030624 RPT-HTTPClient/0.3-3E RPT-HTTPClient/0.3-3E RPT-HTTPClient/0.3-3E</value> - </header> - <header> - <name>testRecorder.playback.failMode</name> - <value>stop</value> - </header> - <header> - <name>testRecorder.playback.testID</name> - <value>755a3675:fc615b4c47:-7d3e</value> - </header> - <header> - <name>testRecorder.playback.testNumber</name> - <value>10</value> - </header> - </headers> - - </request> - - <response> - <statusCode>200</statusCode> - <reason></reason> - <responseBody><![CDATA[<html><head><title>Page Flow Unhandled Exception</title></head> - <body> - <h1>Page Flow Unhandled Exception</h1> - <table border="1" cellspacing="0"> - <tr><td><b>Exception:</b></td><td>pageFlowCore.exceptions.Controller$UnhandledException</td></tr> - <tr><td><b>Message:</b></td><td>this is an UnhandledException</td></tr> - </table><br /> - <span style="color:red">A <b>pageFlowCore.exceptions.Controller$UnhandledException</b> exception was thrown and not handled by any page flow. See the log for the exception stack trace.</span> - </body></html>]]></responseBody> - - </response> - - <testResults> - <testStatus>pass</testStatus> - - </testResults> - </test> - <test> - <testNumber>11</testNumber> - - <request> - - <protocol>HTTP</protocol> - <protocolVersion>1.1</protocolVersion> - <host>localhost</host> - <port>7001</port> <uri>/coreWeb/pageFlowCore/exceptions/failRoles.do</uri> <method>GET</method> @@ -1259,7 +1156,7 @@ </header> <header> <name>testRecorder.playback.testNumber</name> - <value>11</value> + <value>10</value> </header> </headers> @@ -1290,7 +1187,7 @@ <endDate>07 May 2004, 03:32:07.359 PM MDT</endDate> <sessionStatus>fail</sessionStatus> - <testCount>11</testCount> + <testCount>10</testCount> <passedCount>7</passedCount> - <failedCount>4</failedCount> -</recorderSession> \ No newline at end of file + <failedCount>3</failedCount> +</recorderSession> Deleted: /incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/UnhandledException.xml Url: http://svn.apache.org/viewcvs/incubator/beehive/trunk/netui/test/webapps/drt/testRecorder/tests/UnhandledException.xml?view=auto&rev=124348 ==============================================================================
