I was looking at implementing a global error page for unhandled exceptions in a Struts / Tiles application. Normally this was achieved by adding a
This would forward to the error page if an unhandled exception was thrown from the Struts action but will not do so if the exception occurred in one of the tiles JSPs. An exception in a tile would result in a partly rendered page but this was fine in previous app as there were hardly any logic in JSP files and it was very rare to have an exception at the JSP level in production.
In the new app though this wasn’t the case as there were lot of logic that went in to JSPs in the form of custom tags etc… that could potentially throw all sorts of exceptions at run time and I wanted to handle all these exceptions in a unified manner.
New Solution
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error </location>
</error-page>
Then added a servlet and a servlet mapping to the /error URL
<servlet>
<servlet-name>exceptionHandler</servlet-name>
<servlet-class>com.test.ExceptionHandlerServlet</servlet-class>
<init-param>
<param-name>errorPageURL</param-name>
<param-value>error.html</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>exceptionHandler</servlet-name>
<url-pattern>/error</url-pattern>
</servlet-mapping>
The ExceptionHandlerServlet would log the exception and redirect the browser to the URL defined in the servlet configuration (error.html).
ExceptionHandlerServlet Code:
|
This was due to tiles flushing content to the response buffer before the whole page was rendered. In such a situation the browser will happily display what it received and the redirect to the error page will have no effect.
In order to prevent or minimize the flushing of response buffer:
1. Set flush attribute to false in all tiles insert tags
2. Increase the response buffer size to minimize auto flushing
This was achieved by modifying the tiles layout jsp page.
<!-- sets the response buffer size to 64kb -->
<%@ page buffer="64kb"%>
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles"%>
…
<tiles:insert attribute="header" flush="false" />
<tiles:insert attribute="leftnav" flush="false" />
<tiles:insert attribute="body" flush="false" />
<tiles:insert attribute="footer" flush="false" />
In the above code segment all html formatting was removed for clarity. The response buffer was set to 64 kilobytes and this value should be decide based on the average page size of the application and the performance impact of the increased memory usage.
15 comments:
What version of Struts are you using?
I just read here that this issue was fixed in Struts 1.2....
Eric,
I'm using Struts 1.2.9 and this is not a bug in Tiles. It's just the way tiles work. Once tiles flush the response buffer at least once there is no way an exception handler can send a redirect to the browser. That's the reason why you have to explicitly say flush="false" in each tiles insert tag and set the response buffer size to a higher value to prevent auto flushing.
I just tried your solution, but I still get the IllegalStateExcpetion... Any ideas what might be wrong? I am using Struts 1.2.9
I am using Tiles with Spring MVC and have come across this exact problem. The side menu renders ok and I get the exception shown to the user in the body section. I tried your solution and it didn't make a difference.
Are you sure this works?
@drew and bora,
Upto now I have tried this only on BEA Weblogic 8.1 and 9.2 as we are deploying the application on Weblogic.
Since both of you raised questions on the solution I decided to test it on Tomcat 5 and sure enough it throws an IllegalStateExcpetion and does not forward to the configured error-page URL on an exception in a tile.
It looks like Tomcat is flushing the buffer regardless of the flush setting and I couldn't find a work around for it yet.
Anyway please post a comment if you are testing this on something other than Tomcat. I'd love to know on what servers this works.
Dear Master Nothing,
This works with WebSphere 5.1.2 and Struts 1.3.9.
Thanks very much for you nice solution.
I cannot seem to get this to work with Websphere 6.0.2 and Struts 1.3.8. I cannot seem to get the tag errors to get thrown out to the general servlet error handling (i.e., so that my error page tag in the web.xml kicks in).
I get the following exception:
[11/2/07 15:32:59:478 EST] 0000003b ServletWrappe E SRVE0068E: Could not invoke the service() method on servlet /WEB-INF/jsp/content/hotelalert_cont
ent.jsp. Exception thrown : javax.servlet.ServletException: Cannot find bean under name
at org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:640)
at com.ibm._jsp._hotelalert_5F_content._jspService(_hotelalert_5F_content.java:117)
at com.ibm.ws.jsp.runtime.HttpJspBase.service(HttpJspBase.java:88)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1282)
.......
Any help would be greatly appreciated.
Any idea how to get Weblogic to use a single error-page for all web applications? (rather than having to specify a separate one in each web.xml file)
I have a Question regarding exception handling in JSP.
I am looking at implementing a global error page for unhandled exceptions in a Struts / Tiles application.
I am using struts1.1 and WCS v6.0
In the JSP (body.jsp) where the exception is happening i am including the following line
<@ page isThreadSafe="false" errorPage="error.jsp">
and in the Main JSP where tiles are included, i am implementing the following way
tiles:insert attribute="header" flush="false"/> tiles:insert attribute="body" flush="false"/>
tiles:insert attribute="footer" flush="false"/>
When the Exception occurs, still the header and footer are rendered from the tiles and error.jsp is rendered in place of body.jsp
Could you please tell me, why it is functioning the above way.
I had gone through your implementation i.e change in web.xml. How difft is this implementation from the above mentioned one..please share your comments
thanks a million this worked like a charm for me!
Everything i was looking for.
Cheers,
Annie
Does your class ExceptionHandlerServlet extends HttpServlet class? or other class?
I do it as you said but when exception throwed to servlet level, ExceptionHandlerServlet cannot catch the exception. Kindly advise.
Hello All,
I resolved this very easily.
I simply added the following page directive to my tiles layout-main.jsp page. Make sure you surround the below with scripting tag.
page errorPage="systemError.jsp"
Please make sure both layout.jsp and systemError.jsp are in the same directory or change the location of systemError.jsp accordingly.
In systemError.jsp, make sure you have the following page directive. Make sure you surround the below with scripting tag.
page language="java" isErrorPage="true"
Thats all. Any JSP error will be handled by the systemError.jsp page.
Regards,
Rags.
Having customized error page which clearly display error message and redirect to some valid path is a must have thing for a website. I was struggling to implement this using Struts thanks for your post , saved a lot of time.
Thanks
3 ways to resolve NoClassDefFoundError in Java
It worked perfectly and saved me a lot of time for the project I´m working in!! Thanks!!
well explained . thanks for sharing good post . Good arraylist example collection visit
Arraylist example
Post a Comment