Raised Hibernate Validator support dependency to 4.3+

This allows for restoring a static MessageSourceResourceBundleLocator implementation, just implementing the interface at the new spi location introduced in HV 4.3 and preserved in 5.0.

Issue: SPR-8199
This commit is contained in:
Juergen Hoeller 2013-05-03 15:37:02 +02:00
parent cac76192e2
commit 2a53a2de0e
4 changed files with 66 additions and 52 deletions

View File

@ -24,7 +24,6 @@ import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import javax.validation.Configuration;
@ -43,7 +42,6 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.MessageSource;
import org.springframework.context.support.MessageSourceResourceBundle;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.io.Resource;
@ -65,7 +63,7 @@ import org.springframework.util.ReflectionUtils;
* into any target dependency of type {@link org.springframework.validation.Validator}!
*
* <p><b>As of Spring 4.0, this class supports Bean Validation 1.0 and 1.1, with special support
* for Hibernate Validator 4.x and 5.0</b> (see {@link #setValidationMessageSource}).
* for Hibernate Validator 4.3 and 5.0</b> (see {@link #setValidationMessageSource}).
*
* <p>Note that Bean Validation 1.1's {@code #forExecutables} method isn't supported: We do not
* expect that method to be called by application code; consider {@link MethodValidationInterceptor}
@ -130,7 +128,7 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
* instead of relying on JSR-303's default "ValidationMessages.properties" bundle
* in the classpath. This may refer to a Spring context's shared "messageSource" bean,
* or to some special MessageSource setup for validation purposes only.
* <p><b>NOTE:</b> This feature requires Hibernate Validator 4.1 or higher on the classpath.
* <p><b>NOTE:</b> This feature requires Hibernate Validator 4.3 or higher on the classpath.
* You may nevertheless use a different validation provider but Hibernate Validator's
* {@link ResourceBundleMessageInterpolator} class must be accessible during configuration.
* <p>Specify either this property or {@link #setMessageInterpolator "messageInterpolator"},
@ -360,47 +358,8 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter
*/
private static class HibernateValidatorDelegate {
public static MessageInterpolator buildMessageInterpolator(final MessageSource messageSource) {
Class<?> locatorClass;
try {
// Hibernate Validator 5.x
locatorClass = ClassUtils.forName(
"org.hibernate.validator.spi.resourceloading.ResourceBundleLocator",
HibernateValidatorDelegate.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
try {
// Hibernate Validator 4.x
locatorClass = ClassUtils.forName(
"org.hibernate.validator.resourceloading.ResourceBundleLocator",
HibernateValidatorDelegate.class.getClassLoader());
}
catch (ClassNotFoundException ex2) {
throw new IllegalStateException("Neither Hibernate Validator 5.x nor 4.x API found");
}
}
Object locator = Proxy.newProxyInstance(HibernateValidatorDelegate.class.getClassLoader(),
new Class[] {locatorClass}, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("getResourceBundle")) {
return new MessageSourceResourceBundle(messageSource, (Locale) args[0]);
}
else {
try {
return method.invoke(this, args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
});
try {
return ResourceBundleMessageInterpolator.class.getConstructor(locatorClass).newInstance(locator);
}
catch (Exception ex) {
throw new IllegalStateException("Unexpected Hibernate Validator API mismatch", ex);
}
public static MessageInterpolator buildMessageInterpolator(MessageSource messageSource) {
return new ResourceBundleMessageInterpolator(new MessageSourceResourceBundleLocator(messageSource));
}
}

View File

@ -0,0 +1,55 @@
/*
* 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 java.util.Locale;
import java.util.ResourceBundle;
import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator;
import org.springframework.context.MessageSource;
import org.springframework.context.support.MessageSourceResourceBundle;
import org.springframework.util.Assert;
/**
* Implementation of Hibernate Validator 4.3/5.0's {@link ResourceBundleLocator} interface,
* exposing a Spring {@link MessageSource} as localized {@link MessageSourceResourceBundle}.
*
* @author Juergen Hoeller
* @since 3.0.4
* @see ResourceBundleLocator
* @see MessageSource
* @see MessageSourceResourceBundle
*/
public class MessageSourceResourceBundleLocator implements ResourceBundleLocator {
private final MessageSource messageSource;
/**
* Build a MessageSourceResourceBundleLocator for the given MessageSource.
* @param messageSource the Spring MessageSource to wrap
*/
public MessageSourceResourceBundleLocator(MessageSource messageSource) {
Assert.notNull(messageSource, "MessageSource must not be null");
this.messageSource = messageSource;
}
public ResourceBundle getResourceBundle(Locale locale) {
return new MessageSourceResourceBundle(this.messageSource, locale);
}
}

View File

@ -50,8 +50,8 @@ import org.springframework.validation.annotation.Validated;
* of that class. By default, JSR-303 will validate against its default group only.
*
* <p>As of Spring 4.0, this functionality requires either a Bean Validation 1.1 provider
* or Bean Validation 1.0 with Hibernate Validator 4.2 or higher. The actual provider
* will be autodetected and automatically adapted.
* (such as Hibernate Validator 5.0) or the Bean Validation 1.0 API with Hibernate Validator
* 4.2 or 4.3. The actual provider will be autodetected and automatically adapted.
*
* @author Juergen Hoeller
* @since 3.1
@ -149,7 +149,7 @@ public class MethodValidationInterceptor implements MethodInterceptor {
/**
* Inner class to avoid a hard-coded Hibernate Validator dependency.
* Inner class to avoid a hard-coded Hibernate Validator 4.2/4.3 dependency.
*/
private static class HibernateValidatorDelegate {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* 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.
@ -48,9 +48,9 @@ import org.springframework.validation.annotation.Validated;
* inline constraint annotations. Validation groups can be specified through {@code @Validated}
* as well. By default, JSR-303 will validate against its default group only.
*
* <p>As of Spring 3.1, this functionality requires Hibernate Validator 4.2 or higher.
* In a future version of Spring, this class will autodetect a Bean Validation 1.1 compliant
* provider and automatically use the standard method validation support when available.
* <p>As of Spring 4.0, this functionality requires either a Bean Validation 1.1 provider
* (such as Hibernate Validator 5.0) or the Bean Validation 1.0 API with Hibernate Validator
* 4.2 or 4.3. The actual provider will be autodetected and automatically adapted.
*
* @author Juergen Hoeller
* @since 3.1