Skip to content

Commit

Permalink
Form.getValidators does not respect validateAnnotatedMethodOnly flag
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
elqr committed Nov 9, 2015
1 parent afb0c2a commit ee56266
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 8 deletions.
25 changes: 24 additions & 1 deletion core/src/main/java/org/apache/struts2/components/Form.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
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;
Expand Down Expand Up @@ -277,14 +278,36 @@ public List getValidators(String name) {
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, "");

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) {

Expand Down
24 changes: 24 additions & 0 deletions core/src/test/java/org/apache/struts2/TestAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
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.*;
Expand Down Expand Up @@ -177,6 +181,26 @@ public String execute() throws Exception {
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!");
}
Expand Down
60 changes: 53 additions & 7 deletions core/src/test/java/org/apache/struts2/components/FormTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,35 +26,76 @@
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);

Expand All @@ -66,6 +107,11 @@ protected void setUp() throws Exception {

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);
}
Expand Down

0 comments on commit ee56266

Please sign in to comment.