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

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

The newest version!
/*
 * $Id$
 *
 * 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 java.io.IOException;

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

import org.apache.struts.Globals;
import org.apache.struts.config.ExceptionConfig;
import org.apache.struts.util.MessageResources;
import org.apache.struts.util.ModuleException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 

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"; /** * The {@code Log} instance for this class. */ private final Logger log = LoggerFactory.getLogger(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 { // STR-2924 if (ae.getKey() != null) { error = new ActionMessage(ae.getKey(), ex.getMessage()); property = error.getKey(); } else { error = null; property = null; } } 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 {}" + " and response is committed.", SILENT_IF_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: {}" + "; expected path to start with '/'", includePath); } } 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.atDebug() .setMessage(() -> messages.getMessage("exception.LOG")) .setCause(e).log(); } /** *

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), if error is not null. * Otherwise, 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) { if (error != null) { 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