Repository: struts Updated Branches: refs/heads/master afb0c2a22 -> ee562666a
Form.getValidators does not respect validateAnnotatedMethodOnly flag WW-4139 removed method name from getValidators call. While this works fine for a case mentioned in that ticket it fails to account for a case when dynamicMethodCalls and validateAnnotatedMethodOnly are used. Without method name actionValidatorManager.getValidators returns all validators defined for a given field. Expected behavior for dynamicMethodCalls with validateAnnotatedMethodOnly case is to return validators for a given field defined at the method level. Project: http://git-wip-us.apache.org/repos/asf/struts/repo Commit: http://git-wip-us.apache.org/repos/asf/struts/commit/ee562666 Tree: http://git-wip-us.apache.org/repos/asf/struts/tree/ee562666 Diff: http://git-wip-us.apache.org/repos/asf/struts/diff/ee562666 Branch: refs/heads/master Commit: ee562666abf01faf4dd73f65c9f4d77b079423d1 Parents: afb0c2a Author: Lukasz Racon <lra...@jgsullivan.com> Authored: Mon Nov 9 17:02:02 2015 -0600 Committer: Lukasz Racon <lra...@jgsullivan.com> Committed: Mon Nov 9 17:02:02 2015 -0600 ---------------------------------------------------------------------- .../org/apache/struts2/components/Form.java | 25 +++++++- .../java/org/apache/struts2/TestAction.java | 24 ++++++++ .../org/apache/struts2/components/FormTest.java | 60 +++++++++++++++++--- 3 files changed, 101 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/struts/blob/ee562666/core/src/main/java/org/apache/struts2/components/Form.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/struts2/components/Form.java b/core/src/main/java/org/apache/struts2/components/Form.java index 52aaa7c..6b2e478 100644 --- a/core/src/main/java/org/apache/struts2/components/Form.java +++ b/core/src/main/java/org/apache/struts2/components/Form.java @@ -35,6 +35,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.struts2.dispatcher.mapper.ActionMapping; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.views.jsp.TagUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -277,7 +278,12 @@ public class Form extends ClosingUIBean { ActionMapping mapping = actionMapper.getMappingFromActionName(formActionValue); String actionName = mapping.getName(); - List<Validator> actionValidators = actionValidatorManager.getValidators(actionClass, actionName); + String methodName = null; + if (isValidateAnnotatedMethodOnly(actionName)) { + methodName = mapping.getMethod(); + } + + List<Validator> actionValidators = actionValidatorManager.getValidators(actionClass, actionName, methodName); List<Validator> validators = new ArrayList<>(); findFieldValidators(name, actionClass, actionName, actionValidators, validators, ""); @@ -285,6 +291,23 @@ public class Form extends ClosingUIBean { return validators; } + private boolean isValidateAnnotatedMethodOnly(String actionName) { + RuntimeConfiguration runtimeConfiguration = configuration.getRuntimeConfiguration(); + String actionNamespace = TagUtils.buildNamespace(actionMapper, stack, request); + ActionConfig actionConfig = runtimeConfiguration.getActionConfig(actionNamespace, actionName); + + if (actionConfig != null) { + List<InterceptorMapping> interceptors = actionConfig.getInterceptors(); + for (InterceptorMapping interceptorMapping : interceptors) { + if (ValidationInterceptor.class.isInstance(interceptorMapping.getInterceptor())) { + ValidationInterceptor validationInterceptor = (ValidationInterceptor) interceptorMapping.getInterceptor(); + return validationInterceptor.isValidateAnnotatedMethodOnly(); + } + } + } + return false; + } + private void findFieldValidators(String name, Class actionClass, String actionName, List<Validator> validatorList, List<Validator> resultValidators, String prefix) { http://git-wip-us.apache.org/repos/asf/struts/blob/ee562666/core/src/test/java/org/apache/struts2/TestAction.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/struts2/TestAction.java b/core/src/test/java/org/apache/struts2/TestAction.java index dde13e5..8d87588 100644 --- a/core/src/test/java/org/apache/struts2/TestAction.java +++ b/core/src/test/java/org/apache/struts2/TestAction.java @@ -24,6 +24,10 @@ package org.apache.struts2; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.validator.annotations.RequiredFieldValidator; +import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator; +import com.opensymphony.xwork2.validator.annotations.Validations; +import com.opensymphony.xwork2.validator.annotations.ValidatorType; import org.apache.struts2.views.jsp.ui.User; import java.util.*; @@ -177,6 +181,26 @@ public class TestAction extends ActionSupport { return result; } + @Validations( + requiredFields = { + @RequiredFieldValidator(type = ValidatorType.SIMPLE, fieldName = "status", message = "You must enter a value for field.") + }, + requiredStrings = { + @RequiredStringValidator(type = ValidatorType.SIMPLE, fieldName = "result", message = "You must enter a value for field.") + } + ) + public String annotatedExecute1() throws Exception { + return Action.SUCCESS; + } + @Validations( + requiredFields = { + @RequiredFieldValidator(type = ValidatorType.SIMPLE, fieldName = "status", message = "You must enter a value for field.") + } + ) + public String annotatedExecute2() throws Exception { + return Action.SUCCESS; + } + public String executeThrowsException() throws Exception { throw new StrutsException("something went wrong!"); } http://git-wip-us.apache.org/repos/asf/struts/blob/ee562666/core/src/test/java/org/apache/struts2/components/FormTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/struts2/components/FormTest.java b/core/src/test/java/org/apache/struts2/components/FormTest.java index f1611f2..86148f7 100644 --- a/core/src/test/java/org/apache/struts2/components/FormTest.java +++ b/core/src/test/java/org/apache/struts2/components/FormTest.java @@ -26,35 +26,76 @@ import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.ActionProxy; import com.opensymphony.xwork2.config.entities.ActionConfig; +import com.opensymphony.xwork2.config.entities.InterceptorMapping; +import com.opensymphony.xwork2.validator.ValidationInterceptor; import com.opensymphony.xwork2.validator.validators.RequiredFieldValidator; +import com.opensymphony.xwork2.validator.validators.RequiredStringValidator; +import org.apache.struts2.dispatcher.mapper.ActionMapper; +import org.apache.struts2.dispatcher.mapper.DefaultActionMapper; import org.apache.struts2.TestAction; import org.apache.struts2.views.jsp.AbstractUITagTest; import org.easymock.EasyMock; import java.util.List; +import java.util.Map; /** * <code>FormTest</code> * */ public class FormTest extends AbstractUITagTest { - + private ValidationInterceptor validationInterceptor; public void testTestFormGetValidators() { - Form form = new Form(stack, request, response); + checkValidateAnnotatedMethodOnly(false, null, 1, 2, 1); + } + public void testAnnotatedFormGetValidators() { + checkValidateAnnotatedMethodOnly(true, null, 1, 2, 1); + } + public void testValidateAnnotatedMethodOnlyGetValidators1() { + checkValidateAnnotatedMethodOnly(true, "annotatedExecute1", 0, 1, 1); + } + public void testValidateAnnotatedMethodOnlyGetValidators2() { + checkValidateAnnotatedMethodOnly(true, "annotatedExecute2", 0, 1, 0); + } + + private void checkValidateAnnotatedMethodOnly(boolean validateAnnotatedMethodOnly, String methodName, + int expectedFooValidators, int expectedStatusValidators, int expectedResultValidators) { + Form form = new Form(stack, request, response); container.inject(form); form.getParameters().put("actionClass", TestAction.class); - form.setAction("actionName"); + + form.setAction("actionName" + (methodName != null ? "!" + methodName : "")); + validationInterceptor.setValidateAnnotatedMethodOnly(validateAnnotatedMethodOnly); + List v = form.getValidators("foo"); - assertEquals(1, v.size()); - assertEquals(RequiredFieldValidator.class, v.get(0).getClass()); - } + assertEquals(expectedFooValidators, v.size()); + for (Object validator : v) { + assertEquals(RequiredFieldValidator.class, validator.getClass()); + } + + v = form.getValidators("status"); + assertEquals(expectedStatusValidators, v.size()); + for (Object validator : v) { + assertEquals(RequiredFieldValidator.class, validator.getClass()); + } + + v = form.getValidators("result"); + assertEquals(expectedResultValidators, v.size()); + for (Object validator : v) { + assertEquals(RequiredStringValidator.class, validator.getClass()); + } + } @Override protected void setUp() throws Exception { super.setUp(); + validationInterceptor = new ValidationInterceptor(); + validationInterceptor.setIncludeMethods("*"); - ActionConfig config = new ActionConfig.Builder("", "name", "").build(); + ActionConfig config = new ActionConfig.Builder("", "name", "") + .addInterceptor(new InterceptorMapping("validationInterceptor", validationInterceptor)) + .build(); ActionInvocation invocation = EasyMock.createNiceMock(ActionInvocation.class); ActionProxy proxy = EasyMock.createNiceMock(ActionProxy.class); @@ -66,6 +107,11 @@ public class FormTest extends AbstractUITagTest { EasyMock.replay(invocation); EasyMock.replay(proxy); + + Map<String, ActionConfig> defaultNamespace = configuration.getRuntimeConfiguration().getActionConfigs().get(""); + defaultNamespace.put("actionName", config); + + ((DefaultActionMapper) container.getInstance(ActionMapper.class)).setAllowDynamicMethodCalls("true"); ActionContext.getContext().setActionInvocation(invocation); }