Using Struts' declarative exception-handling mechanism is very simple. All you have to do is add exception handler definitions to your application's Struts configuration file. Exception handler definitions work in much the same way as forward definitions. You can create global exception handler definitions and/or create action-specific handlers. Each exception handler definition specifies the exception that it is to handle, a key to an error message in the application resource bundle (e.g., MessageResources.properties), and the path to a page to forward to when the exception is caught by the handler. Following is an example global exception handler definition:
<global-exceptions> <exception type="com.jamesholmes.minihr.NoResultsFoundException" key="error.NoResultsFoundException" path="/exception.jsp"/> </global-exceptions>
The type attribute specifies the fully qualified class name of the exception that the handler is for. When an exception of this type is thrown, the exception handler will take control and process the exception. The key attribute specifies the name of a key in the application resource bundle file that will be used to populate an ActionMessage object that will be passed to the page specified by the path attribute. The path attribute specifies the path to a page that will be forwarded to by the exception handler when the specified exception type is thrown. The page can then display the error message placed in the ActionMessage object, if so desired.
The second way that exception handlers can be defined is by nesting them inside action definitions, as shown next:
<!-- Action Mappings Configuration --> <action-mappings> <action path="/search" type="com.jamesholmes.minihr.SearchAction" name="searchForm" scope="request" validate="true" input="/search.jsp"> <exception type="com.jamesholmes.minihr.NoResultsFoundException" key="error.NoResultsFoundException" path="/exception.jsp"/> </action> </action-mappings>
Action-nested exception handlers handle the specified exception only if it is thrown by the enclosing action. If the exception is thrown by another action, it will not be handled.
You don't have to modify your Action classes in any way to take advantage of declarative exception handling. However, if you already have try-catch blocks for exceptions that you want handled by the exception handler, you need to remove them so that the exception gets propagated up the chain for the exception handler to process.
Generally speaking, Struts' declarative exception handling mechanism was designed to handle the scenario where an exception gets thrown from an Action class during regular processing before a response has been generated back to the client (i.e., browser). In that scenario the response is in what's called a non-committed state. However, there are scenarios where the response has been committed (meaning that data has been sent to the response) before an exception is thrown that the exception handler must handle. This causes a problem for the default Struts exception handler. When an exception occurs, the default Struts exception handler forwards to the page specified by the <exception> element's path attribute, however, forwards cannot be performed if a response has already been committed.
As part of the Struts 1.3 release, the default exception handler was modified to manage the scenario where the response has already been committed before an exception is thrown and then handled by the handler. In that scenario, the default exception handler will now include the contents of the URL specified by the <exception> element's path attribute instead of forwarding to the URL. As part of the additional functionality for the default exception handler, two configurable properties were added to modify the behavior of the exception handler when dealing with committed responses: INCLUDE_PATH and SILENT_IF_COMMITTED.
The INCLUDE_PATH property is used to specify an alternate URL to use for the include in the scenario where the response has been committed. This is especially useful if the <exception> element's path attribute is a Tiles definition or similar resource that is unsuitable for an include. Following is an example of how to use the INCLUDE_PATH property:
<exception key="GlobalExceptionHandler.default" type="java.lang.Exception" path="/error.jsp"> <set-property key="INCLUDE_PATH" value="/error-alt.jsp"/> </exception>
The SILENT_IF_COMMITTED property is used to suppress the exception handler's default behavior of performing an include if the response has been committed. If this property is set to true, the exception handler will revert to its old behavior of forwarding regardless of the state of the response. The following snippet illustrates the usage of the SILENT_IF_COMMITTED property.
<exception key="GlobalExceptionHandler.default" type="java.lang.Exception" path="/error.jsp"> <set-property key="SILENT_IF_COMMITTED" value="true"/> </exception>