Commit eb222209 authored by Phillip Webb's avatar Phillip Webb

Upgrade to hibernate-validator 5.3.4

Upgrade to `hibernate-validator` 5.3.4 and introduce a new
`MessageInterpolatorFactory` that creates a suitable
`MessageInterpolator` (taking into account missing EL dependencies).

Rework `ConfigurationPropertiesBindingPostProcessor` and
`ValidationAutoConfiguration` to make use of the new factory.

Fixes gh-7598
parent d80f22c2
...@@ -27,6 +27,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; ...@@ -27,6 +27,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnResource; import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition; import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.validation.MessageInterpolatorFactory;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Conditional;
...@@ -51,7 +52,10 @@ public class ValidationAutoConfiguration { ...@@ -51,7 +52,10 @@ public class ValidationAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public Validator validator() { public Validator validator() {
return new LocalValidatorFactoryBean(); LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
factoryBean.setMessageInterpolator(interpolatorFactory.getObject());
return factoryBean;
} }
@Bean @Bean
......
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
<hazelcast-hibernate4.version>3.7.1</hazelcast-hibernate4.version> <hazelcast-hibernate4.version>3.7.1</hazelcast-hibernate4.version>
<hazelcast-hibernate5.version>1.1.3</hazelcast-hibernate5.version> <hazelcast-hibernate5.version>1.1.3</hazelcast-hibernate5.version>
<hibernate.version>5.0.11.Final</hibernate.version> <hibernate.version>5.0.11.Final</hibernate.version>
<hibernate-validator.version>5.2.4.Final</hibernate-validator.version> <hibernate-validator.version>5.3.4.Final</hibernate-validator.version>
<hikaricp.version>2.5.1</hikaricp.version> <hikaricp.version>2.5.1</hikaricp.version>
<hikaricp-java6.version>2.3.13</hikaricp-java6.version> <hikaricp-java6.version>2.3.13</hikaricp-java6.version>
<hsqldb.version>2.3.3</hsqldb.version> <hsqldb.version>2.3.3</hsqldb.version>
......
...@@ -35,6 +35,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; ...@@ -35,6 +35,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.bind.PropertiesConfigurationFactory; import org.springframework.boot.bind.PropertiesConfigurationFactory;
import org.springframework.boot.validation.MessageInterpolatorFactory;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener;
...@@ -400,7 +401,9 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc ...@@ -400,7 +401,9 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
public Validator run(ApplicationContext applicationContext) { public Validator run(ApplicationContext applicationContext) {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean(); LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
validator.setApplicationContext(applicationContext); validator.setApplicationContext(applicationContext);
validator.setMessageInterpolator(interpolatorFactory.getObject());
validator.afterPropertiesSet(); validator.afterPropertiesSet();
return validator; return validator;
} }
......
/*
* Copyright 2012-2017 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.boot.validation;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.validation.MessageInterpolator;
import javax.validation.Validation;
import javax.validation.ValidationException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.util.ClassUtils;
/**
* {@link ObjectFactory} that can be used to create a {@link MessageInterpolatorFactory}.
* Attempts to pick the most appropriate {@link MessageInterpolator} based on the
* classpath.
*
* @author Phillip Webb
*/
public class MessageInterpolatorFactory implements ObjectFactory<MessageInterpolator> {
private static final Set<String> FALLBACKS;
static {
Set<String> fallbacks = new LinkedHashSet<String>();
fallbacks.add("org.hibernate.validator.messageinterpolation"
+ ".ParameterMessageInterpolator");
FALLBACKS = Collections.unmodifiableSet(fallbacks);
}
@Override
public MessageInterpolator getObject() throws BeansException {
try {
return Validation.byDefaultProvider().configure()
.getDefaultMessageInterpolator();
}
catch (ValidationException ex) {
MessageInterpolator fallback = getFallback();
if (fallback != null) {
return fallback;
}
throw ex;
}
}
private MessageInterpolator getFallback() {
for (String fallback : FALLBACKS) {
try {
return getFallback(fallback);
}
catch (Exception ex) {
// Swallow an continue
}
}
return null;
}
private MessageInterpolator getFallback(String fallback) {
Class<?> interpolatorClass = ClassUtils.resolveClassName(fallback, null);
Object interpolator = BeanUtils.instantiate(interpolatorClass);
return (MessageInterpolator) interpolator;
}
}
/*
* Copyright 2012-2016 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.
*/
/**
* Utilities and classes related to validation.
*/
package org.springframework.boot.validation;
/*
* Copyright 2012-2017 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.boot.validation;
import javax.validation.MessageInterpolator;
import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MessageInterpolatorFactory}.
*
* @author Phillip Webb
*/
public class MessageInterpolatorFactoryTests {
@Test
public void getObjectShouldReturnResourceBundleMessageInterpolator() {
MessageInterpolator interpolator = new MessageInterpolatorFactory().getObject();
assertThat(interpolator).isInstanceOf(ResourceBundleMessageInterpolator.class);
}
}
/*
* Copyright 2012-2017 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.boot.validation;
import javax.validation.MessageInterpolator;
import javax.validation.Validation;
import javax.validation.ValidationException;
import org.hibernate.validator.messageinterpolation.ParameterMessageInterpolator;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.springframework.boot.junit.runner.classpath.ClassPathExclusions;
import org.springframework.boot.junit.runner.classpath.ModifiedClassPathRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link MessageInterpolatorFactory} without EL.
*
* @author Phillip Webb
*/
@RunWith(ModifiedClassPathRunner.class)
@ClassPathExclusions("tomcat-embed-el-*.jar")
public class MessageInterpolatorFactoryWithoutElIntegrationTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void defaultMessageInterpolatorShouldFail() throws Exception {
// Sanity test
this.thrown.expect(ValidationException.class);
this.thrown.expectMessage("javax.el.ExpressionFactory");
Validation.byDefaultProvider().configure().getDefaultMessageInterpolator();
}
@Test
public void getObjectShouldUseFallback() {
MessageInterpolator interpolator = new MessageInterpolatorFactory().getObject();
assertThat(interpolator).isInstanceOf(ParameterMessageInterpolator.class);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment