SpringValidationAdapter properly detects invalid value for JSR-303 field-level bean constraints
Issue: SPR-9332
This commit is contained in:
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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);
|
FieldError fieldError = errors.getFieldError(field);
|
||||||
if (fieldError == null || !fieldError.isBindingFailure()) {
|
if (fieldError == null || !fieldError.isBindingFailure()) {
|
||||||
try {
|
try {
|
||||||
String errorCode = violation.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName();
|
ConstraintDescriptor<?> cd = violation.getConstraintDescriptor();
|
||||||
Object[] errorArgs = getArgumentsForConstraint(errors.getObjectName(), field, violation.getConstraintDescriptor());
|
String errorCode = cd.getAnnotation().annotationType().getSimpleName();
|
||||||
|
Object[] errorArgs = getArgumentsForConstraint(errors.getObjectName(), field, cd);
|
||||||
if (errors instanceof BindingResult) {
|
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)
|
// as necessary for Hibernate Validator compatibility (non-indexed set path in field)
|
||||||
BindingResult bindingResult = (BindingResult) errors;
|
BindingResult bindingResult = (BindingResult) errors;
|
||||||
String nestedField = bindingResult.getNestedPath() + field;
|
String nestedField = bindingResult.getNestedPath() + field;
|
||||||
@@ -128,8 +130,9 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Object invalidValue = violation.getInvalidValue();
|
Object invalidValue = violation.getInvalidValue();
|
||||||
if (!"".equals(field) && invalidValue == violation.getLeafBean()) {
|
if (field.contains(".") && !field.contains("[]")) {
|
||||||
// bean constraint with property path: retrieve the actual property value
|
// 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);
|
invalidValue = bindingResult.getRawFieldValue(field);
|
||||||
}
|
}
|
||||||
String[] errorCodes = bindingResult.resolveMessageCodes(errorCode, 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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.ConstraintValidator;
|
||||||
import javax.validation.ConstraintValidatorContext;
|
import javax.validation.ConstraintValidatorContext;
|
||||||
import javax.validation.ConstraintViolation;
|
import javax.validation.ConstraintViolation;
|
||||||
|
import javax.validation.Payload;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ import org.hibernate.validator.HibernateValidator;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.validation.BeanPropertyBindingResult;
|
import org.springframework.validation.BeanPropertyBindingResult;
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
import org.springframework.validation.FieldError;
|
import org.springframework.validation.FieldError;
|
||||||
import org.springframework.validation.ObjectError;
|
import org.springframework.validation.ObjectError;
|
||||||
|
|
||||||
@@ -193,6 +195,18 @@ public class ValidatorFactoryTests {
|
|||||||
System.out.println(fieldError.getDefaultMessage());
|
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
|
@NameAddressValid
|
||||||
public static class ValidPerson {
|
public static class ValidPerson {
|
||||||
@@ -242,7 +256,6 @@ public class ValidatorFactoryTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class ValidAddress {
|
public static class ValidAddress {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -257,7 +270,6 @@ public class ValidatorFactoryTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Constraint(validatedBy = NameAddressValidator.class)
|
@Constraint(validatedBy = NameAddressValidator.class)
|
||||||
@@ -270,7 +282,6 @@ public class ValidatorFactoryTests {
|
|||||||
Class<?>[] payload() default {};
|
Class<?>[] payload() default {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class NameAddressValidator implements ConstraintValidator<NameAddressValid, ValidPerson> {
|
public static class NameAddressValidator implements ConstraintValidator<NameAddressValid, ValidPerson> {
|
||||||
|
|
||||||
@Override
|
@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user