Unwrap SpringValidatorAdapter (e.g. CustomValidatorBean) to native Validator

Issue: SPR-15629
This commit is contained in:
Juergen Hoeller 2017-06-07 17:56:42 +02:00
parent 9cb9884533
commit 8330134757
2 changed files with 24 additions and 3 deletions

View File

@ -85,9 +85,13 @@ public class MethodValidationPostProcessor extends AbstractBeanFactoryAwareAdvis
* <p>Default is the default ValidatorFactory's default Validator.
*/
public void setValidator(Validator validator) {
// Unwrap to the native Validator with forExecutables support
if (validator instanceof LocalValidatorFactoryBean) {
this.validator = ((LocalValidatorFactoryBean) validator).getValidator();
}
else if (validator instanceof SpringValidatorAdapter) {
this.validator = validator.unwrap(Validator.class);
}
else {
this.validator = validator;
}

View File

@ -25,6 +25,8 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.validation.ConstraintViolation;
import javax.validation.ValidationException;
import javax.validation.Validator;
import javax.validation.metadata.BeanDescriptor;
import javax.validation.metadata.ConstraintDescriptor;
@ -39,13 +41,19 @@ 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>Note that Bean Validation 1.1's {@code #forExecutables} method isn't supported
* on this adapter: We do not expect that method to be called by application code;
* consider {@link MethodValidationInterceptor} instead. If you really need programmatic
* {@code #forExecutables} access, call {@code #unwrap(Validator.class) which will
* provide the native {@link Validator} object with {@code #forExecutables} support.
*
* @author Juergen Hoeller
* @since 3.0
*/
@ -297,7 +305,16 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
@SuppressWarnings("unchecked")
public <T> T unwrap(Class<T> type) {
Assert.state(this.targetValidator != null, "No target Validator set");
return (type != null ? this.targetValidator.unwrap(type) : (T) this.targetValidator);
try {
return (type != null ? this.targetValidator.unwrap(type) : (T) this.targetValidator);
}
catch (ValidationException ex) {
// ignore if just being asked for plain Validator
if (Validator.class == type) {
return (T) this.targetValidator;
}
throw ex;
}
}