diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.java index d66fc5f16df..b6063f77039 100644 --- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.java +++ b/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.ParameterNameDiscoverer; import org.springframework.core.io.Resource; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; import org.springframework.util.ReflectionUtils; @@ -84,6 +85,7 @@ import org.springframework.util.ReflectionUtils; public class LocalValidatorFactoryBean extends SpringValidatorAdapter implements ValidatorFactory, ApplicationContextAware, InitializingBean, DisposableBean { + // Bean Validation 1.1 close() method available? private static final Method closeMethod = ClassUtils.getMethodIfAvailable(ValidatorFactory.class, "close"); @@ -214,10 +216,9 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter @Override - @SuppressWarnings("unchecked") public void afterPropertiesSet() { - @SuppressWarnings("rawtypes") - Configuration configuration = (this.providerClass != null ? + @SuppressWarnings({"rawtypes", "unchecked"}) + Configuration configuration = (this.providerClass != null ? Validation.byProvider(this.providerClass).configure() : Validation.byDefaultProvider().configure()); @@ -240,7 +241,9 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter configuration.constraintValidatorFactory(targetConstraintValidatorFactory); } - configureParameterNameProviderIfPossible(configuration); + if (this.parameterNameDiscoverer != null) { + configureParameterNameProviderIfPossible(configuration); + } if (this.mappingLocations != null) { for (Resource location : this.mappingLocations) { @@ -329,31 +332,36 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter @Override public Validator getValidator() { + Assert.notNull(this.validatorFactory, "No target ValidatorFactory set"); return this.validatorFactory.getValidator(); } @Override public ValidatorContext usingContext() { + Assert.notNull(this.validatorFactory, "No target ValidatorFactory set"); return this.validatorFactory.usingContext(); } @Override public MessageInterpolator getMessageInterpolator() { + Assert.notNull(this.validatorFactory, "No target ValidatorFactory set"); return this.validatorFactory.getMessageInterpolator(); } @Override public TraversableResolver getTraversableResolver() { + Assert.notNull(this.validatorFactory, "No target ValidatorFactory set"); return this.validatorFactory.getTraversableResolver(); } @Override public ConstraintValidatorFactory getConstraintValidatorFactory() { + Assert.notNull(this.validatorFactory, "No target ValidatorFactory set"); return this.validatorFactory.getConstraintValidatorFactory(); } public void close() { - if (closeMethod != null) { + if (closeMethod != null && this.validatorFactory != null) { ReflectionUtils.invokeMethod(closeMethod, this.validatorFactory); } } diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/OptionalValidatorFactoryBean.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/OptionalValidatorFactoryBean.java new file mode 100644 index 00000000000..9ddcc51714f --- /dev/null +++ b/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. + * + *

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); + } + } + +} diff --git a/spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java b/spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java index 57437f48e39..7733b98b879 100644 --- a/spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java +++ b/spring-context/src/main/java/org/springframework/validation/beanvalidation/SpringValidatorAdapter.java @@ -83,27 +83,31 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation. @Override public boolean supports(Class clazz) { - return true; + return (this.targetValidator != null); } @Override public void validate(Object target, Errors errors) { - processConstraintViolations(this.targetValidator.validate(target), errors); + if (this.targetValidator != null) { + processConstraintViolations(this.targetValidator.validate(target), errors); + } } @Override @SuppressWarnings("rawtypes") public void validate(Object target, Errors errors, Object... validationHints) { - Set groups = new LinkedHashSet(); - if (validationHints != null) { - for (Object hint : validationHints) { - if (hint instanceof Class) { - groups.add((Class) hint); + if (this.targetValidator != null) { + Set groups = new LinkedHashSet(); + if (validationHints != null) { + for (Object hint : validationHints) { + 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 public Set> validate(T object, Class... groups) { + Assert.notNull(this.targetValidator, "No target Validator set"); return this.targetValidator.validate(object, groups); } @Override public Set> validateProperty(T object, String propertyName, Class... groups) { + Assert.notNull(this.targetValidator, "No target Validator set"); return this.targetValidator.validateProperty(object, propertyName, groups); } @@ -212,16 +218,19 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation. public Set> validateValue( Class beanType, String propertyName, Object value, Class... groups) { + Assert.notNull(this.targetValidator, "No target Validator set"); return this.targetValidator.validateValue(beanType, propertyName, value, groups); } @Override public BeanDescriptor getConstraintsForClass(Class clazz) { + Assert.notNull(this.targetValidator, "No target Validator set"); return this.targetValidator.getConstraintsForClass(clazz); } @Override public T unwrap(Class type) { + Assert.notNull(this.targetValidator, "No target Validator set"); return this.targetValidator.unwrap(type); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java index 55e7c9f73bf..c009f0badfd 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java @@ -304,7 +304,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser { } else if (javaxValidationPresent) { RootBeanDefinition validatorDef = new RootBeanDefinition( - "org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"); + "org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean"); validatorDef.setSource(source); validatorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); String validatorName = parserContext.getReaderContext().registerWithGeneratedName(validatorDef);