mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Refine validator and MVC validator configuration
This commit ensures that a primary JSR 303 and Spring Validator will be exposed if the auto-configuration kicks in. As `LocalValidatorFactoryBean` exposes 3 contracts (JSR-303 `Validator` and `ValidatorFactory` as well as the `Spring` validator one), this makes sure that those types can be injected by type. `LocalValidatorFactoryBean` exposes 3 contracts and we're only checking for the absence of a `javax.validation.Validator` to auto-configure a `LocalValidatorFactoryBean`. If no standard JSR validator exists but a Spring's `Validator` exists and is primary, we shouldn't flag the auto-configured one as `@Primary`. Previous iterations on this feature have made sure that we'll auto-configure at most one `javax.validation.Validator` so not flagging it `@Primary` is no problem. This commit also restores and adds tests that validates `ValidationAutoConfiguration` will configure a JSR validator even if a Spring Validator is present. This effectively fixes gh-8495 in a different way. Closes gh-8979 Closes gh-8976
This commit is contained in:
parent
f42998f5ca
commit
1de2316a0b
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.autoconfigure.validation;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
|
||||
/**
|
||||
* Enable the {@code Primary} flag on the auto-configured validator if necessary.
|
||||
* <p>
|
||||
* As {@link LocalValidatorFactoryBean} exposes 3 validator related contracts and we're
|
||||
* only checking for the absence {@link javax.validation.Validator}, we should flag the
|
||||
* auto-configured validator as primary only if no Spring's {@link Validator} is flagged
|
||||
* as primary.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class PrimaryDefaultValidatorPostProcessor
|
||||
implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
|
||||
|
||||
/**
|
||||
* The bean name of the auto-configured Validator.
|
||||
*/
|
||||
private static final String VALIDATOR_BEAN_NAME = "defaultValidator";
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
if (beanFactory instanceof ConfigurableListableBeanFactory) {
|
||||
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
|
||||
BeanDefinitionRegistry registry) {
|
||||
if (this.beanFactory == null) {
|
||||
return;
|
||||
}
|
||||
if (!registry.containsBeanDefinition(VALIDATOR_BEAN_NAME)) {
|
||||
return;
|
||||
}
|
||||
BeanDefinition def = registry.getBeanDefinition(VALIDATOR_BEAN_NAME);
|
||||
if (def != null
|
||||
&& this.beanFactory.isTypeMatch(VALIDATOR_BEAN_NAME, LocalValidatorFactoryBean.class)
|
||||
&& def.getRole() == BeanDefinition.ROLE_INFRASTRUCTURE) {
|
||||
def.setPrimary(!hasPrimarySpringValidator(registry));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasPrimarySpringValidator(BeanDefinitionRegistry registry) {
|
||||
String[] validatorBeans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||
this.beanFactory, Validator.class, false, false);
|
||||
for (String validatorBean : validatorBeans) {
|
||||
BeanDefinition def = registry.getBeanDefinition(validatorBean);
|
||||
if (def != null && def.isPrimary()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.boot.validation.MessageInterpolatorFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Role;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
@ -43,12 +44,13 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess
|
||||
@Configuration
|
||||
@ConditionalOnClass(ExecutableValidator.class)
|
||||
@ConditionalOnResource(resources = "classpath:META-INF/services/javax.validation.spi.ValidationProvider")
|
||||
@Import(PrimaryDefaultValidatorPostProcessor.class)
|
||||
public class ValidationAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
@ConditionalOnMissingBean
|
||||
public static Validator jsr303Validator() {
|
||||
@ConditionalOnMissingBean(Validator.class)
|
||||
public static LocalValidatorFactoryBean defaultValidator() {
|
||||
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
|
||||
MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
|
||||
factoryBean.setMessageInterpolator(interpolatorFactory.getObject());
|
||||
|
@ -31,15 +31,20 @@ import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
|
||||
import org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link ValidationAutoConfiguration}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ValidationAutoConfigurationTests {
|
||||
|
||||
@ -55,6 +60,95 @@ public class ValidationAutoConfigurationTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validationAutoConfigurationShouldConfigureDefaultValidator() {
|
||||
load(Config.class);
|
||||
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
|
||||
String[] springValidatorNames = this.context
|
||||
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
||||
assertThat(jsrValidatorNames).containsExactly("defaultValidator");
|
||||
assertThat(springValidatorNames).containsExactly("defaultValidator");
|
||||
Validator jsrValidator = this.context.getBean(Validator.class);
|
||||
org.springframework.validation.Validator springValidator = this.context
|
||||
.getBean(org.springframework.validation.Validator.class);
|
||||
assertThat(jsrValidator).isInstanceOf(LocalValidatorFactoryBean.class);
|
||||
assertThat(jsrValidator).isEqualTo(springValidator);
|
||||
assertThat(isPrimaryBean("defaultValidator")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validationAutoConfigurationWhenUserProvidesValidatorShouldBackOff() {
|
||||
load(UserDefinedValidatorConfig.class);
|
||||
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
|
||||
String[] springValidatorNames = this.context
|
||||
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
||||
assertThat(jsrValidatorNames).containsExactly("customValidator");
|
||||
assertThat(springValidatorNames).containsExactly("customValidator");
|
||||
org.springframework.validation.Validator springValidator = this.context
|
||||
.getBean(org.springframework.validation.Validator.class);
|
||||
Validator jsrValidator = this.context.getBean(Validator.class);
|
||||
assertThat(jsrValidator).isInstanceOf(OptionalValidatorFactoryBean.class);
|
||||
assertThat(jsrValidator).isEqualTo(springValidator);
|
||||
assertThat(isPrimaryBean("customValidator")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validationAutoConfigurationWhenUserProvidesDefaultValidatorShouldNotEnablePrimary() {
|
||||
load(UserDefinedDefaultValidatorConfig.class);
|
||||
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
|
||||
String[] springValidatorNames = this.context
|
||||
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
||||
assertThat(jsrValidatorNames).containsExactly("defaultValidator");
|
||||
assertThat(springValidatorNames).containsExactly("defaultValidator");
|
||||
assertThat(isPrimaryBean("defaultValidator")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validationAutoConfigurationWhenUserProvidesJsrValidatorShouldBackOff() {
|
||||
load(UserDefinedJsrValidatorConfig.class);
|
||||
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
|
||||
String[] springValidatorNames = this.context
|
||||
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
||||
assertThat(jsrValidatorNames).containsExactly("customValidator");
|
||||
assertThat(springValidatorNames).isEmpty();
|
||||
assertThat(isPrimaryBean("customValidator")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validationAutoConfigurationWhenUserProvidesSpringValidatorShouldCreateJsrValidator() {
|
||||
load(UserDefinedSpringValidatorConfig.class);
|
||||
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
|
||||
String[] springValidatorNames = this.context
|
||||
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
||||
assertThat(jsrValidatorNames).containsExactly("defaultValidator");
|
||||
assertThat(springValidatorNames).containsExactly(
|
||||
"customValidator", "anotherCustomValidator", "defaultValidator");
|
||||
Validator jsrValidator = this.context.getBean(Validator.class);
|
||||
org.springframework.validation.Validator springValidator = this.context
|
||||
.getBean(org.springframework.validation.Validator.class);
|
||||
assertThat(jsrValidator).isInstanceOf(LocalValidatorFactoryBean.class);
|
||||
assertThat(jsrValidator).isEqualTo(springValidator);
|
||||
assertThat(isPrimaryBean("defaultValidator")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validationAutoConfigurationWhenUserProvidesPrimarySpringValidatorShouldRemovePrimaryFlag() {
|
||||
load(UserDefinedPrimarySpringValidatorConfig.class);
|
||||
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
|
||||
String[] springValidatorNames = this.context
|
||||
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
||||
assertThat(jsrValidatorNames).containsExactly("defaultValidator");
|
||||
assertThat(springValidatorNames).containsExactly(
|
||||
"customValidator", "anotherCustomValidator", "defaultValidator");
|
||||
Validator jsrValidator = this.context.getBean(Validator.class);
|
||||
org.springframework.validation.Validator springValidator = this.context
|
||||
.getBean(org.springframework.validation.Validator.class);
|
||||
assertThat(jsrValidator).isInstanceOf(LocalValidatorFactoryBean.class);
|
||||
assertThat(springValidator).isEqualTo(
|
||||
this.context.getBean("anotherCustomValidator"));
|
||||
assertThat(isPrimaryBean("defaultValidator")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validationIsEnabled() {
|
||||
load(SampleService.class);
|
||||
@ -104,7 +198,11 @@ public class ValidationAutoConfigurationTests {
|
||||
.getPropertyValue("validator"));
|
||||
}
|
||||
|
||||
public void load(Class<?> config, String... environment) {
|
||||
private boolean isPrimaryBean(String beanName) {
|
||||
return this.context.getBeanDefinition(beanName).isPrimary();
|
||||
}
|
||||
|
||||
private void load(Class<?> config, String... environment) {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(ctx, environment);
|
||||
if (config != null) {
|
||||
@ -115,6 +213,72 @@ public class ValidationAutoConfigurationTests {
|
||||
this.context = ctx;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class UserDefinedValidatorConfig {
|
||||
|
||||
@Bean
|
||||
public OptionalValidatorFactoryBean customValidator() {
|
||||
return new OptionalValidatorFactoryBean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class UserDefinedDefaultValidatorConfig {
|
||||
|
||||
@Bean
|
||||
public OptionalValidatorFactoryBean defaultValidator() {
|
||||
return new OptionalValidatorFactoryBean();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class UserDefinedJsrValidatorConfig {
|
||||
|
||||
@Bean
|
||||
public Validator customValidator() {
|
||||
return mock(Validator.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class UserDefinedSpringValidatorConfig {
|
||||
|
||||
@Bean
|
||||
public org.springframework.validation.Validator customValidator() {
|
||||
return mock(org.springframework.validation.Validator.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public org.springframework.validation.Validator anotherCustomValidator() {
|
||||
return mock(org.springframework.validation.Validator.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class UserDefinedPrimarySpringValidatorConfig {
|
||||
|
||||
@Bean
|
||||
public org.springframework.validation.Validator customValidator() {
|
||||
return mock(org.springframework.validation.Validator.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public org.springframework.validation.Validator anotherCustomValidator() {
|
||||
return mock(org.springframework.validation.Validator.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Validated
|
||||
static class SampleService {
|
||||
|
||||
|
@ -39,6 +39,7 @@ import org.junit.rules.ExpectedException;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter;
|
||||
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration.WelcomePageHandlerMapping;
|
||||
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
|
||||
@ -59,6 +60,7 @@ import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.Validator;
|
||||
@ -655,77 +657,126 @@ public class WebMvcAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validationNoJsr303ValidatorExposedByDefault() {
|
||||
load();
|
||||
public void validatorWhenNoValidatorShouldUseDefault() {
|
||||
load(null, new Class<?>[] { ValidationAutoConfiguration.class });
|
||||
assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
|
||||
assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
|
||||
.isEmpty();
|
||||
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
||||
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||
assertThat(springValidatorBeans).containsExactly("mvcValidator");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validationCustomConfigurerTakesPrecedence() {
|
||||
load(MvcValidator.class);
|
||||
public void validatorWhenNoCustomizationShouldUseAutoConfigured() {
|
||||
load();
|
||||
String[] jsrValidatorBeans = this.context
|
||||
.getBeanNamesForType(javax.validation.Validator.class);
|
||||
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||
assertThat(jsrValidatorBeans).containsExactly("defaultValidator");
|
||||
assertThat(springValidatorBeans).containsExactly("defaultValidator", "mvcValidator");
|
||||
Validator validator = this.context.getBean("mvcValidator", Validator.class);
|
||||
assertThat(validator).isInstanceOf(WebMvcValidator.class);
|
||||
Object defaultValidator = this.context.getBean("defaultValidator");
|
||||
assertThat(((WebMvcValidator) validator).getTarget()).isSameAs(defaultValidator);
|
||||
// Primary Spring validator is the one use by MVC behind the scenes
|
||||
assertThat(this.context.getBean(Validator.class)).isEqualTo(defaultValidator);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validatorWithConfigurerShouldUseSpringValidator() {
|
||||
load(MvcValidator.class, new Class<?>[] { ValidationAutoConfiguration.class });
|
||||
assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
|
||||
assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
|
||||
.isEmpty();
|
||||
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
||||
Validator validator = this.context.getBean(Validator.class);
|
||||
assertThat(validator)
|
||||
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||
assertThat(springValidatorBeans).containsExactly("mvcValidator");
|
||||
assertThat(this.context.getBean("mvcValidator"))
|
||||
.isSameAs(this.context.getBean(MvcValidator.class).validator);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validationCustomConfigurerTakesPrecedenceAndDoNotExposeJsr303() {
|
||||
load(MvcJsr303Validator.class);
|
||||
public void validatorWithConfigurerDoesNotExposeJsr303() {
|
||||
load(MvcJsr303Validator.class, new Class<?>[] { ValidationAutoConfiguration.class });
|
||||
assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
|
||||
assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
|
||||
.isEmpty();
|
||||
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
||||
Validator validator = this.context.getBean(Validator.class);
|
||||
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||
assertThat(springValidatorBeans).containsExactly("mvcValidator");
|
||||
Validator validator = this.context.getBean("mvcValidator", Validator.class);
|
||||
assertThat(validator).isInstanceOf(WebMvcValidator.class);
|
||||
assertThat(((WebMvcValidator) validator).getTarget())
|
||||
.isSameAs(this.context.getBean(MvcJsr303Validator.class).validator);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validationJsr303CustomValidatorReusedAsSpringValidator() {
|
||||
load(CustomValidator.class);
|
||||
public void validatorWithConfigurerTakesPrecedence() {
|
||||
load(MvcValidator.class);
|
||||
assertThat(this.context.getBeansOfType(ValidatorFactory.class)).hasSize(1);
|
||||
assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
|
||||
.hasSize(1);
|
||||
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(2);
|
||||
Validator validator = this.context.getBean("mvcValidator", Validator.class);
|
||||
assertThat(validator).isInstanceOf(WebMvcValidator.class);
|
||||
assertThat(((WebMvcValidator) validator).getTarget())
|
||||
.isSameAs(this.context.getBean(javax.validation.Validator.class));
|
||||
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||
assertThat(springValidatorBeans).containsExactly("defaultValidator", "mvcValidator");
|
||||
assertThat(this.context.getBean("mvcValidator"))
|
||||
.isSameAs(this.context.getBean(MvcValidator.class).validator);
|
||||
// Primary Spring validator is the auto-configured one as the MVC one has been
|
||||
// customized via a WebMvcConfigurer
|
||||
assertThat(this.context.getBean(Validator.class))
|
||||
.isEqualTo(this.context.getBean("defaultValidator"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validationJsr303ValidatorExposedAsSpringValidator() {
|
||||
load(Jsr303Validator.class);
|
||||
public void validatorWithCustomSpringValidatorIgnored() {
|
||||
load(CustomSpringValidator.class);
|
||||
String[] jsrValidatorBeans = this.context
|
||||
.getBeanNamesForType(javax.validation.Validator.class);
|
||||
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||
assertThat(jsrValidatorBeans).containsExactly("defaultValidator");
|
||||
assertThat(springValidatorBeans).containsExactly(
|
||||
"customSpringValidator", "defaultValidator", "mvcValidator");
|
||||
Validator validator = this.context.getBean("mvcValidator", Validator.class);
|
||||
assertThat(validator).isInstanceOf(WebMvcValidator.class);
|
||||
Object defaultValidator = this.context.getBean("defaultValidator");
|
||||
assertThat(((WebMvcValidator) validator).getTarget())
|
||||
.isSameAs(defaultValidator);
|
||||
// Primary Spring validator is the one use by MVC behind the scenes
|
||||
assertThat(this.context.getBean(Validator.class)).isEqualTo(defaultValidator);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validatorWithCustomJsr303ValidatorExposedAsSpringValidator() {
|
||||
load(CustomJsr303Validator.class);
|
||||
assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
|
||||
assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
|
||||
.hasSize(1);
|
||||
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
||||
String[] jsrValidatorBeans = this.context
|
||||
.getBeanNamesForType(javax.validation.Validator.class);
|
||||
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||
assertThat(jsrValidatorBeans).containsExactly("customJsr303Validator");
|
||||
assertThat(springValidatorBeans).containsExactly("mvcValidator");
|
||||
Validator validator = this.context.getBean(Validator.class);
|
||||
assertThat(validator).isInstanceOf(WebMvcValidator.class);
|
||||
SpringValidatorAdapter target = ((WebMvcValidator) validator)
|
||||
.getTarget();
|
||||
assertThat(new DirectFieldAccessor(target).getPropertyValue("targetValidator"))
|
||||
.isSameAs(this.context.getBean(javax.validation.Validator.class));
|
||||
.isSameAs(this.context.getBean("customJsr303Validator"));
|
||||
}
|
||||
|
||||
private void load(Class<?> config, String... environment) {
|
||||
load(config, null, environment);
|
||||
}
|
||||
|
||||
private void load(Class<?> config, Class<?>[] exclude, String... environment) {
|
||||
this.context = new AnnotationConfigEmbeddedWebApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(this.context, environment);
|
||||
List<Class<?>> configClasses = new ArrayList<Class<?>>();
|
||||
if (config != null) {
|
||||
configClasses.add(config);
|
||||
}
|
||||
configClasses.addAll(Arrays.asList(Config.class, WebMvcAutoConfiguration.class,
|
||||
configClasses.addAll(Arrays.asList(Config.class,
|
||||
ValidationAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||
HttpMessageConvertersAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class));
|
||||
if (!ObjectUtils.isEmpty(exclude)) {
|
||||
configClasses.removeAll(Arrays.asList(exclude));
|
||||
}
|
||||
this.context.register(configClasses.toArray(new Class<?>[configClasses.size()]));
|
||||
this.context.refresh();
|
||||
}
|
||||
@ -919,21 +970,21 @@ public class WebMvcAutoConfigurationTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Jsr303Validator {
|
||||
static class CustomJsr303Validator {
|
||||
|
||||
@Bean
|
||||
public javax.validation.Validator jsr303Validator() {
|
||||
public javax.validation.Validator customJsr303Validator() {
|
||||
return mock(javax.validation.Validator.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class CustomValidator {
|
||||
static class CustomSpringValidator {
|
||||
|
||||
@Bean
|
||||
public Validator customValidator() {
|
||||
return new LocalValidatorFactoryBean();
|
||||
public Validator customSpringValidator() {
|
||||
return mock(Validator.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user