SpringValidationAdapter properly detects invalid value for JSR-303 field-level bean constraints
Issue: SPR-9332
This commit is contained in:
parent
5a773b771d
commit
8e75eee9b2
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -99,7 +99,8 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
|
|||
}
|
||||
}
|
||||
}
|
||||
processConstraintViolations(this.targetValidator.validate(target, groups.toArray(new Class[groups.size()])), errors);
|
||||
processConstraintViolations(
|
||||
this.targetValidator.validate(target, groups.toArray(new Class[groups.size()])), errors);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -114,10 +115,11 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
|
|||
FieldError fieldError = errors.getFieldError(field);
|
||||
if (fieldError == null || !fieldError.isBindingFailure()) {
|
||||
try {
|
||||
String errorCode = violation.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName();
|
||||
Object[] errorArgs = getArgumentsForConstraint(errors.getObjectName(), field, violation.getConstraintDescriptor());
|
||||
ConstraintDescriptor<?> cd = violation.getConstraintDescriptor();
|
||||
String errorCode = cd.getAnnotation().annotationType().getSimpleName();
|
||||
Object[] errorArgs = getArgumentsForConstraint(errors.getObjectName(), field, cd);
|
||||
if (errors instanceof BindingResult) {
|
||||
// can do custom FieldError registration with invalid value from ConstraintViolation,
|
||||
// Can do custom FieldError registration with invalid value from ConstraintViolation,
|
||||
// as necessary for Hibernate Validator compatibility (non-indexed set path in field)
|
||||
BindingResult bindingResult = (BindingResult) errors;
|
||||
String nestedField = bindingResult.getNestedPath() + field;
|
||||
|
|
@ -128,8 +130,9 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
|
|||
}
|
||||
else {
|
||||
Object invalidValue = violation.getInvalidValue();
|
||||
if (!"".equals(field) && invalidValue == violation.getLeafBean()) {
|
||||
// bean constraint with property path: retrieve the actual property value
|
||||
if (field.contains(".") && !field.contains("[]")) {
|
||||
// Possibly a bean constraint with property path: retrieve the actual property value.
|
||||
// However, explicitly avoid this for "address[]" style paths that we can't handle.
|
||||
invalidValue = bindingResult.getRawFieldValue(field);
|
||||
}
|
||||
String[] errorCodes = bindingResult.resolveMessageCodes(errorCode, field);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -30,6 +30,7 @@ import javax.validation.Constraint;
|
|||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Payload;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
|
|
@ -37,6 +38,7 @@ import org.hibernate.validator.HibernateValidator;
|
|||
import org.junit.Test;
|
||||
|
||||
import org.springframework.validation.BeanPropertyBindingResult;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.validation.ObjectError;
|
||||
|
||||
|
|
@ -193,6 +195,18 @@ public class ValidatorFactoryTests {
|
|||
System.out.println(fieldError.getDefaultMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInnerBeanValidation() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
MainBean mainBean = new MainBean();
|
||||
Errors errors = new BeanPropertyBindingResult(mainBean, "mainBean");
|
||||
validator.validate(mainBean, errors);
|
||||
Object rejected = errors.getFieldValue("inner.value");
|
||||
assertNull(rejected);
|
||||
}
|
||||
|
||||
|
||||
@NameAddressValid
|
||||
public static class ValidPerson {
|
||||
|
|
@ -242,7 +256,6 @@ public class ValidatorFactoryTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class ValidAddress {
|
||||
|
||||
@NotNull
|
||||
|
|
@ -257,7 +270,6 @@ public class ValidatorFactoryTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Constraint(validatedBy = NameAddressValidator.class)
|
||||
|
|
@ -270,7 +282,6 @@ public class ValidatorFactoryTests {
|
|||
Class<?>[] payload() default {};
|
||||
}
|
||||
|
||||
|
||||
public static class NameAddressValidator implements ConstraintValidator<NameAddressValid, ValidPerson> {
|
||||
|
||||
@Override
|
||||
|
|
@ -283,4 +294,53 @@ public class ValidatorFactoryTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class MainBean {
|
||||
|
||||
@InnerValid
|
||||
private InnerBean inner = new InnerBean();
|
||||
|
||||
public InnerBean getInner() {
|
||||
return inner;
|
||||
}
|
||||
}
|
||||
|
||||
public static class InnerBean {
|
||||
|
||||
private String value;
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
@Constraint(validatedBy=InnerValidator.class)
|
||||
public static @interface InnerValid {
|
||||
String message() default "NOT VALID";
|
||||
Class<?>[] groups() default { };
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
}
|
||||
|
||||
public static class InnerValidator implements ConstraintValidator<InnerValid, InnerBean> {
|
||||
|
||||
@Override
|
||||
public void initialize(InnerValid constraintAnnotation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(InnerBean bean, ConstraintValidatorContext context) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
if (bean.getValue() == null) {
|
||||
context.buildConstraintViolationWithTemplate("NULL"). addNode("value").addConstraintViolation();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue