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.
This commit is contained in:
Lukasz Racon
2015-11-09 17:02:02 -06:00
parent afb0c2a228
commit ee562666ab
3 changed files with 101 additions and 8 deletions
@@ -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) {
@@ -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!");
}
@@ -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);
}