if enclosing page (e.g. tiles layout) forwards to or includes a jsp that throws an error (compile or otherwise) and the enclosing page doesn't have the errorPage directive, the sub-page processing of the error page causes an IllegalStateException (see bottom of email)

result being the enclosing page displays content up to the point where the errant include occurs.

OK, so it seems like not all pages need to have the errorPage directive, but it seems that all pages contain includes (e.g. tiles insert require the directive to function properly)


16:45:31,234 ERROR [Engine] [EMAIL PROTECTED]: Exception Processing
ErrorPage[exceptionType=java.lang.Throwable, location=/WEB-INF/pages/Error.jsp]
java.lang.IllegalStateException
at org.apache.coyote.Response.reset(Response.java:296)
at org.apache.coyote.tomcat5.CoyoteResponse.reset(CoyoteResponse.java:645)
at org.apache.coyote.tomcat5.CoyoteResponse.reset(CoyoteResponse.java:911)
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:389)
at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:225)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:145)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:118)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11P
rotocol.java:705)
at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
at java.lang.Thread.run(Thread.java:534)


Kishore Senji wrote:
On Sun, 16 Jan 2005 12:10:37 +0800, Nathan Coast <[EMAIL PROTECTED]> wrote:

Hi,

I've been strugling for a while with exception handling.  I've been
trying to ensure:
1) all exceptions are displayed consistently regardless of where / how
the exception is raised.
2) the root cause exception is always displayed,

I'm not saying this is the best solution, nor even a 'correct' solution,
but it is a way I have found that works with the least amount of coding
- so I thought it'd be useful to share.

I have tested the following situations where exceptions are raised
1) Action
2) JSP
3) JSP compile error
4) a jsp included by tiles / jsp:include / jsp:forward
5) an action included by tiles / jsp:include / jsp:forward
6) exception raised in a tag class

cases 4,5 were the only real problem as most attempts to handle
exceptions resulted in an IllegalStateException or the error page
appearing nested within some other page.

solution overview:
all errors go to a single error jsp,  this error page locates the root
cause exception and places the throwable into the session.  The jsp then
redirects the browser to a second jsp (using meta-refresh) this
ViewError.jsp retrieves the error from the session and displays it.

Details:

1) define a single Error JSP

/WEB-INF/pages/Error.jsp:
**************************************************

<%@ page isErrorPage="true" %>
<%@ page import="org.apache.struts.Globals" %>
<%@ page import="org.apache.commons.lang.exception.ExceptionUtils" %>
<%
 //check for tag exceptions that are the 'real' exception
 Throwable th = (Throwable) request.getAttribute(Globals.EXCEPTION_KEY);
 if (th == null)
 {
   th = exception;
 }
 //check exception for root cause using commons-lang ExceptionUtils
 Throwable rootCause = ExceptionUtils.getCause(th);
 if(rootCause != null)
 {
   th = rootCause;
 }
 //best place to log errors is here
 session.setAttribute("some_key", th);
%>
<html>
<META HTTP-EQUIV="Refresh" CONTENT="0;url=<%=request.getContextPath()
%>/ViewError.jsp">
</html>

***************************************************

2) place this directive within every jsp page:
<%@ page errorPage="/WEB-INF/pages/Error.jsp" %>

3) define the following error-page in web.xml

 <error-page>
   <exception-type>java.lang.Throwable</exception-type>
   <location>/WEB-INF/pages/Error.jsp</location>
 </error-page>


If we do (3) I believe we don't have to (2) in each and every jsp. Isn't it?


4) Define your ViewError.jsp

The ViewError.jsp contains the exception display code that you would
normally place in your error jsp. ViewError.jsp is not a jsp error page
(no isErrorPage directive) and you need to include code to retrieve /
remove the Throwable from the session:

ViewError.jsp snip:
***************************************************

<%
Throwable ex = (Throwable) session.getAttribute("some_key");
session.removeAttribute("some_key");
%>
//display the error:
  <pre>
  <% ex.printStackTrace(new PrintWriter(out)); %>
  </pre>

***************************************************

I prefer all jsps to be beneath WEB-INF/pages so I define a simple
action class to access my ViewError.jsp and redirect to /ViewError.do in
my Error.jsp (you can skip this step if your /ViewError.jsp is not
beneath /WEB-INF)

I'd be interested to hear if anyone has any better solutions as this
still feels a little ugly:

1) all jsps having the error page defined is there no way to set the
error-page globally
2) saving and retrieving all 'real' tag exceptions via the request and
throwing an intermediate JspException (can be avoided if all tag classes
wrap root cause exceptions in the JspException) there seems to be plenty
of code like this in struts:
catch (ClassCastException e) {
 saveException(pageContext, e);
 throw new JspException(blah blah blah);
}
I think the JspException(Throwable) constructor was added in jsp 2.0 so
I guess backwards compatability is why this isn't in struts (yet).
3) redirecting browsers, saving and retrieving exceptions in sessions

I still feel like I should be able to define my error handling mechanism
in one place (like in web.xml) and job done.

cheers
Nathan

--
Nathan Coast
Managing Director
Codeczar Ltd
mob : (852) 9049 5581
tel : (852) 2834 8733
fax : (852) 2834 8755
web : http://www.codeczar.com

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




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




-- Nathan Coast Managing Director Codeczar Ltd mob : (852) 9049 5581 tel : (852) 2834 8733 fax : (852) 2834 8755 web : http://www.codeczar.com

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



Reply via email to