Browse Source

Introduced OptionalValidatorFactoryBean for scenarios where the JSR-303 API is present but no Bean Validation Provider is available (used by the MVC namespace)

Issue: SPR-11272
pull/432/head
Juergen Hoeller 12 years ago
parent
commit
6a5a3c97ed
  1. 18
      spring-context/src/main/java/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.java
  2. 47
      spring-context/src/main/java/org/springframework/validation/beanvalidation/OptionalValidatorFactoryBean.java
  3. 27
      spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java
  4. 2
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java

18
spring-context/src/main/java/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.java

@ -45,6 +45,7 @@ import org.springframework.context.MessageSource;
import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
@ -84,6 +85,7 @@ import org.springframework.util.ReflectionUtils;
public class LocalValidatorFactoryBean extends SpringValidatorAdapter public class LocalValidatorFactoryBean extends SpringValidatorAdapter
implements ValidatorFactory, ApplicationContextAware, InitializingBean, DisposableBean { implements ValidatorFactory, ApplicationContextAware, InitializingBean, DisposableBean {
// Bean Validation 1.1 close() method available?
private static final Method closeMethod = ClassUtils.getMethodIfAvailable(ValidatorFactory.class, "close"); private static final Method closeMethod = ClassUtils.getMethodIfAvailable(ValidatorFactory.class, "close");
@ -214,10 +216,9 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
@Override @Override
@SuppressWarnings("unchecked")
public void afterPropertiesSet() { public void afterPropertiesSet() {
@SuppressWarnings("rawtypes") @SuppressWarnings({"rawtypes", "unchecked"})
Configuration configuration = (this.providerClass != null ? Configuration<?> configuration = (this.providerClass != null ?
Validation.byProvider(this.providerClass).configure() : Validation.byProvider(this.providerClass).configure() :
Validation.byDefaultProvider().configure()); Validation.byDefaultProvider().configure());
@ -240,7 +241,9 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
configuration.constraintValidatorFactory(targetConstraintValidatorFactory); configuration.constraintValidatorFactory(targetConstraintValidatorFactory);
} }
configureParameterNameProviderIfPossible(configuration); if (this.parameterNameDiscoverer != null) {
configureParameterNameProviderIfPossible(configuration);
}
if (this.mappingLocations != null) { if (this.mappingLocations != null) {
for (Resource location : this.mappingLocations) { for (Resource location : this.mappingLocations) {
@ -329,31 +332,36 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
@Override @Override
public Validator getValidator() { public Validator getValidator() {
Assert.notNull(this.validatorFactory, "No target ValidatorFactory set");
return this.validatorFactory.getValidator(); return this.validatorFactory.getValidator();
} }
@Override @Override
public ValidatorContext usingContext() { public ValidatorContext usingContext() {
Assert.notNull(this.validatorFactory, "No target ValidatorFactory set");
return this.validatorFactory.usingContext(); return this.validatorFactory.usingContext();
} }
@Override @Override
public MessageInterpolator getMessageInterpolator() { public MessageInterpolator getMessageInterpolator() {
Assert.notNull(this.validatorFactory, "No target ValidatorFactory set");
return this.validatorFactory.getMessageInterpolator(); return this.validatorFactory.getMessageInterpolator();
} }
@Override @Override
public TraversableResolver getTraversableResolver() { public TraversableResolver getTraversableResolver() {
Assert.notNull(this.validatorFactory, "No target ValidatorFactory set");
return this.validatorFactory.getTraversableResolver(); return this.validatorFactory.getTraversableResolver();
} }
@Override @Override
public ConstraintValidatorFactory getConstraintValidatorFactory() { public ConstraintValidatorFactory getConstraintValidatorFactory() {
Assert.notNull(this.validatorFactory, "No target ValidatorFactory set");
return this.validatorFactory.getConstraintValidatorFactory(); return this.validatorFactory.getConstraintValidatorFactory();
} }
public void close() { public void close() {
if (closeMethod != null) { if (closeMethod != null && this.validatorFactory != null) {
ReflectionUtils.invokeMethod(closeMethod, this.validatorFactory); ReflectionUtils.invokeMethod(closeMethod, this.validatorFactory);
} }
} }

47
spring-context/src/main/java/org/springframework/validation/beanvalidation/OptionalValidatorFactoryBean.java

@ -0,0 +1,47 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.validation.beanvalidation;
import javax.validation.ValidationException;
import org.apache.commons.logging.LogFactory;
/**
* {@link LocalValidatorFactoryBean} subclass that simply turns
* {@link org.springframework.validation.Validator} calls into no-ops
* in case of no Bean Validation provider being available.
*
* <p>This is the actual class used by Spring's MVC configuration namespace,
* in case of the {@code javax.validation} API being present but no explicit
* Validator having been configured.
*
* @author Juergen Hoeller
* @since 4.0.1
*/
public class OptionalValidatorFactoryBean extends LocalValidatorFactoryBean {
@Override
public void afterPropertiesSet() {
try {
super.afterPropertiesSet();
}
catch (ValidationException ex) {
LogFactory.getLog(getClass()).debug("Failed to set up a Bean Validation provider", ex);
}
}
}

27
spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java

@ -83,27 +83,31 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
@Override @Override
public boolean supports(Class<?> clazz) { public boolean supports(Class<?> clazz) {
return true; return (this.targetValidator != null);
} }
@Override @Override
public void validate(Object target, Errors errors) { public void validate(Object target, Errors errors) {
processConstraintViolations(this.targetValidator.validate(target), errors); if (this.targetValidator != null) {
processConstraintViolations(this.targetValidator.validate(target), errors);
}
} }
@Override @Override
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public void validate(Object target, Errors errors, Object... validationHints) { public void validate(Object target, Errors errors, Object... validationHints) {
Set<Class> groups = new LinkedHashSet<Class>(); if (this.targetValidator != null) {
if (validationHints != null) { Set<Class> groups = new LinkedHashSet<Class>();
for (Object hint : validationHints) { if (validationHints != null) {
if (hint instanceof Class) { for (Object hint : validationHints) {
groups.add((Class) hint); if (hint instanceof Class) {
groups.add((Class) hint);
}
} }
} }
processConstraintViolations(
this.targetValidator.validate(target, groups.toArray(new Class[groups.size()])), errors);
} }
processConstraintViolations(
this.targetValidator.validate(target, groups.toArray(new Class[groups.size()])), errors);
} }
/** /**
@ -200,11 +204,13 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
@Override @Override
public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) { public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {
Assert.notNull(this.targetValidator, "No target Validator set");
return this.targetValidator.validate(object, groups); return this.targetValidator.validate(object, groups);
} }
@Override @Override
public <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, Class<?>... groups) { public <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, Class<?>... groups) {
Assert.notNull(this.targetValidator, "No target Validator set");
return this.targetValidator.validateProperty(object, propertyName, groups); return this.targetValidator.validateProperty(object, propertyName, groups);
} }
@ -212,16 +218,19 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
public <T> Set<ConstraintViolation<T>> validateValue( public <T> Set<ConstraintViolation<T>> validateValue(
Class<T> beanType, String propertyName, Object value, Class<?>... groups) { Class<T> beanType, String propertyName, Object value, Class<?>... groups) {
Assert.notNull(this.targetValidator, "No target Validator set");
return this.targetValidator.validateValue(beanType, propertyName, value, groups); return this.targetValidator.validateValue(beanType, propertyName, value, groups);
} }
@Override @Override
public BeanDescriptor getConstraintsForClass(Class<?> clazz) { public BeanDescriptor getConstraintsForClass(Class<?> clazz) {
Assert.notNull(this.targetValidator, "No target Validator set");
return this.targetValidator.getConstraintsForClass(clazz); return this.targetValidator.getConstraintsForClass(clazz);
} }
@Override @Override
public <T> T unwrap(Class<T> type) { public <T> T unwrap(Class<T> type) {
Assert.notNull(this.targetValidator, "No target Validator set");
return this.targetValidator.unwrap(type); return this.targetValidator.unwrap(type);
} }

2
spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java

@ -304,7 +304,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
} }
else if (javaxValidationPresent) { else if (javaxValidationPresent) {
RootBeanDefinition validatorDef = new RootBeanDefinition( RootBeanDefinition validatorDef = new RootBeanDefinition(
"org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"); "org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean");
validatorDef.setSource(source); validatorDef.setSource(source);
validatorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); validatorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String validatorName = parserContext.getReaderContext().registerWithGeneratedName(validatorDef); String validatorName = parserContext.getReaderContext().registerWithGeneratedName(validatorDef);

Loading…
Cancel
Save