diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/DefaultValidatorConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/DefaultValidatorConfiguration.java
deleted file mode 100644
index 9311a272c6..0000000000
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/DefaultValidatorConfiguration.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.factory.config.BeanDefinition;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.validation.MessageInterpolatorFactory;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Role;
-import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
-
-/**
- * Default validator configuration imported by {@link ValidationAutoConfiguration}.
- *
- * @author Stephane Nicoll
- * @author Phillip Webb
- */
-@Configuration
-class DefaultValidatorConfiguration {
-
- @Bean
- @ConditionalOnMissingBean(type = { "javax.validation.Validator",
- "org.springframework.validation.Validator" })
- @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
- public static LocalValidatorFactoryBean defaultValidator() {
- LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
- MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
- factoryBean.setMessageInterpolator(interpolatorFactory.getObject());
- return factoryBean;
- }
-
-}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/DelegatingValidator.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/DelegatingValidator.java
deleted file mode 100644
index e180ba284a..0000000000
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/DelegatingValidator.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.util.Assert;
-import org.springframework.validation.Errors;
-import org.springframework.validation.SmartValidator;
-import org.springframework.validation.Validator;
-import org.springframework.validation.beanvalidation.SpringValidatorAdapter;
-
-/**
- * {@link Validator} implementation that delegates calls to another {@link Validator}.
- * This {@link Validator} implements Spring's {@link SmartValidator} interface but does
- * not implement the JSR-303 {@code javax.validator.Validator} interface.
- *
- * @author Phillip Webb
- * @since 1.5.3
- */
-public class DelegatingValidator implements SmartValidator {
-
- private final Validator delegate;
-
- /**
- * Create a new {@link DelegatingValidator} instance.
- * @param targetValidator the target JSR validator
- */
- public DelegatingValidator(javax.validation.Validator targetValidator) {
- this.delegate = new SpringValidatorAdapter(targetValidator);
- }
-
- /**
- * Create a new {@link DelegatingValidator} instance.
- * @param targetValidator the target validator
- */
- public DelegatingValidator(Validator targetValidator) {
- Assert.notNull(targetValidator, "Target Validator must not be null");
- this.delegate = targetValidator;
- }
-
- @Override
- public boolean supports(Class> clazz) {
- return this.delegate.supports(clazz);
- }
-
- @Override
- public void validate(Object target, Errors errors) {
- this.delegate.validate(target, errors);
- }
-
- @Override
- public void validate(Object target, Errors errors, Object... validationHints) {
- if (this.delegate instanceof SmartValidator) {
- ((SmartValidator) this.delegate).validate(target, errors, validationHints);
- }
- else {
- this.delegate.validate(target, errors);
- }
- }
-
- /**
- * Return the delegate validator.
- * @return the delegate validator
- */
- protected final Validator getDelegate() {
- return this.delegate;
- }
-
-}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/Jsr303ValidatorAdapterConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/Jsr303ValidatorAdapterConfiguration.java
deleted file mode 100644
index 2573dd3e3c..0000000000
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/Jsr303ValidatorAdapterConfiguration.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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 javax.validation.Validator;
-
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Role;
-import org.springframework.validation.SmartValidator;
-
-/**
- * JSR 303 adapter configration imported by {@link ValidationAutoConfiguration}.
- *
- * @author Stephane Nicoll
- * @author Phillip Webb
- */
-@Configuration
-class Jsr303ValidatorAdapterConfiguration {
-
- @Bean
- @ConditionalOnSingleCandidate(Validator.class)
- @ConditionalOnMissingBean(org.springframework.validation.Validator.class)
- @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
- public SmartValidator jsr303ValidatorAdapter(Validator validator) {
- return new DelegatingValidator(validator);
- }
-
-}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/PrimaryDefaultValidatorPostProcessor.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/PrimaryDefaultValidatorPostProcessor.java
new file mode 100644
index 0000000000..ad32b2c998
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/PrimaryDefaultValidatorPostProcessor.java
@@ -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.
+ *
+ * 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;
+ }
+
+}
+
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.java
index 32abaccad1..7eef174b3a 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/ValidationAutoConfiguration.java
@@ -19,15 +19,18 @@ package org.springframework.boot.autoconfigure.validation;
import javax.validation.Validator;
import javax.validation.executable.ExecutableValidator;
+import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
+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;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
/**
@@ -41,12 +44,20 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess
@Configuration
@ConditionalOnClass(ExecutableValidator.class)
@ConditionalOnResource(resources = "classpath:META-INF/services/javax.validation.spi.ValidationProvider")
-@Import({ DefaultValidatorConfiguration.class,
- Jsr303ValidatorAdapterConfiguration.class })
+@Import(PrimaryDefaultValidatorPostProcessor.class)
public class ValidationAutoConfiguration {
@Bean
- @ConditionalOnBean(Validator.class)
+ @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
+ @ConditionalOnMissingBean(Validator.class)
+ public static LocalValidatorFactoryBean defaultValidator() {
+ LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
+ MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
+ factoryBean.setMessageInterpolator(interpolatorFactory.getObject());
+ return factoryBean;
+ }
+
+ @Bean
@ConditionalOnMissingBean
public static MethodValidationPostProcessor methodValidationPostProcessor(
Environment environment, Validator validator) {
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/ValidatorAdapter.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/ValidatorAdapter.java
new file mode 100644
index 0000000000..c91ee83d10
--- /dev/null
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/validation/ValidatorAdapter.java
@@ -0,0 +1,154 @@
+/*
+ * 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.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.boot.validation.MessageInterpolatorFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.validation.Errors;
+import org.springframework.validation.SmartValidator;
+import org.springframework.validation.Validator;
+import org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean;
+import org.springframework.validation.beanvalidation.SpringValidatorAdapter;
+
+/**
+ * {@link Validator} implementation that delegates calls to another {@link Validator}.
+ * This {@link Validator} implements Spring's {@link SmartValidator} interface but does
+ * not implement the JSR-303 {@code javax.validator.Validator} interface.
+ *
+ * @author Stephane Nicoll
+ * @author Phillip Webb
+ * @since 2.0.0
+ */
+public class ValidatorAdapter implements SmartValidator, ApplicationContextAware,
+ InitializingBean, DisposableBean {
+
+ private final SmartValidator target;
+
+ private final boolean existingBean;
+
+ ValidatorAdapter(SmartValidator target, boolean existingBean) {
+ this.target = target;
+ this.existingBean = existingBean;
+ }
+
+ public final Validator getTarget() {
+ return this.target;
+ }
+
+ @Override
+ public boolean supports(Class> clazz) {
+ return this.target.supports(clazz);
+ }
+
+ @Override
+ public void validate(Object target, Errors errors) {
+ this.target.validate(target, errors);
+ }
+
+ @Override
+ public void validate(Object target, Errors errors, Object... validationHints) {
+ this.target.validate(target, errors, validationHints);
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ if (!this.existingBean && this.target instanceof ApplicationContextAware) {
+ ((ApplicationContextAware) this.target)
+ .setApplicationContext(applicationContext);
+ }
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ if (!this.existingBean && this.target instanceof InitializingBean) {
+ ((InitializingBean) this.target).afterPropertiesSet();
+ }
+ }
+
+ @Override
+ public void destroy() throws Exception {
+ if (!this.existingBean && this.target instanceof DisposableBean) {
+ ((DisposableBean) this.target).destroy();
+ }
+ }
+
+ /**
+ * Return a {@link Validator} that only implements the {@link Validator} interface,
+ * wrapping it if necessary.
+ *
If the specified {@link Validator} is not {@code null}, it is wrapped. If not,
+ * a {@link javax.validation.Validator} is retrieved from the context and wrapped.
+ * Otherwise, a new default validator is created.
+ * @param applicationContext the application context
+ * @param validator an existing validator to use or {@code null}
+ * @return the validator to use
+ */
+ public static Validator get(ApplicationContext applicationContext,
+ Validator validator) {
+ if (validator != null) {
+ return wrap(validator, false);
+ }
+ return getExistingOrCreate(applicationContext);
+ }
+
+ private static Validator getExistingOrCreate(ApplicationContext applicationContext) {
+ Validator existing = getExisting(applicationContext);
+ if (existing != null) {
+ return wrap(existing, true);
+ }
+ return create();
+ }
+
+ private static Validator getExisting(ApplicationContext applicationContext) {
+ try {
+ javax.validation.Validator validator = applicationContext
+ .getBean(javax.validation.Validator.class);
+ if (validator instanceof Validator) {
+ return (Validator) validator;
+ }
+ return new SpringValidatorAdapter(validator);
+ }
+ catch (NoSuchBeanDefinitionException ex) {
+ return null;
+ }
+ }
+
+ private static Validator create() {
+ OptionalValidatorFactoryBean validator = new OptionalValidatorFactoryBean();
+ validator.setMessageInterpolator(new MessageInterpolatorFactory().getObject());
+ return wrap(validator, false);
+ }
+
+ private static Validator wrap(Validator validator, boolean existingBean) {
+ if (validator instanceof javax.validation.Validator) {
+ if (validator instanceof SpringValidatorAdapter) {
+ return new ValidatorAdapter((SpringValidatorAdapter) validator,
+ existingBean);
+ }
+ return new ValidatorAdapter(
+ new SpringValidatorAdapter((javax.validation.Validator) validator),
+ existingBean);
+ }
+ return validator;
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java
index 7224bea60f..262128cb46 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfiguration.java
@@ -23,48 +23,30 @@ import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-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.DisposableBean;
-import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
-import org.springframework.boot.autoconfigure.validation.DelegatingValidator;
+import org.springframework.boot.autoconfigure.validation.ValidatorAdapter;
import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ConditionContext;
-import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.ConfigurationCondition;
import org.springframework.context.annotation.Import;
-import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.GenericConverter;
-import org.springframework.core.type.AnnotatedTypeMetadata;
-import org.springframework.core.type.AnnotationMetadata;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.CacheControl;
-import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
-import org.springframework.util.ObjectUtils;
import org.springframework.validation.Validator;
import org.springframework.web.reactive.config.DelegatingWebFluxConfiguration;
import org.springframework.web.reactive.config.EnableWebFlux;
@@ -103,7 +85,7 @@ public class WebFluxAutoConfiguration {
@Configuration
@EnableConfigurationProperties({ ResourceProperties.class, WebFluxProperties.class })
- @Import({ EnableWebFluxConfiguration.class, WebFluxValidatorRegistrar.class })
+ @Import({ EnableWebFluxConfiguration.class })
public static class WebFluxConfig implements WebFluxConfigurer {
private static final Log logger = LogFactory.getLog(WebFluxConfig.class);
@@ -209,29 +191,17 @@ public class WebFluxAutoConfiguration {
* Configuration equivalent to {@code @EnableWebFlux}.
*/
@Configuration
- public static class EnableWebFluxConfiguration extends DelegatingWebFluxConfiguration
- implements InitializingBean {
+ public static class EnableWebFluxConfiguration
+ extends DelegatingWebFluxConfiguration {
- private final ApplicationContext context;
-
- public EnableWebFluxConfiguration(ApplicationContext context) {
- this.context = context;
- }
-
- @Bean
@Override
- @Conditional(DisableWebFluxValidatorCondition.class)
+ @Bean
public Validator webFluxValidator() {
- return this.context.getBean("webFluxValidator", Validator.class);
- }
-
- @Override
- public void afterPropertiesSet() throws Exception {
- Assert.state(getValidator() == null,
- "Found unexpected validator configuration. A Spring Boot WebFlux "
- + "validator should be registered as bean named "
- + "'webFluxValidator' and not returned from "
- + "WebFluxConfigurer.getValidator()");
+ if (!ClassUtils.isPresent("javax.validation.Validator",
+ getClass().getClassLoader())) {
+ return super.webFluxValidator();
+ }
+ return ValidatorAdapter.get(getApplicationContext(), getValidator());
}
}
@@ -297,130 +267,4 @@ public class WebFluxAutoConfiguration {
}
- /**
- * Condition used to disable the default WebFlux validator registration. The
- * {@link WebFluxValidatorRegistrar} is used to register the {@code webFluxValidator}
- * bean.
- */
- static class DisableWebFluxValidatorCondition implements ConfigurationCondition {
-
- @Override
- public ConfigurationPhase getConfigurationPhase() {
- return ConfigurationPhase.REGISTER_BEAN;
- }
-
- @Override
- public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
- return false;
- }
-
- }
-
- /**
- * {@link ImportBeanDefinitionRegistrar} to deal with the WebFlux validator bean
- * registration. Applies the following rules:
- *
- * - With no validators - Uses standard
- * {@link WebFluxConfigurationSupport#webFluxValidator()} logic.
- * - With a single validator - Uses an alias.
- * - With multiple validators - Registers a webFluxValidator bean if not already
- * defined.
- *
- */
- static class WebFluxValidatorRegistrar
- implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
-
- private static final String JSR303_VALIDATOR_CLASS = "javax.validation.Validator";
-
- private BeanFactory beanFactory;
-
- @Override
- public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
- this.beanFactory = beanFactory;
- }
-
- @Override
- public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
- BeanDefinitionRegistry registry) {
- if (this.beanFactory instanceof ListableBeanFactory) {
- registerOrAliasWebFluxValidator(registry,
- (ListableBeanFactory) this.beanFactory);
- }
- }
-
- private void registerOrAliasWebFluxValidator(BeanDefinitionRegistry registry,
- ListableBeanFactory beanFactory) {
- String[] validatorBeans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
- beanFactory, Validator.class, false, false);
- if (validatorBeans.length == 0) {
- registerNewWebFluxValidator(registry, beanFactory);
- }
- else if (validatorBeans.length == 1) {
- registry.registerAlias(validatorBeans[0], "webFluxValidator");
- }
- else {
- if (!ObjectUtils.containsElement(validatorBeans, "webFluxValidator")) {
- registerNewWebFluxValidator(registry, beanFactory);
- }
- }
- }
-
- private void registerNewWebFluxValidator(BeanDefinitionRegistry registry,
- ListableBeanFactory beanFactory) {
- RootBeanDefinition definition = new RootBeanDefinition();
- definition.setBeanClass(getClass());
- definition.setFactoryMethodName("webFluxValidator");
- registry.registerBeanDefinition("webFluxValidator", definition);
- }
-
- static Validator webFluxValidator() {
- Validator validator = new WebFluxConfigurationSupport().webFluxValidator();
- try {
- if (ClassUtils.forName(JSR303_VALIDATOR_CLASS, null)
- .isInstance(validator)) {
- return new DelegatingWebFluxValidator(validator);
- }
- }
- catch (Exception ex) {
- }
- return validator;
- }
-
- }
-
- /**
- * {@link DelegatingValidator} for the WebFlux validator.
- */
- static class DelegatingWebFluxValidator extends DelegatingValidator
- implements ApplicationContextAware, InitializingBean, DisposableBean {
-
- DelegatingWebFluxValidator(Validator targetValidator) {
- super(targetValidator);
- }
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext)
- throws BeansException {
- if (getDelegate() instanceof ApplicationContextAware) {
- ((ApplicationContextAware) getDelegate())
- .setApplicationContext(applicationContext);
- }
- }
-
- @Override
- public void afterPropertiesSet() throws Exception {
- if (getDelegate() instanceof InitializingBean) {
- ((InitializingBean) getDelegate()).afterPropertiesSet();
- }
- }
-
- @Override
- public void destroy() throws Exception {
- if (getDelegate() instanceof DisposableBean) {
- ((DisposableBean) getDelegate()).destroy();
- }
- }
-
- }
-
}
diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java
index 0ad98edc85..340ef81751 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java
@@ -30,18 +30,11 @@ import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-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.DisposableBean;
-import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@@ -52,8 +45,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
-import org.springframework.boot.autoconfigure.validation.DelegatingValidator;
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
+import org.springframework.boot.autoconfigure.validation.ValidatorAdapter;
import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties.Strategy;
@@ -61,31 +54,21 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.web.servlet.filter.OrderedHiddenHttpMethodFilter;
import org.springframework.boot.web.servlet.filter.OrderedHttpPutFormContentFilter;
import org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ConditionContext;
-import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.ConfigurationCondition;
import org.springframework.context.annotation.Import;
-import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.core.io.Resource;
-import org.springframework.core.type.AnnotatedTypeMetadata;
-import org.springframework.core.type.AnnotationMetadata;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
-import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
-import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.DefaultMessageCodesResolver;
import org.springframework.validation.MessageCodesResolver;
@@ -172,7 +155,7 @@ public class WebMvcAutoConfiguration {
// Defined as a nested config to ensure WebMvcConfigurer is not read when not
// on the classpath
@Configuration
- @Import({ EnableWebMvcConfiguration.class, MvcValidatorRegistrar.class })
+ @Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
@@ -380,22 +363,21 @@ public class WebMvcAutoConfiguration {
* Configuration equivalent to {@code @EnableWebMvc}.
*/
@Configuration
- public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration
- implements InitializingBean {
+ public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
private final WebMvcProperties mvcProperties;
- private final ApplicationContext context;
+ private final ListableBeanFactory beanFactory;
private final WebMvcRegistrations mvcRegistrations;
public EnableWebMvcConfiguration(
ObjectProvider mvcPropertiesProvider,
ObjectProvider mvcRegistrationsProvider,
- ApplicationContext context) {
+ ListableBeanFactory beanFactory) {
this.mvcProperties = mvcPropertiesProvider.getIfAvailable();
this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique();
- this.context = context;
+ this.beanFactory = beanFactory;
}
@Bean
@@ -426,9 +408,12 @@ public class WebMvcAutoConfiguration {
@Bean
@Override
- @Conditional(DisableMvcValidatorCondition.class)
public Validator mvcValidator() {
- return this.context.getBean("mvcValidator", Validator.class);
+ if (!ClassUtils.isPresent("javax.validation.Validator",
+ getClass().getClassLoader())) {
+ return super.mvcValidator();
+ }
+ return ValidatorAdapter.get(getApplicationContext(), getValidator());
}
@Override
@@ -443,7 +428,7 @@ public class WebMvcAutoConfiguration {
@Override
protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
try {
- return this.context.getBean(ConfigurableWebBindingInitializer.class);
+ return this.beanFactory.getBean(ConfigurableWebBindingInitializer.class);
}
catch (NoSuchBeanDefinitionException ex) {
return super.getConfigurableWebBindingInitializer();
@@ -492,15 +477,6 @@ public class WebMvcAutoConfiguration {
return manager;
}
- @Override
- public void afterPropertiesSet() throws Exception {
- Assert.state(getValidator() == null,
- "Found unexpected validator configuration. A Spring Boot MVC "
- + "validator should be registered as bean named "
- + "'mvcValidator' and not returned from "
- + "WebMvcConfigurer.getValidator()");
- }
-
}
@Configuration
@@ -628,130 +604,4 @@ public class WebMvcAutoConfiguration {
}
- /**
- * Condition used to disable the default MVC validator registration. The
- * {@link MvcValidatorRegistrar} is actually used to register the {@code mvcValidator}
- * bean.
- */
- static class DisableMvcValidatorCondition implements ConfigurationCondition {
-
- @Override
- public ConfigurationPhase getConfigurationPhase() {
- return ConfigurationPhase.REGISTER_BEAN;
- }
-
- @Override
- public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
- return false;
- }
-
- }
-
- /**
- * {@link ImportBeanDefinitionRegistrar} to deal with the MVC validator bean
- * registration. Applies the following rules:
- *
- * - With no validators - Uses standard
- * {@link WebMvcConfigurationSupport#mvcValidator()} logic.
- * - With a single validator - Uses an alias.
- * - With multiple validators - Registers a mvcValidator bean if not already
- * defined.
- *
- */
- static class MvcValidatorRegistrar
- implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
-
- private static final String JSR303_VALIDATOR_CLASS = "javax.validation.Validator";
-
- private BeanFactory beanFactory;
-
- @Override
- public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
- this.beanFactory = beanFactory;
- }
-
- @Override
- public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
- BeanDefinitionRegistry registry) {
- if (this.beanFactory instanceof ListableBeanFactory) {
- registerOrAliasMvcValidator(registry,
- (ListableBeanFactory) this.beanFactory);
- }
- }
-
- private void registerOrAliasMvcValidator(BeanDefinitionRegistry registry,
- ListableBeanFactory beanFactory) {
- String[] validatorBeans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
- beanFactory, Validator.class, false, false);
- if (validatorBeans.length == 0) {
- registerNewMvcValidator(registry, beanFactory);
- }
- else if (validatorBeans.length == 1) {
- registry.registerAlias(validatorBeans[0], "mvcValidator");
- }
- else {
- if (!ObjectUtils.containsElement(validatorBeans, "mvcValidator")) {
- registerNewMvcValidator(registry, beanFactory);
- }
- }
- }
-
- private void registerNewMvcValidator(BeanDefinitionRegistry registry,
- ListableBeanFactory beanFactory) {
- RootBeanDefinition definition = new RootBeanDefinition();
- definition.setBeanClass(getClass());
- definition.setFactoryMethodName("mvcValidator");
- registry.registerBeanDefinition("mvcValidator", definition);
- }
-
- static Validator mvcValidator() {
- Validator validator = new WebMvcConfigurationSupport().mvcValidator();
- try {
- if (ClassUtils.forName(JSR303_VALIDATOR_CLASS, null)
- .isInstance(validator)) {
- return new DelegatingWebMvcValidator(validator);
- }
- }
- catch (Exception ex) {
- }
- return validator;
- }
-
- }
-
- /**
- * {@link DelegatingValidator} for the MVC validator.
- */
- static class DelegatingWebMvcValidator extends DelegatingValidator
- implements ApplicationContextAware, InitializingBean, DisposableBean {
-
- DelegatingWebMvcValidator(Validator targetValidator) {
- super(targetValidator);
- }
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext)
- throws BeansException {
- if (getDelegate() instanceof ApplicationContextAware) {
- ((ApplicationContextAware) getDelegate())
- .setApplicationContext(applicationContext);
- }
- }
-
- @Override
- public void afterPropertiesSet() throws Exception {
- if (getDelegate() instanceof InitializingBean) {
- ((InitializingBean) getDelegate()).afterPropertiesSet();
- }
- }
-
- @Override
- public void destroy() throws Exception {
- if (getDelegate() instanceof DisposableBean) {
- ((DisposableBean) getDelegate()).destroy();
- }
- }
-
- }
-
}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfigurationTests.java
index 0f68897c96..ce9b93a3c6 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfigurationTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SpringBootWebSecurityConfigurationTests.java
@@ -32,7 +32,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
-import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
@@ -323,9 +322,9 @@ public class SpringBootWebSecurityConfigurationTests {
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({ ServletWebServerFactoryAutoConfiguration.class,
- DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class,
- WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
- ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class })
+ DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class,
+ HttpMessageConvertersAutoConfiguration.class, ErrorMvcAutoConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class })
protected @interface MinimalWebConfiguration {
}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/DelegatingValidatorTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/DelegatingValidatorTests.java
deleted file mode 100644
index 04cc4e8c07..0000000000
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/DelegatingValidatorTests.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import org.springframework.validation.BeanPropertyBindingResult;
-import org.springframework.validation.Errors;
-import org.springframework.validation.SmartValidator;
-import org.springframework.validation.Validator;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-/**
- * Tests for {@link DelegatingValidator}.
- *
- * @author Phillip Webb
- */
-public class DelegatingValidatorTests {
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- @Mock
- private SmartValidator delegate;
-
- private DelegatingValidator delegating;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- this.delegating = new DelegatingValidator(this.delegate);
- }
-
- @Test
- public void createWhenJsrValidatorIsNullShouldThrowException() throws Exception {
- this.thrown.expect(IllegalArgumentException.class);
- this.thrown.expectMessage("Target Validator must not be null");
- new DelegatingValidator((javax.validation.Validator) null);
- }
-
- @Test
- public void createWithJsrValidatorShouldAdapt() throws Exception {
- javax.validation.Validator delegate = mock(javax.validation.Validator.class);
- Validator delegating = new DelegatingValidator(delegate);
- Object target = new Object();
- Errors errors = new BeanPropertyBindingResult(target, "foo");
- delegating.validate(target, errors);
- verify(delegate).validate(any());
- }
-
- @Test
- public void createWithSpringValidatorWhenValidatorIsNullShouldThrowException()
- throws Exception {
- this.thrown.expect(IllegalArgumentException.class);
- this.thrown.expectMessage("Target Validator must not be null");
- new DelegatingValidator((Validator) null);
- }
-
- @Test
- public void supportsShouldDelegateToValidator() throws Exception {
- this.delegating.supports(Object.class);
- verify(this.delegate).supports(Object.class);
- }
-
- @Test
- public void validateShouldDelegateToValidator() throws Exception {
- Object target = new Object();
- Errors errors = new BeanPropertyBindingResult(target, "foo");
- this.delegating.validate(target, errors);
- verify(this.delegate).validate(target, errors);
- }
-
- @Test
- public void validateWithHintsShouldDelegateToValidator() throws Exception {
- Object target = new Object();
- Errors errors = new BeanPropertyBindingResult(target, "foo");
- Object[] hints = { "foo", "bar" };
- this.delegating.validate(target, errors, hints);
- verify(this.delegate).validate(target, errors, hints);
- }
-
- @Test
- public void validateWithHintsWhenDelegateIsNotSmartShouldDelegateToSimpleValidator()
- throws Exception {
- Validator delegate = mock(Validator.class);
- DelegatingValidator delegating = new DelegatingValidator(delegate);
- Object target = new Object();
- Errors errors = new BeanPropertyBindingResult(target, "foo");
- Object[] hints = { "foo", "bar" };
- delegating.validate(target, errors, hints);
- verify(delegate).validate(target, errors);
- }
-
-}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/ValidationAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/ValidationAutoConfigurationTests.java
index df2e7e3cd9..1f83b02e4d 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/ValidationAutoConfigurationTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/ValidationAutoConfigurationTests.java
@@ -31,6 +31,7 @@ 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;
@@ -43,6 +44,7 @@ import static org.mockito.Mockito.mock;
* Tests for {@link ValidationAutoConfiguration}.
*
* @author Stephane Nicoll
+ * @author Phillip Webb
*/
public class ValidationAutoConfigurationTests {
@@ -59,94 +61,134 @@ public class ValidationAutoConfigurationTests {
}
@Test
- public void validationAutoConfigurationShouldConfigureJsrAndSpringValidator()
- throws Exception {
+ public void validationAutoConfigurationShouldConfigureDefaultValidator() {
load(Config.class);
- Validator jsrValidator = this.context.getBean(Validator.class);
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
- org.springframework.validation.Validator springValidator = this.context
- .getBean(org.springframework.validation.Validator.class);
String[] springValidatorNames = this.context
.getBeanNamesForType(org.springframework.validation.Validator.class);
- assertThat(jsrValidator).isInstanceOf(LocalValidatorFactoryBean.class);
- assertThat(jsrValidator).isEqualTo(springValidator);
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()
- throws Exception {
+ public void validationAutoConfigurationWhenUserProvidesValidatorShouldBackOff() {
load(UserDefinedValidatorConfig.class);
- Validator jsrValidator = this.context.getBean(Validator.class);
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
- org.springframework.validation.Validator springValidator = this.context
- .getBean(org.springframework.validation.Validator.class);
String[] springValidatorNames = this.context
.getBeanNamesForType(org.springframework.validation.Validator.class);
- assertThat(jsrValidator).isInstanceOf(OptionalValidatorFactoryBean.class);
- assertThat(jsrValidator).isEqualTo(springValidator);
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 validationAutoConfigurationWhenUserProvidesJsrOnlyShouldAdaptIt()
- throws Exception {
+ 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);
- Validator jsrValidator = this.context.getBean(Validator.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(jsrValidator).isNotEqualTo(springValidator);
- assertThat(springValidator).isInstanceOf(DelegatingValidator.class);
- assertThat(jsrValidatorNames).containsExactly("customValidator");
- assertThat(springValidatorNames).containsExactly("jsr303ValidatorAdapter");
+ 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 validationAutoConfigurationShouldBeEnabled() {
- load(ClassWithConstraint.class);
+ public void validationIsEnabled() {
+ load(SampleService.class);
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
- ClassWithConstraint service = this.context.getBean(ClassWithConstraint.class);
- service.call("Valid");
+ SampleService service = this.context.getBean(SampleService.class);
+ service.doSomething("Valid");
this.thrown.expect(ConstraintViolationException.class);
- service.call("KO");
+ service.doSomething("KO");
}
@Test
- public void validationAutoConfigurationShouldUseCglibProxy() {
- load(ImplementationOfInterfaceWithConstraint.class);
+ public void validationUsesCglibProxy() {
+ load(DefaultAnotherSampleService.class);
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
- ImplementationOfInterfaceWithConstraint service = this.context
- .getBean(ImplementationOfInterfaceWithConstraint.class);
- service.call(42);
+ DefaultAnotherSampleService service = this.context
+ .getBean(DefaultAnotherSampleService.class);
+ service.doSomething(42);
this.thrown.expect(ConstraintViolationException.class);
- service.call(2);
+ service.doSomething(2);
}
@Test
- public void validationAutoConfigurationWhenProxyTargetClassIsFalseShouldUseJdkProxy() {
+ public void validationCanBeConfiguredToUseJdkProxy() {
load(AnotherSampleServiceConfiguration.class,
"spring.aop.proxy-target-class=false");
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
- assertThat(this.context
- .getBeansOfType(ImplementationOfInterfaceWithConstraint.class)).isEmpty();
- InterfaceWithConstraint service = this.context
- .getBean(InterfaceWithConstraint.class);
- service.call(42);
+ assertThat(this.context.getBeansOfType(DefaultAnotherSampleService.class))
+ .isEmpty();
+ AnotherSampleService service = this.context.getBean(AnotherSampleService.class);
+ service.doSomething(42);
this.thrown.expect(ConstraintViolationException.class);
- service.call(2);
+ service.doSomething(2);
}
@Test
- public void validationAutoConfigurationWhenUserDefinesMethodValidationPostProcessorShouldBackOff() {
- load(UserDefinedMethodValidationConfig.class);
+ public void userDefinedMethodValidationPostProcessorTakesPrecedence() {
+ load(SampleConfiguration.class);
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
Object userMethodValidationPostProcessor = this.context
- .getBean("customMethodValidationPostProcessor");
+ .getBean("testMethodValidationPostProcessor");
assertThat(this.context.getBean(MethodValidationPostProcessor.class))
.isSameAs(userMethodValidationPostProcessor);
assertThat(this.context.getBeansOfType(MethodValidationPostProcessor.class))
@@ -156,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) {
@@ -182,6 +228,16 @@ public class ValidationAutoConfigurationTests {
}
+ @Configuration
+ static class UserDefinedDefaultValidatorConfig {
+
+ @Bean
+ public OptionalValidatorFactoryBean defaultValidator() {
+ return new OptionalValidatorFactoryBean();
+ }
+
+ }
+
@Configuration
static class UserDefinedJsrValidatorConfig {
@@ -193,47 +249,77 @@ public class ValidationAutoConfigurationTests {
}
@Configuration
- static class UserDefinedMethodValidationConfig {
+ static class UserDefinedSpringValidatorConfig {
@Bean
- public MethodValidationPostProcessor customMethodValidationPostProcessor() {
- return new MethodValidationPostProcessor();
+ 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 AnotherSampleServiceConfiguration {
+ static class UserDefinedPrimarySpringValidatorConfig {
+
+ @Bean
+ public org.springframework.validation.Validator customValidator() {
+ return mock(org.springframework.validation.Validator.class);
+ }
@Bean
- public InterfaceWithConstraint implementationOfInterfaceWithConstraint() {
- return new ImplementationOfInterfaceWithConstraint();
+ @Primary
+ public org.springframework.validation.Validator anotherCustomValidator() {
+ return mock(org.springframework.validation.Validator.class);
}
}
@Validated
- static class ClassWithConstraint {
+ static class SampleService {
- public void call(@Size(min = 3, max = 10) String name) {
+ public void doSomething(@Size(min = 3, max = 10) String name) {
}
}
- interface InterfaceWithConstraint {
+ interface AnotherSampleService {
- void call(@Min(42) Integer counter);
+ void doSomething(@Min(42) Integer counter);
}
@Validated
- static class ImplementationOfInterfaceWithConstraint
- implements InterfaceWithConstraint {
+ static class DefaultAnotherSampleService implements AnotherSampleService {
@Override
- public void call(Integer counter) {
+ public void doSomething(Integer counter) {
}
}
+ @Configuration
+ static class AnotherSampleServiceConfiguration {
+
+ @Bean
+ public AnotherSampleService anotherSampleService() {
+ return new DefaultAnotherSampleService();
+ }
+
+ }
+
+ @Configuration
+ static class SampleConfiguration {
+
+ @Bean
+ public MethodValidationPostProcessor testMethodValidationPostProcessor() {
+ return new MethodValidationPostProcessor();
+ }
+
+ }
+
}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/ValidatorAdapterTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/ValidatorAdapterTests.java
new file mode 100644
index 0000000000..8d6f0858bc
--- /dev/null
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/validation/ValidatorAdapterTests.java
@@ -0,0 +1,152 @@
+/*
+ * 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 java.util.HashMap;
+
+import javax.validation.constraints.Min;
+
+import org.junit.After;
+import org.junit.Test;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.MapBindingResult;
+import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Tests for {@link ValidatorAdapter}.
+ *
+ * @author Stephane Nicoll
+ */
+public class ValidatorAdapterTests {
+
+ private AnnotationConfigApplicationContext context;
+
+ @After
+ public void close() {
+ if (this.context != null) {
+ this.context.close();
+ }
+ }
+
+ @Test
+ public void wrapLocalValidatorFactoryBean() {
+ ValidatorAdapter wrapper = load(
+ LocalValidatorFactoryBeanConfig.class);
+ assertThat(wrapper.supports(SampleData.class)).isTrue();
+ MapBindingResult errors = new MapBindingResult(new HashMap(),
+ "test");
+ wrapper.validate(new SampleData(40), errors);
+ assertThat(errors.getErrorCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void wrapperInvokesCallbackOnNonManagedBean() {
+ load(NonManagedBeanConfig.class);
+ LocalValidatorFactoryBean validator = this.context
+ .getBean(NonManagedBeanConfig.class).validator;
+ verify(validator, times(1)).setApplicationContext(any(ApplicationContext.class));
+ verify(validator, times(1)).afterPropertiesSet();
+ verify(validator, times(0)).destroy();
+ this.context.close();
+ this.context = null;
+ verify(validator, times(1)).destroy();
+ }
+
+ @Test
+ public void wrapperDoesNotInvokeCallbackOnManagedBean() {
+ load(ManagedBeanConfig.class);
+ LocalValidatorFactoryBean validator = this.context
+ .getBean(ManagedBeanConfig.class).validator;
+ verify(validator, times(0)).setApplicationContext(any(ApplicationContext.class));
+ verify(validator, times(0)).afterPropertiesSet();
+ verify(validator, times(0)).destroy();
+ this.context.close();
+ this.context = null;
+ verify(validator, times(0)).destroy();
+ }
+
+ private ValidatorAdapter load(Class> config) {
+ AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
+ ctx.register(config);
+ ctx.refresh();
+ this.context = ctx;
+ return this.context.getBean(ValidatorAdapter.class);
+ }
+
+ @Configuration
+ static class LocalValidatorFactoryBeanConfig {
+
+ @Bean
+ public LocalValidatorFactoryBean validator() {
+ return new LocalValidatorFactoryBean();
+ }
+
+ @Bean
+ public ValidatorAdapter wrapper() {
+ return new ValidatorAdapter(validator(), true);
+ }
+
+ }
+
+ @Configuration
+ static class NonManagedBeanConfig {
+
+ private final LocalValidatorFactoryBean validator = mock(
+ LocalValidatorFactoryBean.class);
+
+ @Bean
+ public ValidatorAdapter wrapper() {
+ return new ValidatorAdapter(this.validator, false);
+ }
+
+ }
+
+ @Configuration
+ static class ManagedBeanConfig {
+
+ private final LocalValidatorFactoryBean validator = mock(
+ LocalValidatorFactoryBean.class);
+
+ @Bean
+ public ValidatorAdapter wrapper() {
+ return new ValidatorAdapter(this.validator, true);
+ }
+
+ }
+
+ static class SampleData {
+
+ @Min(42)
+ private int counter;
+
+ SampleData(int counter) {
+ this.counter = counter;
+ }
+
+ }
+
+}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java
index 70ba22a0f8..bddf089f29 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/reactive/WebFluxAutoConfigurationTests.java
@@ -21,13 +21,15 @@ import java.util.Arrays;
import java.util.List;
import java.util.Optional;
+import javax.validation.ValidatorFactory;
+
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import org.springframework.beans.factory.BeanCreationException;
-import org.springframework.boot.autoconfigure.validation.DelegatingValidator;
+import org.springframework.beans.DirectFieldAccessor;
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
+import org.springframework.boot.autoconfigure.validation.ValidatorAdapter;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfigurationTests.Config;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.util.EnvironmentTestUtils;
@@ -172,134 +174,107 @@ public class WebFluxAutoConfigurationTests {
}
@Test
- public void validatorWhenSuppliedByConfigurerShouldThrowException() throws Exception {
- this.thrown.expect(BeanCreationException.class);
- this.thrown.expectMessage("unexpected validator configuration");
- load(ValidatorWebFluxConfigurer.class);
+ 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();
+ String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
+ assertThat(springValidatorBeans).containsExactly("webFluxValidator");
}
@Test
- public void validatorWhenAutoConfiguredShouldUseAlias() throws Exception {
+ public void validatorWhenNoCustomizationShouldUseAutoConfigured() {
load();
- Object defaultValidator = this.context.getBean("defaultValidator");
- Object webFluxValidator = this.context.getBean("webFluxValidator");
String[] jsrValidatorBeans = this.context
.getBeanNamesForType(javax.validation.Validator.class);
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(webFluxValidator).isSameAs(defaultValidator);
- assertThat(springValidatorBeans).containsExactly("defaultValidator");
assertThat(jsrValidatorBeans).containsExactly("defaultValidator");
+ assertThat(springValidatorBeans).containsExactly("defaultValidator", "webFluxValidator");
+ Validator validator = this.context.getBean("webFluxValidator", Validator.class);
+ assertThat(validator).isInstanceOf(ValidatorAdapter.class);
+ Object defaultValidator = this.context.getBean("defaultValidator");
+ assertThat(((ValidatorAdapter) validator).getTarget()).isSameAs(defaultValidator);
+ // Primary Spring validator is the one use by WebFlux behind the scenes
+ assertThat(this.context.getBean(Validator.class)).isEqualTo(defaultValidator);
}
@Test
- public void validatorWhenUserDefinedSpringOnlyShouldUseDefined() throws Exception {
- load(UserDefinedSpringOnlyValidator.class);
- Object customValidator = this.context.getBean("customValidator");
- Object webFluxValidator = this.context.getBean("webFluxValidator");
- String[] jsrValidatorBeans = this.context
- .getBeanNamesForType(javax.validation.Validator.class);
- String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(webFluxValidator).isSameAs(customValidator);
- assertThat(this.context.getBean(Validator.class)).isEqualTo(customValidator);
- assertThat(springValidatorBeans).containsExactly("customValidator");
- assertThat(jsrValidatorBeans).isEmpty();
- }
-
- @Test
- public void validatorWhenUserDefinedJsr303ShouldAdapt() throws Exception {
- load(UserDefinedJsr303Validator.class);
- Object customValidator = this.context.getBean("customValidator");
- Object webFluxValidator = this.context.getBean("webFluxValidator");
- String[] jsrValidatorBeans = this.context
- .getBeanNamesForType(javax.validation.Validator.class);
+ public void validatorWithConfigurerShouldUseSpringValidator() {
+ load(ValidatorWebFluxConfigurer.class,
+ new Class>[] { ValidationAutoConfiguration.class });
+ assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
+ assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
+ .isEmpty();
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(webFluxValidator).isNotSameAs(customValidator);
- assertThat(this.context.getBean(javax.validation.Validator.class))
- .isEqualTo(customValidator);
- assertThat(springValidatorBeans).containsExactly("jsr303ValidatorAdapter");
- assertThat(jsrValidatorBeans).containsExactly("customValidator");
+ assertThat(springValidatorBeans).containsExactly("webFluxValidator");
+ assertThat(this.context.getBean("webFluxValidator"))
+ .isSameAs(this.context.getBean(ValidatorWebFluxConfigurer.class).validator);
}
@Test
- public void validatorWhenUserDefinedSingleJsr303AndSpringShouldUseDefined()
- throws Exception {
- load(UserDefinedSingleJsr303AndSpringValidator.class);
- Object customValidator = this.context.getBean("customValidator");
- Object webFluxValidator = this.context.getBean("webFluxValidator");
- String[] jsrValidatorBeans = this.context
- .getBeanNamesForType(javax.validation.Validator.class);
+ public void validatorWithConfigurerDoesNotExposeJsr303() {
+ load(ValidatorJsr303WebFluxConfigurer.class, new Class>[] { ValidationAutoConfiguration.class });
+ assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
+ assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
+ .isEmpty();
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(webFluxValidator).isSameAs(customValidator);
- assertThat(this.context.getBean(javax.validation.Validator.class))
- .isEqualTo(customValidator);
- assertThat(this.context.getBean(Validator.class)).isEqualTo(customValidator);
- assertThat(springValidatorBeans).containsExactly("customValidator");
- assertThat(jsrValidatorBeans).containsExactly("customValidator");
+ assertThat(springValidatorBeans).containsExactly("webFluxValidator");
+ Validator validator = this.context.getBean("webFluxValidator", Validator.class);
+ assertThat(validator).isInstanceOf(ValidatorAdapter.class);
+ assertThat(((ValidatorAdapter) validator).getTarget())
+ .isSameAs(this.context.getBean(ValidatorJsr303WebFluxConfigurer.class).validator);
}
@Test
- public void validatorWhenUserDefinedJsr303AndSpringShouldUseDefined()
- throws Exception {
- load(UserDefinedJsr303AndSpringValidator.class);
- Object customJsrValidator = this.context.getBean("customJsrValidator");
- Object customSpringValidator = this.context.getBean("customSpringValidator");
- Object webFluxValidator = this.context.getBean("webFluxValidator");
- String[] jsrValidatorBeans = this.context
- .getBeanNamesForType(javax.validation.Validator.class);
+ public void validationCustomConfigurerTakesPrecedence() {
+ load(ValidatorWebFluxConfigurer.class);
+ assertThat(this.context.getBeansOfType(ValidatorFactory.class)).hasSize(1);
+ assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
+ .hasSize(1);
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(customJsrValidator).isNotSameAs(customSpringValidator);
- assertThat(webFluxValidator).isSameAs(customSpringValidator);
- assertThat(this.context.getBean(javax.validation.Validator.class))
- .isEqualTo(customJsrValidator);
+ assertThat(springValidatorBeans)
+ .containsExactly("defaultValidator", "webFluxValidator");
+ assertThat(this.context.getBean("webFluxValidator"))
+ .isSameAs(this.context.getBean(ValidatorWebFluxConfigurer.class).validator);
+ // Primary Spring validator is the auto-configured one as the WebFlux one has been
+ // customized via a WebFluxConfigurer
assertThat(this.context.getBean(Validator.class))
- .isEqualTo(customSpringValidator);
- assertThat(springValidatorBeans).containsExactly("customSpringValidator");
- assertThat(jsrValidatorBeans).containsExactly("customJsrValidator");
- }
-
- @Test
- public void validatorWhenExcludingValidatorAutoConfigurationShouldUseWebFlux()
- throws Exception {
- load(null, new Class[] { ValidationAutoConfiguration.class });
- Object webFluxValidator = this.context.getBean("webFluxValidator");
- String[] jsrValidatorBeans = this.context
- .getBeanNamesForType(javax.validation.Validator.class);
- String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(webFluxValidator).isInstanceOf(DelegatingValidator.class);
- assertThat(springValidatorBeans).containsExactly("webFluxValidator");
- assertThat(jsrValidatorBeans).isEmpty();
+ .isEqualTo(this.context.getBean("defaultValidator"));
}
@Test
- public void validatorWhenMultipleValidatorsAndNoWebFluxValidatorShouldAddWebFlux()
- throws Exception {
- load(MultipleValidatorsAndNoWebFluxValidator.class);
- Object customValidator1 = this.context.getBean("customValidator1");
- Object customValidator2 = this.context.getBean("customValidator2");
- Object webFluxValidator = this.context.getBean("webFluxValidator");
+ public void validatorWithCustomSpringValidatorIgnored() {
+ load(CustomSpringValidator.class);
String[] jsrValidatorBeans = this.context
.getBeanNamesForType(javax.validation.Validator.class);
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(webFluxValidator).isNotSameAs(customValidator1)
- .isNotSameAs(customValidator2);
- assertThat(springValidatorBeans).containsExactly("customValidator1",
- "customValidator2", "webFluxValidator");
- assertThat(jsrValidatorBeans).isEmpty();
+ assertThat(jsrValidatorBeans).containsExactly("defaultValidator");
+ assertThat(springValidatorBeans).containsExactly(
+ "customValidator", "defaultValidator", "webFluxValidator");
+ Validator validator = this.context.getBean("webFluxValidator", Validator.class);
+ assertThat(validator).isInstanceOf(ValidatorAdapter.class);
+ Object defaultValidator = this.context.getBean("defaultValidator");
+ assertThat(((ValidatorAdapter) validator).getTarget())
+ .isSameAs(defaultValidator);
+ // Primary Spring validator is the one use by WebFlux behind the scenes
+ assertThat(this.context.getBean(Validator.class)).isEqualTo(defaultValidator);
}
@Test
- public void validatorWhenMultipleValidatorsAndWebFluxValidatorShouldUseWebFlux()
- throws Exception {
- load(MultipleValidatorsAndWebFluxValidator.class);
- Object customValidator = this.context.getBean("customValidator");
- Object webFluxValidator = this.context.getBean("webFluxValidator");
+ public void validatorWithCustomJsr303ValidatorExposedAsSpringValidator() {
+ load(CustomJsr303Validator.class);
+ assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
String[] jsrValidatorBeans = this.context
.getBeanNamesForType(javax.validation.Validator.class);
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(webFluxValidator).isNotSameAs(customValidator);
- assertThat(springValidatorBeans).containsExactly("customValidator",
- "webFluxValidator");
- assertThat(jsrValidatorBeans).isEmpty();
+ assertThat(jsrValidatorBeans).containsExactly("customValidator");
+ assertThat(springValidatorBeans).containsExactly("webFluxValidator");
+ Validator validator = this.context.getBean(Validator.class);
+ assertThat(validator).isInstanceOf(ValidatorAdapter.class);
+ Validator target = ((ValidatorAdapter) validator).getTarget();
+ assertThat(new DirectFieldAccessor(target).getPropertyValue("targetValidator"))
+ .isSameAs(this.context.getBean("customValidator"));
}
private void load(String... environment) {
@@ -324,7 +299,6 @@ public class WebFluxAutoConfigurationTests {
}
this.context.register(configClasses.toArray(new Class>[configClasses.size()]));
this.context.refresh();
-
}
@Configuration
@@ -381,86 +355,45 @@ public class WebFluxAutoConfigurationTests {
@Configuration
protected static class ValidatorWebFluxConfigurer implements WebFluxConfigurer {
+ private final Validator validator = mock(Validator.class);
+
@Override
public Optional getValidator() {
- return Optional.of(mock(Validator.class));
+ return Optional.of(this.validator);
}
}
@Configuration
- static class UserDefinedSpringOnlyValidator {
+ protected static class ValidatorJsr303WebFluxConfigurer implements WebFluxConfigurer {
- @Bean
- public Validator customValidator() {
- return mock(Validator.class);
- }
-
- }
-
- @Configuration
- static class UserDefinedJsr303Validator {
-
- @Bean
- public javax.validation.Validator customValidator() {
- return mock(javax.validation.Validator.class);
- }
+ private final LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
- }
-
- @Configuration
- static class UserDefinedSingleJsr303AndSpringValidator {
-
- @Bean
- public LocalValidatorFactoryBean customValidator() {
- return new LocalValidatorFactoryBean();
+ @Override
+ public Optional getValidator() {
+ return Optional.of(this.validator);
}
}
@Configuration
- static class UserDefinedJsr303AndSpringValidator {
+ static class CustomJsr303Validator {
@Bean
- public javax.validation.Validator customJsrValidator() {
+ public javax.validation.Validator customValidator() {
return mock(javax.validation.Validator.class);
}
- @Bean
- public Validator customSpringValidator() {
- return mock(Validator.class);
- }
-
}
@Configuration
- static class MultipleValidatorsAndNoWebFluxValidator {
-
- @Bean
- public Validator customValidator1() {
- return mock(Validator.class);
- }
-
- @Bean
- public Validator customValidator2() {
- return mock(Validator.class);
- }
-
- }
-
- @Configuration
- static class MultipleValidatorsAndWebFluxValidator {
+ static class CustomSpringValidator {
@Bean
public Validator customValidator() {
return mock(Validator.class);
}
- @Bean
- public Validator webFluxValidator() {
- return mock(Validator.class);
- }
-
}
}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java
index 206650331a..87f9df050f 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java
@@ -27,6 +27,7 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.validation.ValidatorFactory;
import org.assertj.core.api.Condition;
import org.joda.time.DateTime;
@@ -36,13 +37,12 @@ import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.DirectFieldAccessor;
-import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
-import org.springframework.boot.autoconfigure.validation.DelegatingValidator;
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
+import org.springframework.boot.autoconfigure.validation.ValidatorAdapter;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.WelcomePageHandlerMapping;
import org.springframework.boot.test.util.EnvironmentTestUtils;
@@ -659,134 +659,105 @@ public class WebMvcAutoConfigurationTests {
}
@Test
- public void validatorWhenSuppliedByConfigurerShouldThrowException() throws Exception {
- this.thrown.expect(BeanCreationException.class);
- this.thrown.expectMessage("unexpected validator configuration");
- load(ValidatorWebMvcConfigurer.class);
+ 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();
+ String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
+ assertThat(springValidatorBeans).containsExactly("mvcValidator");
}
@Test
- public void validatorWhenAutoConfiguredShouldUseAlias() throws Exception {
+ public void validatorWhenNoCustomizationShouldUseAutoConfigured() {
load();
- Object defaultValidator = this.context.getBean("defaultValidator");
- Object mvcValidator = this.context.getBean("mvcValidator");
String[] jsrValidatorBeans = this.context
.getBeanNamesForType(javax.validation.Validator.class);
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(mvcValidator).isSameAs(defaultValidator);
- assertThat(springValidatorBeans).containsExactly("defaultValidator");
assertThat(jsrValidatorBeans).containsExactly("defaultValidator");
+ assertThat(springValidatorBeans).containsExactly("defaultValidator", "mvcValidator");
+ Validator validator = this.context.getBean("mvcValidator", Validator.class);
+ assertThat(validator).isInstanceOf(ValidatorAdapter.class);
+ Object defaultValidator = this.context.getBean("defaultValidator");
+ assertThat(((ValidatorAdapter) 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 validatorWhenUserDefinedSpringOnlyShouldUseDefined() throws Exception {
- load(UserDefinedSpringOnlyValidator.class);
- Object customValidator = this.context.getBean("customValidator");
- Object mvcValidator = this.context.getBean("mvcValidator");
- String[] jsrValidatorBeans = this.context
- .getBeanNamesForType(javax.validation.Validator.class);
+ 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();
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(mvcValidator).isSameAs(customValidator);
- assertThat(this.context.getBean(Validator.class)).isEqualTo(customValidator);
- assertThat(springValidatorBeans).containsExactly("customValidator");
- assertThat(jsrValidatorBeans).isEmpty();
- }
-
- @Test
- public void validatorWhenUserDefinedJsr303ShouldAdapt() throws Exception {
- load(UserDefinedJsr303Validator.class);
- Object customValidator = this.context.getBean("customValidator");
- Object mvcValidator = this.context.getBean("mvcValidator");
- String[] jsrValidatorBeans = this.context
- .getBeanNamesForType(javax.validation.Validator.class);
- String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(mvcValidator).isNotSameAs(customValidator);
- assertThat(this.context.getBean(javax.validation.Validator.class))
- .isEqualTo(customValidator);
- assertThat(springValidatorBeans).containsExactly("jsr303ValidatorAdapter");
- assertThat(jsrValidatorBeans).containsExactly("customValidator");
+ assertThat(springValidatorBeans).containsExactly("mvcValidator");
+ assertThat(this.context.getBean("mvcValidator"))
+ .isSameAs(this.context.getBean(MvcValidator.class).validator);
}
@Test
- public void validatorWhenUserDefinedSingleJsr303AndSpringShouldUseDefined()
- throws Exception {
- load(UserDefinedSingleJsr303AndSpringValidator.class);
- Object customValidator = this.context.getBean("customValidator");
- Object mvcValidator = this.context.getBean("mvcValidator");
- String[] jsrValidatorBeans = this.context
- .getBeanNamesForType(javax.validation.Validator.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();
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(mvcValidator).isSameAs(customValidator);
- assertThat(this.context.getBean(javax.validation.Validator.class))
- .isEqualTo(customValidator);
- assertThat(this.context.getBean(Validator.class)).isEqualTo(customValidator);
- assertThat(springValidatorBeans).containsExactly("customValidator");
- assertThat(jsrValidatorBeans).containsExactly("customValidator");
+ assertThat(springValidatorBeans).containsExactly("mvcValidator");
+ Validator validator = this.context.getBean("mvcValidator", Validator.class);
+ assertThat(validator).isInstanceOf(ValidatorAdapter.class);
+ assertThat(((ValidatorAdapter) validator).getTarget())
+ .isSameAs(this.context.getBean(MvcJsr303Validator.class).validator);
}
@Test
- public void validatorWhenUserDefinedJsr303AndSpringShouldUseDefined()
- throws Exception {
- load(UserDefinedJsr303AndSpringValidator.class);
- Object customJsrValidator = this.context.getBean("customJsrValidator");
- Object customSpringValidator = this.context.getBean("customSpringValidator");
- Object mvcValidator = this.context.getBean("mvcValidator");
- String[] jsrValidatorBeans = this.context
- .getBeanNamesForType(javax.validation.Validator.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);
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(customJsrValidator).isNotSameAs(customSpringValidator);
- assertThat(mvcValidator).isSameAs(customSpringValidator);
- assertThat(this.context.getBean(javax.validation.Validator.class))
- .isEqualTo(customJsrValidator);
+ 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(customSpringValidator);
- assertThat(springValidatorBeans).containsExactly("customSpringValidator");
- assertThat(jsrValidatorBeans).containsExactly("customJsrValidator");
+ .isEqualTo(this.context.getBean("defaultValidator"));
}
@Test
- public void validatorWhenExcludingValidatorAutoConfigurationShouldUseMvc()
- throws Exception {
- load(null, new Class[] { ValidationAutoConfiguration.class });
- Object mvcValidator = this.context.getBean("mvcValidator");
+ public void validatorWithCustomSpringValidatorIgnored() {
+ load(CustomSpringValidator.class);
String[] jsrValidatorBeans = this.context
.getBeanNamesForType(javax.validation.Validator.class);
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(mvcValidator).isInstanceOf(DelegatingValidator.class);
- assertThat(springValidatorBeans).containsExactly("mvcValidator");
- assertThat(jsrValidatorBeans).isEmpty();
- }
-
- @Test
- public void validatorWhenMultipleValidatorsAndNoMvcValidatorShouldAddMvc()
- throws Exception {
- load(MultipleValidatorsAndNoMvcValidator.class);
- Object customValidator1 = this.context.getBean("customValidator1");
- Object customValidator2 = this.context.getBean("customValidator2");
- Object mvcValidator = this.context.getBean("mvcValidator");
- String[] jsrValidatorBeans = this.context
- .getBeanNamesForType(javax.validation.Validator.class);
- String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(mvcValidator).isNotSameAs(customValidator1)
- .isNotSameAs(customValidator2);
- assertThat(springValidatorBeans).containsExactly("customValidator1",
- "customValidator2", "mvcValidator");
- assertThat(jsrValidatorBeans).isEmpty();
+ assertThat(jsrValidatorBeans).containsExactly("defaultValidator");
+ assertThat(springValidatorBeans).containsExactly(
+ "customSpringValidator", "defaultValidator", "mvcValidator");
+ Validator validator = this.context.getBean("mvcValidator", Validator.class);
+ assertThat(validator).isInstanceOf(ValidatorAdapter.class);
+ Object defaultValidator = this.context.getBean("defaultValidator");
+ assertThat(((ValidatorAdapter) 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 validatorWhenMultipleValidatorsAndMvcValidatorShouldUseMvc()
- throws Exception {
- load(MultipleValidatorsAndMvcValidator.class);
- Object customValidator = this.context.getBean("customValidator");
- Object mvcValidator = this.context.getBean("mvcValidator");
+ public void validatorWithCustomJsr303ValidatorExposedAsSpringValidator() {
+ load(CustomJsr303Validator.class);
+ assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
String[] jsrValidatorBeans = this.context
.getBeanNamesForType(javax.validation.Validator.class);
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
- assertThat(mvcValidator).isNotSameAs(customValidator);
- assertThat(springValidatorBeans).containsExactly("customValidator",
- "mvcValidator");
- assertThat(jsrValidatorBeans).isEmpty();
+ assertThat(jsrValidatorBeans).containsExactly("customJsr303Validator");
+ assertThat(springValidatorBeans).containsExactly("mvcValidator");
+ Validator validator = this.context.getBean(Validator.class);
+ assertThat(validator).isInstanceOf(ValidatorAdapter.class);
+ Validator target = ((ValidatorAdapter) validator).getTarget();
+ assertThat(new DirectFieldAccessor(target).getPropertyValue("targetValidator"))
+ .isSameAs(this.context.getBean("customJsr303Validator"));
}
private void load(Class> config, String... environment) {
@@ -976,85 +947,44 @@ public class WebMvcAutoConfigurationTests {
}
@Configuration
- protected static class ValidatorWebMvcConfigurer implements WebMvcConfigurer {
+ protected static class MvcValidator implements WebMvcConfigurer {
+
+ private final Validator validator = mock(Validator.class);
@Override
public Validator getValidator() {
- return mock(Validator.class);
- }
-
- }
-
- @Configuration
- static class UserDefinedSpringOnlyValidator {
-
- @Bean
- public Validator customValidator() {
- return mock(Validator.class);
+ return this.validator;
}
}
@Configuration
- static class UserDefinedJsr303Validator {
+ protected static class MvcJsr303Validator implements WebMvcConfigurer {
- @Bean
- public javax.validation.Validator customValidator() {
- return mock(javax.validation.Validator.class);
- }
+ private final LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
- }
-
- @Configuration
- static class UserDefinedSingleJsr303AndSpringValidator {
-
- @Bean
- public LocalValidatorFactoryBean customValidator() {
- return new LocalValidatorFactoryBean();
+ @Override
+ public Validator getValidator() {
+ return this.validator;
}
}
@Configuration
- static class UserDefinedJsr303AndSpringValidator {
+ static class CustomJsr303Validator {
@Bean
- public javax.validation.Validator customJsrValidator() {
+ public javax.validation.Validator customJsr303Validator() {
return mock(javax.validation.Validator.class);
}
- @Bean
- public Validator customSpringValidator() {
- return mock(Validator.class);
- }
-
}
@Configuration
- static class MultipleValidatorsAndNoMvcValidator {
-
- @Bean
- public Validator customValidator1() {
- return mock(Validator.class);
- }
+ static class CustomSpringValidator {
@Bean
- public Validator customValidator2() {
- return mock(Validator.class);
- }
-
- }
-
- @Configuration
- static class MultipleValidatorsAndMvcValidator {
-
- @Bean
- public Validator customValidator() {
- return mock(Validator.class);
- }
-
- @Bean
- public Validator mvcValidator() {
+ public Validator customSpringValidator() {
return mock(Validator.class);
}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerDirectMockMvcTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerDirectMockMvcTests.java
index ce092308ec..255d07e773 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerDirectMockMvcTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerDirectMockMvcTests.java
@@ -36,7 +36,6 @@ import org.junit.rules.ExpectedException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
-import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
@@ -130,9 +129,9 @@ public class BasicErrorControllerDirectMockMvcTests {
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({ ServletWebServerFactoryAutoConfiguration.class,
- DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class,
- WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
- ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class })
+ DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class,
+ HttpMessageConvertersAutoConfiguration.class, ErrorMvcAutoConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class })
protected @interface MinimalWebConfiguration {
}
diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerMockMvcTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerMockMvcTests.java
index 45e451a9a5..881dc9cf32 100644
--- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerMockMvcTests.java
+++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorControllerMockMvcTests.java
@@ -36,7 +36,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
-import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
@@ -132,9 +131,9 @@ public class BasicErrorControllerMockMvcTests {
@Documented
@Import({ ServletWebServerFactoryAutoConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryAutoConfiguration.class,
- DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class,
- WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
- ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class })
+ DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class,
+ HttpMessageConvertersAutoConfiguration.class, ErrorMvcAutoConfiguration.class,
+ PropertyPlaceholderAutoConfiguration.class })
private @interface MinimalWebConfiguration {
}