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

com.opensymphony.xwork2.validator.ValidationInterceptor Maven / Gradle / Ivy

There is a newer version: 6.4.0
Show newest version
/*
 * 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 com.opensymphony.xwork2.validator;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.Validateable;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import com.opensymphony.xwork2.interceptor.PrefixMethodInvocationUtil;
import com.opensymphony.xwork2.interceptor.ValidationAware;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * 
 *
 * 

* This interceptor runs the action through the standard validation framework, which in turn checks the action against * any validation rules (found in files such as ActionClass-validation.xml) and adds field-level and action-level * error messages (provided that the action implements {@link ValidationAware}). This interceptor * is often one of the last (or second to last) interceptors applied in a stack, as it assumes that all values have * already been set on the action. *

* *

* This interceptor does nothing if the name of the method being invoked is specified in the excludeMethods * parameter. excludeMethods accepts a comma-delimited list of method names. For example, requests to * foo!input.action and foo!back.action will be skipped by this interceptor if you set the * excludeMethods parameter to "input, back". *

* *

* The workflow of the action request does not change due to this interceptor. Rather, * this interceptor is often used in conjunction with the workflow interceptor. *

* *

* NOTE: As this method extends off MethodFilterInterceptor, it is capable of * deciding if it is applicable only to selective methods in the action class. See * MethodFilterInterceptor for more info. *

* * * *

Interceptor parameters:

* * * *
    * *
  • alwaysInvokeValidate - Defaults to true. If true validate() method will always * be invoked, otherwise it will not.
  • * *
  • programmatic - Defaults to true. If true and the action is Validateable call validate(), * and any method that starts with "validate". *
  • * *
  • declarative - Defaults to true. Perform validation based on xml or annotations.
  • * *
* * * *

Extending the interceptor:

* * * * There are no known extension points for this interceptor. * * * *

Example code:

* *
 * 
 * 
 * <action name="someAction" class="com.examples.SomeAction">
 *     <interceptor-ref name="params"/>
 *     <interceptor-ref name="validation"/>
 *     <interceptor-ref name="workflow"/>
 *     <result name="success">good_result.ftl</result>
 * </action>
 * 
 * <-- in the following case myMethod of the action class will not
 *        get validated -->
 * <action name="someAction" class="com.examples.SomeAction">
 *     <interceptor-ref name="params"/>
 *     <interceptor-ref name="validation">
 *         <param name="excludeMethods">myMethod</param>
 *     </interceptor-ref>
 *     <interceptor-ref name="workflow"/>
 *     <result name="success">good_result.ftl</result>
 * </action>
 * 
 * <-- in the following case only annotated methods of the action class will
 *        be validated -->
 * <action name="someAction" class="com.examples.SomeAction">
 *     <interceptor-ref name="params"/>
 *     <interceptor-ref name="validation">
 *         <param name="validateAnnotatedMethodOnly">true</param>
 *     </interceptor-ref>
 *     <interceptor-ref name="workflow"/>
 *     <result name="success">good_result.ftl</result>
 * </action>
 *
 *
 * 
 * 
* * @author Jason Carreira * @author Rainer Hermanns * @author Alexandru Popescu * @see ActionValidatorManager * @see com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor */ public class ValidationInterceptor extends MethodFilterInterceptor { private static final Logger LOG = LogManager.getLogger(ValidationInterceptor.class); private final static String VALIDATE_PREFIX = "validate"; private final static String ALT_VALIDATE_PREFIX = "validateDo"; private boolean validateAnnotatedMethodOnly; private ActionValidatorManager actionValidatorManager; private boolean alwaysInvokeValidate = true; private boolean programmatic = true; private boolean declarative = true; @Inject public void setActionValidatorManager(ActionValidatorManager mgr) { this.actionValidatorManager = mgr; } /** * Determines if {@link Validateable}'s validate() should be called, * as well as methods whose name that start with "validate". Defaults to "true". * * @param programmatic true then validate() is invoked. */ public void setProgrammatic(boolean programmatic) { this.programmatic = programmatic; } /** * Determines if validation based on annotations or xml should be performed. Defaults * to "true". * * @param declarative true then perform validation based on annotations or xml. */ public void setDeclarative(boolean declarative) { this.declarative = declarative; } /** * Determines if {@link Validateable}'s validate() should always * be invoked. Default to "true". * * @param alwaysInvokeValidate true then validate() is always invoked. */ public void setAlwaysInvokeValidate(String alwaysInvokeValidate) { this.alwaysInvokeValidate = Boolean.parseBoolean(alwaysInvokeValidate); } /** * Gets if validate() should always be called or only per annotated method. * * @return true to only validate per annotated method, otherwise false to always validate. */ public boolean isValidateAnnotatedMethodOnly() { return validateAnnotatedMethodOnly; } /** * Determine if validate() should always be called or only per annotated method. * Default to false. * * @param validateAnnotatedMethodOnly true to only validate per annotated method, otherwise false to always validate. */ public void setValidateAnnotatedMethodOnly(boolean validateAnnotatedMethodOnly) { this.validateAnnotatedMethodOnly = validateAnnotatedMethodOnly; } /** * Gets the current action and its context and delegates to {@link ActionValidatorManager} proper validate method. * * @param invocation the execution state of the Action. * @throws Exception if an error occurs validating the action. */ protected void doBeforeInvocation(ActionInvocation invocation) throws Exception { Object action = invocation.getAction(); ActionProxy proxy = invocation.getProxy(); //the action name has to be from the url, otherwise validators that use aliases, like //MyActio-someaction-validator.xml will not be found, see WW-3194 //UPDATE: see WW-3753 String context = this.getValidationContext(proxy); String method = proxy.getMethod(); if (LOG.isDebugEnabled()) { LOG.debug("Validating {}/{} with method {}.", invocation.getProxy().getNamespace(), invocation.getProxy().getActionName(), method); } if (declarative) { if (validateAnnotatedMethodOnly) { actionValidatorManager.validate(action, context, method); } else { actionValidatorManager.validate(action, context); } } if (action instanceof Validateable && programmatic) { // keep exception that might occured in validateXXX or validateDoXXX Exception exception = null; Validateable validateable = (Validateable) action; LOG.debug("Invoking validate() on action {}", validateable); try { PrefixMethodInvocationUtil.invokePrefixMethod(invocation, new String[]{VALIDATE_PREFIX, ALT_VALIDATE_PREFIX}); } catch(Exception e) { // If any exception occurred while doing reflection, we want // validate() to be executed LOG.warn("an exception occured while executing the prefix method", e); exception = e; } if (alwaysInvokeValidate) { validateable.validate(); } if (exception != null) { // rethrow if something is wrong while doing validateXXX / validateDoXXX throw exception; } } } @Override protected String doIntercept(ActionInvocation invocation) throws Exception { doBeforeInvocation(invocation); return invocation.invoke(); } /** *

* Returns the context that will be used by the * {@link ActionValidatorManager} to associate the action invocation with * the appropriate {@link ValidatorConfig ValidatorConfigs}. *

* *

* The context returned is used in the pattern * ActionClass-context-validation.xml *

* *

* The default context is the action name from the URL, but the method can * be overridden to implement custom contexts. *

* *

* This can be useful in cases in which a single action and a single model * require vastly different validation based on some condition. *

* * @param proxy action proxy * @return the context (action name) */ protected String getValidationContext(ActionProxy proxy) { // This method created for WW-3753 return proxy.getActionName(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy