All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.struts.action.ExceptionHandler Maven / Gradle / Ivy

/*
 * $Id: ExceptionHandler.java 471754 2006-11-06 14:55:09Z husted $
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.struts.action;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.Globals;
import org.apache.struts.config.ExceptionConfig;
import org.apache.struts.util.MessageResources;
import org.apache.struts.util.ModuleException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

/**
 * 

An ExceptionHandler is configured in the Struts * configuration file to handle a specific type of exception thrown by an * Action.execute method.

* * @since Struts 1.1 */ public class ExceptionHandler { /** *

The name of a configuration property which can be set to specify an * alternative path which should be used when the HttpServletResponse has * already been committed.

To use this, in your * struts-config.xml specify the exception handler like * this: *

     *   <exception
     *       key="GlobalExceptionHandler.default"
     *       type="java.lang.Exception"
     *       path="/ErrorPage.jsp">
     *       <set-property key="INCLUDE_PATH" value="/error.jsp" />
     *   </exception>
     *  
*

You would want to use this when your normal ExceptionHandler * path is a Tiles definition or otherwise unsuitable for use in an * include context. If you do not use this, and you do not * specify "SILENT_IF_COMMITTED" then the ExceptionHandler will attempt to * forward to the same path which would be used in normal circumstances, * specified using the "path" attribute in the <exception> * element.

* * @since Struts 1.3 */ public static final String INCLUDE_PATH = "INCLUDE_PATH"; /** *

The name of a configuration property which indicates that Struts * should do nothing if the response has already been committed. This * suppresses the default behavior, which is to use an "include" rather * than a "forward" in this case in hopes of providing some meaningful * information to the browser.

To use this, in your * struts-config.xml specify the exception handler like * this: *

     *   <exception
     *       key="GlobalExceptionHandler.default"
     *       type="java.lang.Exception"
     *       path="/ErrorPage.jsp">
     *       <set-property key="SILENT_IF_COMMITTED" value="true" />
     *   </exception>
     *  
* To be effective, this value must be defined to the literal String * "true". If it is not defined or defined to any other value, the default * behavior will be used.

You only need to use this if you do not * want error information displayed in the browser when Struts intercepts * an exception after the response has been committed.

* * @since Struts 1.3 */ public static final String SILENT_IF_COMMITTED = "SILENT_IF_COMMITTED"; /** *

Commons logging instance.

*/ private static final Log LOG = LogFactory.getLog(ExceptionHandler.class); /** *

The message resources for this package.

*/ private static MessageResources messages = MessageResources.getMessageResources( "org.apache.struts.action.LocalStrings"); /** *

Handle the Exception. Return the ActionForward instance (if any) * returned by the called ExceptionHandler.

* * @param ex The exception to handle * @param ae The ExceptionConfig corresponding to the exception * @param mapping The ActionMapping we are processing * @param formInstance The ActionForm we are processing * @param request The servlet request we are processing * @param response The servlet response we are creating * @return The ActionForward instance (if any) returned by * the called ExceptionHandler. * @throws ServletException if a servlet exception occurs * @since Struts 1.1 */ public ActionForward execute(Exception ex, ExceptionConfig ae, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request, HttpServletResponse response) throws ServletException { LOG.debug("ExceptionHandler executing for exception " + ex); ActionForward forward; ActionMessage error; String property; // Build the forward from the exception mapping if it exists // or from the form input if (ae.getPath() != null) { forward = new ActionForward(ae.getPath()); } else { forward = mapping.getInputForward(); } // Figure out the error if (ex instanceof ModuleException) { error = ((ModuleException) ex).getActionMessage(); property = ((ModuleException) ex).getProperty(); } else { error = new ActionMessage(ae.getKey(), ex.getMessage()); property = error.getKey(); } this.logException(ex); // Store the exception request.setAttribute(Globals.EXCEPTION_KEY, ex); this.storeException(request, property, error, forward, ae.getScope()); if (!response.isCommitted()) { return forward; } LOG.debug("Response is already committed, so forwarding will not work." + " Attempt alternate handling."); if (!silent(ae)) { handleCommittedResponse(ex, ae, mapping, formInstance, request, response, forward); } else { LOG.warn("ExceptionHandler configured with " + SILENT_IF_COMMITTED + " and response is committed.", ex); } return null; } /** *

Attempt to give good information when the response has already been * committed when the exception was thrown. This happens often when Tiles * is used. Base implementation will see if the INCLUDE_PATH property has * been set, or if not, it will attempt to use the same path to which * control would have been forwarded.

* * @param ex The exception to handle * @param config The ExceptionConfig we are processing * @param mapping The ActionMapping we are processing * @param formInstance The ActionForm we are processing * @param request The servlet request we are processing * @param response The servlet response we are creating * @param actionForward The ActionForward we are processing * @since Struts 1.3 */ protected void handleCommittedResponse(Exception ex, ExceptionConfig config, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request, HttpServletResponse response, ActionForward actionForward) { String includePath = determineIncludePath(config, actionForward); if (includePath != null) { if (includePath.startsWith("/")) { LOG.debug("response committed, " + "but attempt to include results " + "of actionForward path"); RequestDispatcher requestDispatcher = request.getRequestDispatcher(includePath); try { requestDispatcher.include(request, response); return; } catch (IOException e) { LOG.error("IOException when trying to include " + "the error page path " + includePath, e); } catch (ServletException e) { LOG.error("ServletException when trying to include " + "the error page path " + includePath, e); } } else { LOG.warn("Suspicious includePath doesn't seem likely to work, " + "so skipping it: " + includePath + "; expected path to start with '/'"); } } LOG.debug("Include not available or failed; " + "try writing to the response directly."); try { response.getWriter().println("Unexpected error: " + ex); response.getWriter().println(""); } catch (IOException e) { LOG.error("Error giving minimal information about exception", e); LOG.error("Original exception: ", ex); } } /** *

Return a path to which an include should be attempted in the case * when the response was committed before the ExceptionHandler * was invoked.

If the ExceptionConfig has the * property INCLUDE_PATH defined, then the value of that * property will be returned. Otherwise, the ActionForward path is * returned.

* * @param config Configuration element * @param actionForward Forward to use on error * @return Path of resource to include * @since Struts 1.3 */ protected String determineIncludePath(ExceptionConfig config, ActionForward actionForward) { String includePath = config.getProperty("INCLUDE_PATH"); if (includePath == null) { includePath = actionForward.getPath(); } return includePath; } /** *

Logs the Exception using commons-logging.

* * @param e The Exception to LOG. * @since Struts 1.2 */ protected void logException(Exception e) { LOG.debug(messages.getMessage("exception.LOG"), e); } /** *

Default implementation for handling an ActionMessage * generated from an Exception during Action * delegation. The default implementation is to set an attribute of the * request or session, as defined by the scope provided (the scope from * the exception mapping). An ActionMessages instance is * created, the error is added to the collection and the collection is set * under the Globals.ERROR_KEY.

* * @param request The request we are handling * @param property The property name to use for this error * @param error The error generated from the exception mapping * @param forward The forward generated from the input path (from the * form or exception mapping) * @param scope The scope of the exception mapping. * @since Struts 1.2 */ protected void storeException(HttpServletRequest request, String property, ActionMessage error, ActionForward forward, String scope) { ActionMessages errors = new ActionMessages(); errors.add(property, error); if ("request".equals(scope)) { request.setAttribute(Globals.ERROR_KEY, errors); } else { request.getSession().setAttribute(Globals.ERROR_KEY, errors); } } /** *

Indicate whether this Handler has been configured to be silent. In * the base implementation, this is done by specifying the value * "true" for the property "SILENT_IF_COMMITTED" in the * ExceptionConfig.

* * @param config The ExceptionConfiguration we are handling * @return True if Handler is silent * @since Struts 1.3 */ private boolean silent(ExceptionConfig config) { return "true".equals(config.getProperty(SILENT_IF_COMMITTED)); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy