LocalValidatorFactoryBean properly supports unwrap at ValidatorFactory level
Also documents limitation for Bean Validation 2.0's getClockProvider() method. Issue: SPR-15561 Issue: SPR-13482
This commit is contained in:
parent
67881a5726
commit
cb3d1befcd
|
@ -30,6 +30,7 @@ import javax.validation.MessageInterpolator;
|
|||
import javax.validation.ParameterNameProvider;
|
||||
import javax.validation.TraversableResolver;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.ValidationException;
|
||||
import javax.validation.ValidationProviderResolver;
|
||||
import javax.validation.Validator;
|
||||
import javax.validation.ValidatorContext;
|
||||
|
@ -64,8 +65,12 @@ import org.springframework.util.ReflectionUtils;
|
|||
* you will almost always use the default Validator anyway. This can also be injected directly
|
||||
* into any target dependency of type {@link org.springframework.validation.Validator}!
|
||||
*
|
||||
* <p><b>As of Spring 5.0, this class requires Bean Validation 1.1, with special support
|
||||
* <p><b>As of Spring 5.0, this class requires Bean Validation 1.1+, with special support
|
||||
* for Hibernate Validator 5.x</b> (see {@link #setValidationMessageSource}).
|
||||
* This class is also runtime-compatible with Bean Validation 2.0 and Hibernate Validator 6.0,
|
||||
* with one special note: If you'd like to call BV 2.0's {@code getClockProvider()} method,
|
||||
* obtain the native {@code ValidatorFactory} through {@code #unwrap(ValidatorFactory.class)}
|
||||
* and call the {@code getClockProvider()} method on the returned native reference there.
|
||||
*
|
||||
* <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.
|
||||
|
@ -293,7 +298,6 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
|
|||
}
|
||||
|
||||
private void configureParameterNameProviderIfPossible(Configuration<?> configuration) {
|
||||
// TODO: inner class
|
||||
final ParameterNameDiscoverer discoverer = this.parameterNameDiscoverer;
|
||||
final ParameterNameProvider defaultProvider = configuration.getDefaultParameterNameProvider();
|
||||
configuration.parameterNameProvider(new ParameterNameProvider() {
|
||||
|
@ -359,6 +363,32 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
|
|||
return this.validatorFactory.getParameterNameProvider();
|
||||
}
|
||||
|
||||
// Bean Validation 2.0: currently not implemented here since it would imply
|
||||
// a hard dependency on the new javax.validation.ClockProvider interface.
|
||||
// To be resolved once Spring Framework requires Bean Validation 2.0+.
|
||||
// Obtain the native ValidatorFactory through unwrap(ValidatorFactory.class)
|
||||
// instead which will fully support a getClockProvider() call as well.
|
||||
/*
|
||||
@Override
|
||||
public javax.validation.ClockProvider getClockProvider() {
|
||||
Assert.notNull(this.validatorFactory, "No target ValidatorFactory set");
|
||||
return this.validatorFactory.getClockProvider();
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
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
|
||||
}
|
||||
}
|
||||
return this.validatorFactory.unwrap(type);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (this.validatorFactory != null) {
|
||||
this.validatorFactory.close();
|
||||
|
|
|
@ -40,13 +40,16 @@ import org.springframework.validation.ObjectError;
|
|||
import org.springframework.validation.SmartValidator;
|
||||
|
||||
/**
|
||||
* Adapter that takes a JSR-303 {@code javax.validator.Validator}
|
||||
* and exposes it as a Spring {@link org.springframework.validation.Validator}
|
||||
* Adapter that takes a JSR-303 {@code javax.validator.Validator} and
|
||||
* exposes it as a Spring {@link org.springframework.validation.Validator}
|
||||
* while also exposing the original JSR-303 Validator interface itself.
|
||||
*
|
||||
* <p>Can be used as a programmatic wrapper. Also serves as base class for
|
||||
* {@link CustomValidatorBean} and {@link LocalValidatorFactoryBean}.
|
||||
*
|
||||
* <p>As of Spring Framework 5.0, this adapter is fully compatible with
|
||||
* Bean Validation 1.1 as well as 2.0.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
@ -75,6 +78,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();
|
||||
}
|
||||
|
||||
|
@ -96,6 +105,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();
|
||||
}
|
||||
|
||||
|
@ -465,7 +480,7 @@ public class ValidatorFactoryTests {
|
|||
|
||||
String message() default "Should not be X";
|
||||
|
||||
Class<?>[] groups() default { };
|
||||
Class<?>[] groups() default {};
|
||||
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue