LocalValidatorFactoryBean properly supports unwrap at ValidatorFactory level
Issue: SPR-15561
(cherry picked from commit cb3d1be)
This commit is contained in:
parent
22bf9febcc
commit
ac25db6d2b
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
|
|
@ -31,6 +31,7 @@ import javax.validation.ConstraintValidatorFactory;
|
|||
import javax.validation.MessageInterpolator;
|
||||
import javax.validation.TraversableResolver;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.ValidationException;
|
||||
import javax.validation.ValidationProviderResolver;
|
||||
import javax.validation.Validator;
|
||||
import javax.validation.ValidatorContext;
|
||||
|
|
@ -74,6 +75,7 @@ import org.springframework.util.ReflectionUtils;
|
|||
* instead. If you really need programmatic {@code #forExecutables} access, inject this class as
|
||||
* a {@link ValidatorFactory} and call {@link #getValidator()} on it, then {@code #forExecutables}
|
||||
* on the returned native {@link Validator} reference instead of directly on this class.
|
||||
* Alternatively, call {@code #unwrap(Validator.class) which will also provide the native object.
|
||||
*
|
||||
* <p>This class is also being used by Spring's MVC configuration namespace, in case of the
|
||||
* {@code javax.validation} API being present but no explicit Validator having been configured.
|
||||
|
|
@ -397,6 +399,30 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
|
|||
return this.validatorFactory.getConstraintValidatorFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T unwrap(Class<T> type) {
|
||||
if (type == null || !ValidatorFactory.class.isAssignableFrom(type)) {
|
||||
try {
|
||||
return super.unwrap(type);
|
||||
}
|
||||
catch (ValidationException ex) {
|
||||
// ignore - we'll try ValidatorFactory unwrapping next
|
||||
}
|
||||
}
|
||||
try {
|
||||
return this.validatorFactory.unwrap(type);
|
||||
}
|
||||
catch (ValidationException ex) {
|
||||
// ignore if just being asked for ValidatorFactory
|
||||
if (ValidatorFactory.class == type) {
|
||||
return (T) this.validatorFactory;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void close() {
|
||||
if (closeMethod != null && this.validatorFactory != null) {
|
||||
ReflectionUtils.invokeMethod(closeMethod, this.validatorFactory);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import javax.validation.ConstraintValidator;
|
|||
import javax.validation.ConstraintValidatorContext;
|
||||
import javax.validation.Payload;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
|
|
@ -51,8 +52,9 @@ import static org.junit.Assert.*;
|
|||
*/
|
||||
public class SpringValidatorAdapterTests {
|
||||
|
||||
private final SpringValidatorAdapter validatorAdapter = new SpringValidatorAdapter(
|
||||
Validation.buildDefaultValidatorFactory().getValidator());
|
||||
private final Validator nativeValidator = Validation.buildDefaultValidatorFactory().getValidator();
|
||||
|
||||
private final SpringValidatorAdapter validatorAdapter = new SpringValidatorAdapter(nativeValidator);
|
||||
|
||||
private final StaticMessageSource messageSource = new StaticMessageSource();
|
||||
|
||||
|
|
@ -66,6 +68,12 @@ public class SpringValidatorAdapterTests {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testUnwrap() {
|
||||
Validator nativeValidator = validatorAdapter.unwrap(Validator.class);
|
||||
assertSame(this.nativeValidator, nativeValidator);
|
||||
}
|
||||
|
||||
@Test // SPR-13406
|
||||
public void testNoStringArgumentValue() {
|
||||
TestBean testBean = new TestBean();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
|
|
@ -33,11 +33,18 @@ import javax.validation.ConstraintValidatorContext;
|
|||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Payload;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.Validator;
|
||||
import javax.validation.ValidatorFactory;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.hibernate.validator.HibernateValidator;
|
||||
import org.hibernate.validator.HibernateValidatorFactory;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.validation.BeanPropertyBindingResult;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.FieldError;
|
||||
|
|
@ -47,10 +54,9 @@ import static org.hamcrest.Matchers.*;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tested against Hibernate Validator 4.3, as of Spring 4.0.
|
||||
* Tests against Hibernate Validator 5.x.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class ValidatorFactoryTests {
|
||||
|
||||
|
|
@ -58,6 +64,7 @@ public class ValidatorFactoryTests {
|
|||
public void testSimpleValidation() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
Set<ConstraintViolation<ValidPerson>> result = validator.validate(person);
|
||||
assertEquals(2, result.size());
|
||||
|
|
@ -70,6 +77,12 @@ public class ValidatorFactoryTests {
|
|||
fail("Invalid constraint violation with path '" + path + "'");
|
||||
}
|
||||
}
|
||||
|
||||
Validator nativeValidator = validator.unwrap(Validator.class);
|
||||
assertTrue(nativeValidator.getClass().getName().startsWith("org.hibernate"));
|
||||
assertTrue(validator.unwrap(ValidatorFactory.class) instanceof HibernateValidatorFactory);
|
||||
assertTrue(validator.unwrap(HibernateValidatorFactory.class) instanceof HibernateValidatorFactory);
|
||||
|
||||
validator.destroy();
|
||||
}
|
||||
|
||||
|
|
@ -78,6 +91,7 @@ public class ValidatorFactoryTests {
|
|||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.setProviderClass(HibernateValidator.class);
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
Set<ConstraintViolation<ValidPerson>> result = validator.validate(person);
|
||||
assertEquals(2, result.size());
|
||||
|
|
@ -90,6 +104,12 @@ public class ValidatorFactoryTests {
|
|||
fail("Invalid constraint violation with path '" + path + "'");
|
||||
}
|
||||
}
|
||||
|
||||
Validator nativeValidator = validator.unwrap(Validator.class);
|
||||
assertTrue(nativeValidator.getClass().getName().startsWith("org.hibernate"));
|
||||
assertTrue(validator.unwrap(ValidatorFactory.class) instanceof HibernateValidatorFactory);
|
||||
assertTrue(validator.unwrap(HibernateValidatorFactory.class) instanceof HibernateValidatorFactory);
|
||||
|
||||
validator.destroy();
|
||||
}
|
||||
|
||||
|
|
@ -112,6 +132,7 @@ public class ValidatorFactoryTests {
|
|||
public void testSpringValidationFieldType() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.setName("Phil");
|
||||
person.getAddress().setStreet("Phil's Street");
|
||||
|
|
@ -126,6 +147,7 @@ public class ValidatorFactoryTests {
|
|||
public void testSpringValidation() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
|
||||
validator.validate(person, result);
|
||||
|
|
@ -153,6 +175,7 @@ public class ValidatorFactoryTests {
|
|||
public void testSpringValidationWithClassLevel() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.setName("Juergen");
|
||||
person.getAddress().setStreet("Juergen's Street");
|
||||
|
|
@ -166,10 +189,32 @@ public class ValidatorFactoryTests {
|
|||
assertTrue(errorCodes.contains("NameAddressValid"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithAutowiredValidator() throws Exception {
|
||||
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(
|
||||
LocalValidatorFactoryBean.class);
|
||||
LocalValidatorFactoryBean validator = ctx.getBean(LocalValidatorFactoryBean.class);
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.expectsAutowiredValidator = true;
|
||||
person.setName("Juergen");
|
||||
person.getAddress().setStreet("Juergen's Street");
|
||||
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
|
||||
validator.validate(person, result);
|
||||
assertEquals(1, result.getErrorCount());
|
||||
ObjectError globalError = result.getGlobalError();
|
||||
List<String> errorCodes = Arrays.asList(globalError.getCodes());
|
||||
assertEquals(2, errorCodes.size());
|
||||
assertTrue(errorCodes.contains("NameAddressValid.person"));
|
||||
assertTrue(errorCodes.contains("NameAddressValid"));
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationWithErrorInListElement() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.getAddressList().add(new ValidAddress());
|
||||
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
|
||||
|
|
@ -187,6 +232,7 @@ public class ValidatorFactoryTests {
|
|||
public void testSpringValidationWithErrorInSetElement() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.getAddressSet().add(new ValidAddress());
|
||||
BeanPropertyBindingResult result = new BeanPropertyBindingResult(person, "person");
|
||||
|
|
@ -235,10 +281,12 @@ public class ValidatorFactoryTests {
|
|||
private ValidAddress address = new ValidAddress();
|
||||
|
||||
@Valid
|
||||
private List<ValidAddress> addressList = new LinkedList<ValidAddress>();
|
||||
private List<ValidAddress> addressList = new LinkedList<>();
|
||||
|
||||
@Valid
|
||||
private Set<ValidAddress> addressSet = new LinkedHashSet<ValidAddress>();
|
||||
private Set<ValidAddress> addressSet = new LinkedHashSet<>();
|
||||
|
||||
public boolean expectsAutowiredValidator = false;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
|
|
@ -304,12 +352,18 @@ public class ValidatorFactoryTests {
|
|||
|
||||
public static class NameAddressValidator implements ConstraintValidator<NameAddressValid, ValidPerson> {
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Override
|
||||
public void initialize(NameAddressValid constraintAnnotation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(ValidPerson value, ConstraintValidatorContext context) {
|
||||
if (value.expectsAutowiredValidator) {
|
||||
assertNotNull(this.environment);
|
||||
}
|
||||
boolean valid = (value.name == null || !value.address.street.contains(value.name));
|
||||
if (!valid && "Phil".equals(value.name)) {
|
||||
context.buildConstraintViolationWithTemplate(
|
||||
|
|
@ -378,7 +432,7 @@ public class ValidatorFactoryTests {
|
|||
public boolean isValid(InnerBean bean, ConstraintValidatorContext context) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
if (bean.getValue() == null) {
|
||||
context.buildConstraintViolationWithTemplate("NULL"). addNode("value").addConstraintViolation();
|
||||
context.buildConstraintViolationWithTemplate("NULL").addNode("value").addConstraintViolation();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2017 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.
|
||||
|
|
@ -33,9 +33,12 @@ import javax.validation.ConstraintValidatorContext;
|
|||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Payload;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.Validator;
|
||||
import javax.validation.ValidatorFactory;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.hibernate.validator.HibernateValidator;
|
||||
import org.hibernate.validator.HibernateValidatorFactory;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -77,6 +80,12 @@ public class ValidatorFactoryTests {
|
|||
fail("Invalid constraint violation with path '" + path + "'");
|
||||
}
|
||||
}
|
||||
|
||||
Validator nativeValidator = validator.unwrap(Validator.class);
|
||||
assertTrue(nativeValidator.getClass().getName().startsWith("org.hibernate"));
|
||||
assertTrue(validator.unwrap(ValidatorFactory.class) instanceof HibernateValidatorFactory);
|
||||
assertTrue(validator.unwrap(HibernateValidatorFactory.class) instanceof HibernateValidatorFactory);
|
||||
|
||||
validator.destroy();
|
||||
}
|
||||
|
||||
|
|
@ -98,6 +107,12 @@ public class ValidatorFactoryTests {
|
|||
fail("Invalid constraint violation with path '" + path + "'");
|
||||
}
|
||||
}
|
||||
|
||||
Validator nativeValidator = validator.unwrap(Validator.class);
|
||||
assertTrue(nativeValidator.getClass().getName().startsWith("org.hibernate"));
|
||||
assertTrue(validator.unwrap(ValidatorFactory.class) instanceof HibernateValidatorFactory);
|
||||
assertTrue(validator.unwrap(HibernateValidatorFactory.class) instanceof HibernateValidatorFactory);
|
||||
|
||||
validator.destroy();
|
||||
}
|
||||
|
||||
|
|
@ -269,10 +284,10 @@ public class ValidatorFactoryTests {
|
|||
private ValidAddress address = new ValidAddress();
|
||||
|
||||
@Valid
|
||||
private List<ValidAddress> addressList = new LinkedList<ValidAddress>();
|
||||
private List<ValidAddress> addressList = new LinkedList<>();
|
||||
|
||||
@Valid
|
||||
private Set<ValidAddress> addressSet = new LinkedHashSet<ValidAddress>();
|
||||
private Set<ValidAddress> addressSet = new LinkedHashSet<>();
|
||||
|
||||
public boolean expectsAutowiredValidator = false;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue