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.