WW-3135 OVal Plugin doesn't add field errors for "subfields"

patch provided by rdk@

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@777502 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Musachy Barroso
2009-05-22 12:58:29 +00:00
parent c282bc85f5
commit e97d30adf6
7 changed files with 178 additions and 7 deletions
@@ -24,6 +24,7 @@ import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import com.opensymphony.xwork2.interceptor.PrefixMethodInvocationUtil;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Validateable;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.validator.ValidatorContext;
@@ -38,6 +39,9 @@ import net.sf.oval.context.FieldContext;
import net.sf.oval.context.OValContext;
import net.sf.oval.context.MethodReturnValueContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
@@ -167,7 +171,11 @@ public class OValValidationInterceptor extends MethodFilterInterceptor {
//perform validation
List<ConstraintViolation> violations = validator.validate(action);
if (violations != null) {
addValidationErrors(violations.toArray(new ConstraintViolation[0]), action, valueStack, null);
}
private void addValidationErrors(ConstraintViolation[] violations, Object action, ValueStack valueStack, String parentFieldname) {
if (violations != null) {
ValidatorContext validatorContext = new DelegatingValidatorContext(action);
for (ConstraintViolation violation : violations) {
//translate message
@@ -182,15 +190,34 @@ public class OValValidationInterceptor extends MethodFilterInterceptor {
valueStack.pop();
}
if (isActionError(violation))
if (isActionError(violation)) {
LOG.debug("Adding action error '#0'", message);
validatorContext.addActionError(message);
else {
} else {
ValidationError validationError = buildValidationError(violation, message);
validatorContext.addFieldError(validationError.getFieldName(), validationError.getMessage());
// build field name
String fieldName = validationError.getFieldName();
if (parentFieldname != null) {
fieldName = parentFieldname + "." + fieldName;
}
LOG.debug("Adding field error [#0] with message '#1'", fieldName, validationError.getMessage());
validatorContext.addFieldError(fieldName, validationError.getMessage());
// don't add "model." prefix to fields of model in model driven action
if ((action instanceof ModelDriven) && "model".equals(fieldName)) {
fieldName = null;
}
// add violations of member object fields
addValidationErrors(violation.getCauses(), action, valueStack, fieldName);
}
}
}
}
}
/**
@@ -0,0 +1,18 @@
package org.apache.struts2.oval.interceptor;
import net.sf.oval.constraint.AssertValid;
import org.apache.struts2.oval.interceptor.domain.Person;
import com.opensymphony.xwork2.ActionSupport;
public class MemberObject extends ActionSupport {
@AssertValid
private Person person = new Person();
public Person getPerson() {
return person;
}
}
@@ -0,0 +1,19 @@
package org.apache.struts2.oval.interceptor;
import net.sf.oval.constraint.AssertValid;
import org.apache.struts2.oval.interceptor.domain.Person;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class ModelDrivenAction extends ActionSupport implements ModelDriven<Person> {
@AssertValid
private Person model = new Person();
public Person getModel() {
return model;
}
}
@@ -82,7 +82,7 @@ public class OValValidationInterceptorTest extends XWorkTestCase {
public void testSlashesInNameWithWildcardsHitsCache() throws Exception {
ActionProxy baseActionProxy = actionProxyFactory.createActionProxy("oval", "simpleFieldsXML/test", null, null);
baseActionProxy.execute();
ActionProxy baseActionProxy2 = actionProxyFactory.createActionProxy("oval", "simpleFieldsXML/test2", null, null);
baseActionProxy2.execute();
@@ -247,6 +247,40 @@ public class OValValidationInterceptorTest extends XWorkTestCase {
}
public void testModelDrivenAction() throws Exception {
ActionProxy baseActionProxy = actionProxyFactory.createActionProxy("oval", "modelDrivenAction", null, null);
ModelDrivenAction action = (ModelDrivenAction) baseActionProxy.getAction();
action.getModel().setName(null);
action.getModel().setEmail(null);
action.getModel().getAddress().setStreet("short");
baseActionProxy.execute();
Map<String, List<String>> fieldErrors = ((ValidationAware) baseActionProxy.getAction()).getFieldErrors();
assertNotNull(fieldErrors);
assertEquals(5, fieldErrors.size()); // 5: as there will be field errors for 'model' and 'address' themselves
assertValue(fieldErrors, "name", Arrays.asList("name cannot be null"));
assertValue(fieldErrors, "email", Arrays.asList("email cannot be null"));
assertValue(fieldErrors, "address.street", Arrays.asList("street cannot be smaller than 7 characters"));
}
public void testMemberObject() throws Exception {
ActionProxy baseActionProxy = actionProxyFactory.createActionProxy("oval", "memberObject", null, null);
MemberObject action = (MemberObject) baseActionProxy.getAction();
action.getPerson().setName(null);
action.getPerson().setEmail(null);
action.getPerson().getAddress().setStreet("short");
baseActionProxy.execute();
Map<String, List<String>> fieldErrors = ((ValidationAware) baseActionProxy.getAction()).getFieldErrors();
assertNotNull(fieldErrors);
assertEquals(5, fieldErrors.size()); // 5: as there will be field errors for 'person' and 'person.address' themselves
assertValue(fieldErrors, "person.name", Arrays.asList("name cannot be null"));
assertValue(fieldErrors, "person.email", Arrays.asList("email cannot be null"));
assertValue(fieldErrors, "person.address.street", Arrays.asList("street cannot be smaller than 7 characters"));
}
private void assertValue(Map<String, List<String>> map, String key, List<String> expectedValues) {
assertNotNull(map);
assertNotNull(key);
@@ -0,0 +1,18 @@
package org.apache.struts2.oval.interceptor.domain;
import net.sf.oval.constraint.MinLength;
public class Address {
@MinLength(value=7)
private String street;
public void setStreet(String street) {
this.street = street;
}
public String getStreet() {
return street;
}
}
@@ -0,0 +1,43 @@
package org.apache.struts2.oval.interceptor.domain;
import javax.persistence.Column;
import net.sf.oval.constraint.AssertValid;
import net.sf.oval.constraint.NotNull;
public class Person {
@Column(nullable=false)
private String name;
@NotNull
private String email;
@AssertValid
private Address address = new Address();
public void setEmail(String email) {
this.email = email;
}
public String getEmail() {
return email;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAddress(Address address) {
this.address = address;
}
public Address getAddress() {
return address;
}
}
+13 -1
View File
@@ -7,7 +7,7 @@
<bean type="org.apache.struts2.oval.interceptor.OValValidationManager" class="org.apache.struts2.oval.interceptor.DummyDefaultOValValidationManager"/>
<constant name="struts.enable.SlashesInActionNames" value="true"/>
<constant name="struts.oval.validateJPAAnnotations" value="false" />
<package namespace="oval" name="oval-test">
<result-types>
<result-type name="void" class="org.apache.struts2.oval.interceptor.VoidResult"/>
@@ -82,5 +82,17 @@
</interceptor-ref>
<result type="void"></result>
</action>
<action name="modelDrivenAction" class="org.apache.struts2.oval.interceptor.ModelDrivenAction">
<interceptor-ref name="ovalValidation">
<param name="validateJPAAnnotations">true</param>
</interceptor-ref>
<result type="void"></result>
</action>
<action name="memberObject" class="org.apache.struts2.oval.interceptor.MemberObject">
<interceptor-ref name="ovalValidation">
<param name="validateJPAAnnotations">true</param>
</interceptor-ref>
<result type="void"></result>
</action>
</package>
</xwork>