Merge branch '1.5.x'
This commit is contained in:
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2017 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.autoconfigure.validation;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
|
import org.springframework.beans.factory.BeanFactoryAware;
|
||||||
|
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
|
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||||
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
|
import org.springframework.validation.Validator;
|
||||||
|
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable the {@code Primary} flag on the auto-configured validator if necessary.
|
||||||
|
* <p>
|
||||||
|
* As {@link LocalValidatorFactoryBean} exposes 3 validator related contracts and we're
|
||||||
|
* only checking for the absence {@link javax.validation.Validator}, we should flag the
|
||||||
|
* auto-configured validator as primary only if no Spring's {@link Validator} is flagged
|
||||||
|
* as primary.
|
||||||
|
*
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
*/
|
||||||
|
class PrimaryDefaultValidatorPostProcessor
|
||||||
|
implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bean name of the auto-configured Validator.
|
||||||
|
*/
|
||||||
|
private static final String VALIDATOR_BEAN_NAME = "defaultValidator";
|
||||||
|
|
||||||
|
private ConfigurableListableBeanFactory beanFactory;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||||
|
if (beanFactory instanceof ConfigurableListableBeanFactory) {
|
||||||
|
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
|
||||||
|
BeanDefinitionRegistry registry) {
|
||||||
|
if (this.beanFactory == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!registry.containsBeanDefinition(VALIDATOR_BEAN_NAME)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BeanDefinition def = registry.getBeanDefinition(VALIDATOR_BEAN_NAME);
|
||||||
|
if (def != null
|
||||||
|
&& this.beanFactory.isTypeMatch(VALIDATOR_BEAN_NAME, LocalValidatorFactoryBean.class)
|
||||||
|
&& def.getRole() == BeanDefinition.ROLE_INFRASTRUCTURE) {
|
||||||
|
def.setPrimary(!hasPrimarySpringValidator(registry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasPrimarySpringValidator(BeanDefinitionRegistry registry) {
|
||||||
|
String[] validatorBeans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
|
||||||
|
this.beanFactory, Validator.class, false, false);
|
||||||
|
for (String validatorBean : validatorBeans) {
|
||||||
|
BeanDefinition def = registry.getBeanDefinition(validatorBean);
|
||||||
|
if (def != null && def.isPrimary()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -19,15 +19,18 @@ package org.springframework.boot.autoconfigure.validation;
|
|||||||
import javax.validation.Validator;
|
import javax.validation.Validator;
|
||||||
import javax.validation.executable.ExecutableValidator;
|
import javax.validation.executable.ExecutableValidator;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
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.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
|
||||||
|
import org.springframework.boot.validation.MessageInterpolatorFactory;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.context.annotation.Role;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||||
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
|
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,12 +44,20 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess
|
|||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnClass(ExecutableValidator.class)
|
@ConditionalOnClass(ExecutableValidator.class)
|
||||||
@ConditionalOnResource(resources = "classpath:META-INF/services/javax.validation.spi.ValidationProvider")
|
@ConditionalOnResource(resources = "classpath:META-INF/services/javax.validation.spi.ValidationProvider")
|
||||||
@Import({ DefaultValidatorConfiguration.class,
|
@Import(PrimaryDefaultValidatorPostProcessor.class)
|
||||||
Jsr303ValidatorAdapterConfiguration.class })
|
|
||||||
public class ValidationAutoConfiguration {
|
public class ValidationAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@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
|
@ConditionalOnMissingBean
|
||||||
public static MethodValidationPostProcessor methodValidationPostProcessor(
|
public static MethodValidationPostProcessor methodValidationPostProcessor(
|
||||||
Environment environment, Validator validator) {
|
Environment environment, Validator validator) {
|
||||||
|
|||||||
@@ -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.
|
||||||
|
* <p>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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -23,48 +23,30 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
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.ListableBeanFactory;
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.AutoConfigureAfter;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
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.ConditionalOnEnabledResourceChain;
|
||||||
import org.springframework.boot.autoconfigure.web.ResourceProperties;
|
import org.springframework.boot.autoconfigure.web.ResourceProperties;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
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.Bean;
|
||||||
import org.springframework.context.annotation.ConditionContext;
|
|
||||||
import org.springframework.context.annotation.Conditional;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.ConfigurationCondition;
|
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
import org.springframework.core.convert.converter.GenericConverter;
|
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.Formatter;
|
||||||
import org.springframework.format.FormatterRegistry;
|
import org.springframework.format.FormatterRegistry;
|
||||||
import org.springframework.http.CacheControl;
|
import org.springframework.http.CacheControl;
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
import org.springframework.validation.Validator;
|
import org.springframework.validation.Validator;
|
||||||
import org.springframework.web.reactive.config.DelegatingWebFluxConfiguration;
|
import org.springframework.web.reactive.config.DelegatingWebFluxConfiguration;
|
||||||
import org.springframework.web.reactive.config.EnableWebFlux;
|
import org.springframework.web.reactive.config.EnableWebFlux;
|
||||||
@@ -103,7 +85,7 @@ public class WebFluxAutoConfiguration {
|
|||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableConfigurationProperties({ ResourceProperties.class, WebFluxProperties.class })
|
@EnableConfigurationProperties({ ResourceProperties.class, WebFluxProperties.class })
|
||||||
@Import({ EnableWebFluxConfiguration.class, WebFluxValidatorRegistrar.class })
|
@Import({ EnableWebFluxConfiguration.class })
|
||||||
public static class WebFluxConfig implements WebFluxConfigurer {
|
public static class WebFluxConfig implements WebFluxConfigurer {
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(WebFluxConfig.class);
|
private static final Log logger = LogFactory.getLog(WebFluxConfig.class);
|
||||||
@@ -209,29 +191,17 @@ public class WebFluxAutoConfiguration {
|
|||||||
* Configuration equivalent to {@code @EnableWebFlux}.
|
* Configuration equivalent to {@code @EnableWebFlux}.
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public static class EnableWebFluxConfiguration extends DelegatingWebFluxConfiguration
|
public static class EnableWebFluxConfiguration
|
||||||
implements InitializingBean {
|
extends DelegatingWebFluxConfiguration {
|
||||||
|
|
||||||
private final ApplicationContext context;
|
|
||||||
|
|
||||||
public EnableWebFluxConfiguration(ApplicationContext context) {
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
@Bean
|
@Bean
|
||||||
@Override
|
|
||||||
@Conditional(DisableWebFluxValidatorCondition.class)
|
|
||||||
public Validator webFluxValidator() {
|
public Validator webFluxValidator() {
|
||||||
return this.context.getBean("webFluxValidator", Validator.class);
|
if (!ClassUtils.isPresent("javax.validation.Validator",
|
||||||
}
|
getClass().getClassLoader())) {
|
||||||
|
return super.webFluxValidator();
|
||||||
@Override
|
}
|
||||||
public void afterPropertiesSet() throws Exception {
|
return ValidatorAdapter.get(getApplicationContext(), getValidator());
|
||||||
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()");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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:
|
|
||||||
* <ul>
|
|
||||||
* <li>With no validators - Uses standard
|
|
||||||
* {@link WebFluxConfigurationSupport#webFluxValidator()} logic.</li>
|
|
||||||
* <li>With a single validator - Uses an alias.</li>
|
|
||||||
* <li>With multiple validators - Registers a webFluxValidator bean if not already
|
|
||||||
* defined.</li>
|
|
||||||
* </ul>
|
|
||||||
*/
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,18 +30,11 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
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.ListableBeanFactory;
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.AutoConfigureAfter;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
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;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
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.ValidationAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.validation.ValidatorAdapter;
|
||||||
import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain;
|
import org.springframework.boot.autoconfigure.web.ConditionalOnEnabledResourceChain;
|
||||||
import org.springframework.boot.autoconfigure.web.ResourceProperties;
|
import org.springframework.boot.autoconfigure.web.ResourceProperties;
|
||||||
import org.springframework.boot.autoconfigure.web.ResourceProperties.Strategy;
|
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.OrderedHiddenHttpMethodFilter;
|
||||||
import org.springframework.boot.web.servlet.filter.OrderedHttpPutFormContentFilter;
|
import org.springframework.boot.web.servlet.filter.OrderedHttpPutFormContentFilter;
|
||||||
import org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter;
|
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.Bean;
|
||||||
import org.springframework.context.annotation.ConditionContext;
|
|
||||||
import org.springframework.context.annotation.Conditional;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.ConfigurationCondition;
|
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
|
||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
import org.springframework.core.convert.converter.GenericConverter;
|
import org.springframework.core.convert.converter.GenericConverter;
|
||||||
import org.springframework.core.io.Resource;
|
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.Formatter;
|
||||||
import org.springframework.format.FormatterRegistry;
|
import org.springframework.format.FormatterRegistry;
|
||||||
import org.springframework.format.datetime.DateFormatter;
|
import org.springframework.format.datetime.DateFormatter;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.validation.DefaultMessageCodesResolver;
|
import org.springframework.validation.DefaultMessageCodesResolver;
|
||||||
import org.springframework.validation.MessageCodesResolver;
|
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
|
// Defined as a nested config to ensure WebMvcConfigurer is not read when not
|
||||||
// on the classpath
|
// on the classpath
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import({ EnableWebMvcConfiguration.class, MvcValidatorRegistrar.class })
|
@Import(EnableWebMvcConfiguration.class)
|
||||||
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
|
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
|
||||||
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
|
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
|
||||||
|
|
||||||
@@ -380,22 +363,21 @@ public class WebMvcAutoConfiguration {
|
|||||||
* Configuration equivalent to {@code @EnableWebMvc}.
|
* Configuration equivalent to {@code @EnableWebMvc}.
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration
|
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
|
||||||
implements InitializingBean {
|
|
||||||
|
|
||||||
private final WebMvcProperties mvcProperties;
|
private final WebMvcProperties mvcProperties;
|
||||||
|
|
||||||
private final ApplicationContext context;
|
private final ListableBeanFactory beanFactory;
|
||||||
|
|
||||||
private final WebMvcRegistrations mvcRegistrations;
|
private final WebMvcRegistrations mvcRegistrations;
|
||||||
|
|
||||||
public EnableWebMvcConfiguration(
|
public EnableWebMvcConfiguration(
|
||||||
ObjectProvider<WebMvcProperties> mvcPropertiesProvider,
|
ObjectProvider<WebMvcProperties> mvcPropertiesProvider,
|
||||||
ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider,
|
ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider,
|
||||||
ApplicationContext context) {
|
ListableBeanFactory beanFactory) {
|
||||||
this.mvcProperties = mvcPropertiesProvider.getIfAvailable();
|
this.mvcProperties = mvcPropertiesProvider.getIfAvailable();
|
||||||
this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique();
|
this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique();
|
||||||
this.context = context;
|
this.beanFactory = beanFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -426,9 +408,12 @@ public class WebMvcAutoConfiguration {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Override
|
@Override
|
||||||
@Conditional(DisableMvcValidatorCondition.class)
|
|
||||||
public Validator mvcValidator() {
|
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
|
@Override
|
||||||
@@ -443,7 +428,7 @@ public class WebMvcAutoConfiguration {
|
|||||||
@Override
|
@Override
|
||||||
protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
|
protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
|
||||||
try {
|
try {
|
||||||
return this.context.getBean(ConfigurableWebBindingInitializer.class);
|
return this.beanFactory.getBean(ConfigurableWebBindingInitializer.class);
|
||||||
}
|
}
|
||||||
catch (NoSuchBeanDefinitionException ex) {
|
catch (NoSuchBeanDefinitionException ex) {
|
||||||
return super.getConfigurableWebBindingInitializer();
|
return super.getConfigurableWebBindingInitializer();
|
||||||
@@ -492,15 +477,6 @@ public class WebMvcAutoConfiguration {
|
|||||||
return manager;
|
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
|
@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:
|
|
||||||
* <ul>
|
|
||||||
* <li>With no validators - Uses standard
|
|
||||||
* {@link WebMvcConfigurationSupport#mvcValidator()} logic.</li>
|
|
||||||
* <li>With a single validator - Uses an alias.</li>
|
|
||||||
* <li>With multiple validators - Registers a mvcValidator bean if not already
|
|
||||||
* defined.</li>
|
|
||||||
* </ul>
|
|
||||||
*/
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
|
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.DispatcherServletAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
|
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
|
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
|
||||||
@@ -323,9 +322,9 @@ public class SpringBootWebSecurityConfigurationTests {
|
|||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Documented
|
@Documented
|
||||||
@Import({ ServletWebServerFactoryAutoConfiguration.class,
|
@Import({ ServletWebServerFactoryAutoConfiguration.class,
|
||||||
DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class,
|
DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||||
WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
HttpMessageConvertersAutoConfiguration.class, ErrorMvcAutoConfiguration.class,
|
||||||
ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class })
|
PropertyPlaceholderAutoConfiguration.class })
|
||||||
protected @interface MinimalWebConfiguration {
|
protected @interface MinimalWebConfiguration {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -31,6 +31,7 @@ import org.springframework.boot.test.util.EnvironmentTestUtils;
|
|||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Primary;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||||
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
|
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
|
||||||
@@ -43,6 +44,7 @@ import static org.mockito.Mockito.mock;
|
|||||||
* Tests for {@link ValidationAutoConfiguration}.
|
* Tests for {@link ValidationAutoConfiguration}.
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
public class ValidationAutoConfigurationTests {
|
public class ValidationAutoConfigurationTests {
|
||||||
|
|
||||||
@@ -59,94 +61,134 @@ public class ValidationAutoConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validationAutoConfigurationShouldConfigureJsrAndSpringValidator()
|
public void validationAutoConfigurationShouldConfigureDefaultValidator() {
|
||||||
throws Exception {
|
|
||||||
load(Config.class);
|
load(Config.class);
|
||||||
Validator jsrValidator = this.context.getBean(Validator.class);
|
|
||||||
String[] jsrValidatorNames = this.context.getBeanNamesForType(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
|
String[] springValidatorNames = this.context
|
||||||
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
||||||
assertThat(jsrValidator).isInstanceOf(LocalValidatorFactoryBean.class);
|
|
||||||
assertThat(jsrValidator).isEqualTo(springValidator);
|
|
||||||
assertThat(jsrValidatorNames).containsExactly("defaultValidator");
|
assertThat(jsrValidatorNames).containsExactly("defaultValidator");
|
||||||
assertThat(springValidatorNames).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
|
@Test
|
||||||
public void validationAutoConfigurationWhenUserProvidesValidatorShouldBackOff()
|
public void validationAutoConfigurationWhenUserProvidesValidatorShouldBackOff() {
|
||||||
throws Exception {
|
|
||||||
load(UserDefinedValidatorConfig.class);
|
load(UserDefinedValidatorConfig.class);
|
||||||
Validator jsrValidator = this.context.getBean(Validator.class);
|
|
||||||
String[] jsrValidatorNames = this.context.getBeanNamesForType(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
|
String[] springValidatorNames = this.context
|
||||||
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
||||||
assertThat(jsrValidator).isInstanceOf(OptionalValidatorFactoryBean.class);
|
|
||||||
assertThat(jsrValidator).isEqualTo(springValidator);
|
|
||||||
assertThat(jsrValidatorNames).containsExactly("customValidator");
|
assertThat(jsrValidatorNames).containsExactly("customValidator");
|
||||||
assertThat(springValidatorNames).containsExactly("customValidator");
|
assertThat(springValidatorNames).containsExactly("customValidator");
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void validationAutoConfigurationWhenUserProvidesJsrOnlyShouldAdaptIt()
|
|
||||||
throws Exception {
|
|
||||||
load(UserDefinedJsrValidatorConfig.class);
|
|
||||||
Validator jsrValidator = this.context.getBean(Validator.class);
|
|
||||||
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
|
|
||||||
org.springframework.validation.Validator springValidator = this.context
|
org.springframework.validation.Validator springValidator = this.context
|
||||||
.getBean(org.springframework.validation.Validator.class);
|
.getBean(org.springframework.validation.Validator.class);
|
||||||
|
Validator jsrValidator = this.context.getBean(Validator.class);
|
||||||
|
assertThat(jsrValidator).isInstanceOf(OptionalValidatorFactoryBean.class);
|
||||||
|
assertThat(jsrValidator).isEqualTo(springValidator);
|
||||||
|
assertThat(isPrimaryBean("customValidator")).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void validationAutoConfigurationWhenUserProvidesDefaultValidatorShouldNotEnablePrimary() {
|
||||||
|
load(UserDefinedDefaultValidatorConfig.class);
|
||||||
|
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
|
||||||
|
String[] springValidatorNames = this.context
|
||||||
|
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
||||||
|
assertThat(jsrValidatorNames).containsExactly("defaultValidator");
|
||||||
|
assertThat(springValidatorNames).containsExactly("defaultValidator");
|
||||||
|
assertThat(isPrimaryBean("defaultValidator")).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void validationAutoConfigurationWhenUserProvidesJsrValidatorShouldBackOff() {
|
||||||
|
load(UserDefinedJsrValidatorConfig.class);
|
||||||
|
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
|
||||||
String[] springValidatorNames = this.context
|
String[] springValidatorNames = this.context
|
||||||
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
||||||
assertThat(jsrValidator).isNotEqualTo(springValidator);
|
|
||||||
assertThat(springValidator).isInstanceOf(DelegatingValidator.class);
|
|
||||||
assertThat(jsrValidatorNames).containsExactly("customValidator");
|
assertThat(jsrValidatorNames).containsExactly("customValidator");
|
||||||
assertThat(springValidatorNames).containsExactly("jsr303ValidatorAdapter");
|
assertThat(springValidatorNames).isEmpty();
|
||||||
|
assertThat(isPrimaryBean("customValidator")).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validationAutoConfigurationShouldBeEnabled() {
|
public void validationAutoConfigurationWhenUserProvidesSpringValidatorShouldCreateJsrValidator() {
|
||||||
load(ClassWithConstraint.class);
|
load(UserDefinedSpringValidatorConfig.class);
|
||||||
|
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
|
||||||
|
String[] springValidatorNames = this.context
|
||||||
|
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
||||||
|
assertThat(jsrValidatorNames).containsExactly("defaultValidator");
|
||||||
|
assertThat(springValidatorNames).containsExactly(
|
||||||
|
"customValidator", "anotherCustomValidator", "defaultValidator");
|
||||||
|
Validator jsrValidator = this.context.getBean(Validator.class);
|
||||||
|
org.springframework.validation.Validator springValidator = this.context
|
||||||
|
.getBean(org.springframework.validation.Validator.class);
|
||||||
|
assertThat(jsrValidator).isInstanceOf(LocalValidatorFactoryBean.class);
|
||||||
|
assertThat(jsrValidator).isEqualTo(springValidator);
|
||||||
|
assertThat(isPrimaryBean("defaultValidator")).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void validationAutoConfigurationWhenUserProvidesPrimarySpringValidatorShouldRemovePrimaryFlag() {
|
||||||
|
load(UserDefinedPrimarySpringValidatorConfig.class);
|
||||||
|
String[] jsrValidatorNames = this.context.getBeanNamesForType(Validator.class);
|
||||||
|
String[] springValidatorNames = this.context
|
||||||
|
.getBeanNamesForType(org.springframework.validation.Validator.class);
|
||||||
|
assertThat(jsrValidatorNames).containsExactly("defaultValidator");
|
||||||
|
assertThat(springValidatorNames).containsExactly(
|
||||||
|
"customValidator", "anotherCustomValidator", "defaultValidator");
|
||||||
|
Validator jsrValidator = this.context.getBean(Validator.class);
|
||||||
|
org.springframework.validation.Validator springValidator = this.context
|
||||||
|
.getBean(org.springframework.validation.Validator.class);
|
||||||
|
assertThat(jsrValidator).isInstanceOf(LocalValidatorFactoryBean.class);
|
||||||
|
assertThat(springValidator).isEqualTo(
|
||||||
|
this.context.getBean("anotherCustomValidator"));
|
||||||
|
assertThat(isPrimaryBean("defaultValidator")).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void validationIsEnabled() {
|
||||||
|
load(SampleService.class);
|
||||||
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
||||||
ClassWithConstraint service = this.context.getBean(ClassWithConstraint.class);
|
SampleService service = this.context.getBean(SampleService.class);
|
||||||
service.call("Valid");
|
service.doSomething("Valid");
|
||||||
this.thrown.expect(ConstraintViolationException.class);
|
this.thrown.expect(ConstraintViolationException.class);
|
||||||
service.call("KO");
|
service.doSomething("KO");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validationAutoConfigurationShouldUseCglibProxy() {
|
public void validationUsesCglibProxy() {
|
||||||
load(ImplementationOfInterfaceWithConstraint.class);
|
load(DefaultAnotherSampleService.class);
|
||||||
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
||||||
ImplementationOfInterfaceWithConstraint service = this.context
|
DefaultAnotherSampleService service = this.context
|
||||||
.getBean(ImplementationOfInterfaceWithConstraint.class);
|
.getBean(DefaultAnotherSampleService.class);
|
||||||
service.call(42);
|
service.doSomething(42);
|
||||||
this.thrown.expect(ConstraintViolationException.class);
|
this.thrown.expect(ConstraintViolationException.class);
|
||||||
service.call(2);
|
service.doSomething(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validationAutoConfigurationWhenProxyTargetClassIsFalseShouldUseJdkProxy() {
|
public void validationCanBeConfiguredToUseJdkProxy() {
|
||||||
load(AnotherSampleServiceConfiguration.class,
|
load(AnotherSampleServiceConfiguration.class,
|
||||||
"spring.aop.proxy-target-class=false");
|
"spring.aop.proxy-target-class=false");
|
||||||
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
||||||
assertThat(this.context
|
assertThat(this.context.getBeansOfType(DefaultAnotherSampleService.class))
|
||||||
.getBeansOfType(ImplementationOfInterfaceWithConstraint.class)).isEmpty();
|
.isEmpty();
|
||||||
InterfaceWithConstraint service = this.context
|
AnotherSampleService service = this.context.getBean(AnotherSampleService.class);
|
||||||
.getBean(InterfaceWithConstraint.class);
|
service.doSomething(42);
|
||||||
service.call(42);
|
|
||||||
this.thrown.expect(ConstraintViolationException.class);
|
this.thrown.expect(ConstraintViolationException.class);
|
||||||
service.call(2);
|
service.doSomething(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validationAutoConfigurationWhenUserDefinesMethodValidationPostProcessorShouldBackOff() {
|
public void userDefinedMethodValidationPostProcessorTakesPrecedence() {
|
||||||
load(UserDefinedMethodValidationConfig.class);
|
load(SampleConfiguration.class);
|
||||||
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
assertThat(this.context.getBeansOfType(Validator.class)).hasSize(1);
|
||||||
Object userMethodValidationPostProcessor = this.context
|
Object userMethodValidationPostProcessor = this.context
|
||||||
.getBean("customMethodValidationPostProcessor");
|
.getBean("testMethodValidationPostProcessor");
|
||||||
assertThat(this.context.getBean(MethodValidationPostProcessor.class))
|
assertThat(this.context.getBean(MethodValidationPostProcessor.class))
|
||||||
.isSameAs(userMethodValidationPostProcessor);
|
.isSameAs(userMethodValidationPostProcessor);
|
||||||
assertThat(this.context.getBeansOfType(MethodValidationPostProcessor.class))
|
assertThat(this.context.getBeansOfType(MethodValidationPostProcessor.class))
|
||||||
@@ -156,7 +198,11 @@ public class ValidationAutoConfigurationTests {
|
|||||||
.getPropertyValue("validator"));
|
.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();
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||||
EnvironmentTestUtils.addEnvironment(ctx, environment);
|
EnvironmentTestUtils.addEnvironment(ctx, environment);
|
||||||
if (config != null) {
|
if (config != null) {
|
||||||
@@ -182,6 +228,16 @@ public class ValidationAutoConfigurationTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
static class UserDefinedDefaultValidatorConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public OptionalValidatorFactoryBean defaultValidator() {
|
||||||
|
return new OptionalValidatorFactoryBean();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class UserDefinedJsrValidatorConfig {
|
static class UserDefinedJsrValidatorConfig {
|
||||||
|
|
||||||
@@ -193,47 +249,77 @@ public class ValidationAutoConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class UserDefinedMethodValidationConfig {
|
static class UserDefinedSpringValidatorConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public MethodValidationPostProcessor customMethodValidationPostProcessor() {
|
public org.springframework.validation.Validator customValidator() {
|
||||||
return new MethodValidationPostProcessor();
|
return mock(org.springframework.validation.Validator.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public org.springframework.validation.Validator anotherCustomValidator() {
|
||||||
|
return mock(org.springframework.validation.Validator.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
static class UserDefinedPrimarySpringValidatorConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public org.springframework.validation.Validator customValidator() {
|
||||||
|
return mock(org.springframework.validation.Validator.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Primary
|
||||||
|
public org.springframework.validation.Validator anotherCustomValidator() {
|
||||||
|
return mock(org.springframework.validation.Validator.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Validated
|
||||||
|
static class SampleService {
|
||||||
|
|
||||||
|
public void doSomething(@Size(min = 3, max = 10) String name) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AnotherSampleService {
|
||||||
|
|
||||||
|
void doSomething(@Min(42) Integer counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Validated
|
||||||
|
static class DefaultAnotherSampleService implements AnotherSampleService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doSomething(Integer counter) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class AnotherSampleServiceConfiguration {
|
static class AnotherSampleServiceConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public InterfaceWithConstraint implementationOfInterfaceWithConstraint() {
|
public AnotherSampleService anotherSampleService() {
|
||||||
return new ImplementationOfInterfaceWithConstraint();
|
return new DefaultAnotherSampleService();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Validated
|
@Configuration
|
||||||
static class ClassWithConstraint {
|
static class SampleConfiguration {
|
||||||
|
|
||||||
public void call(@Size(min = 3, max = 10) String name) {
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public MethodValidationPostProcessor testMethodValidationPostProcessor() {
|
||||||
|
return new MethodValidationPostProcessor();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface InterfaceWithConstraint {
|
|
||||||
|
|
||||||
void call(@Min(42) Integer counter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Validated
|
|
||||||
static class ImplementationOfInterfaceWithConstraint
|
|
||||||
implements InterfaceWithConstraint {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void call(Integer counter) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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<String, Object>(),
|
||||||
|
"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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,13 +21,15 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import javax.validation.ValidatorFactory;
|
||||||
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.ExpectedException;
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanCreationException;
|
import org.springframework.beans.DirectFieldAccessor;
|
||||||
import org.springframework.boot.autoconfigure.validation.DelegatingValidator;
|
|
||||||
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
|
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.autoconfigure.web.servlet.WebMvcAutoConfigurationTests.Config;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||||
@@ -172,134 +174,107 @@ public class WebFluxAutoConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validatorWhenSuppliedByConfigurerShouldThrowException() throws Exception {
|
public void validatorWhenNoValidatorShouldUseDefault() {
|
||||||
this.thrown.expect(BeanCreationException.class);
|
load(null, new Class<?>[] { ValidationAutoConfiguration.class });
|
||||||
this.thrown.expectMessage("unexpected validator configuration");
|
assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
|
||||||
load(ValidatorWebFluxConfigurer.class);
|
assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
|
||||||
}
|
.isEmpty();
|
||||||
|
|
||||||
@Test
|
|
||||||
public void validatorWhenAutoConfiguredShouldUseAlias() throws Exception {
|
|
||||||
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);
|
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||||
assertThat(webFluxValidator).isSameAs(defaultValidator);
|
|
||||||
assertThat(springValidatorBeans).containsExactly("defaultValidator");
|
|
||||||
assertThat(jsrValidatorBeans).containsExactly("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);
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
@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);
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
@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);
|
|
||||||
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(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(springValidatorBeans).containsExactly("webFluxValidator");
|
||||||
assertThat(jsrValidatorBeans).isEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validatorWhenMultipleValidatorsAndNoWebFluxValidatorShouldAddWebFlux()
|
public void validatorWhenNoCustomizationShouldUseAutoConfigured() {
|
||||||
throws Exception {
|
load();
|
||||||
load(MultipleValidatorsAndNoWebFluxValidator.class);
|
|
||||||
Object customValidator1 = this.context.getBean("customValidator1");
|
|
||||||
Object customValidator2 = this.context.getBean("customValidator2");
|
|
||||||
Object webFluxValidator = this.context.getBean("webFluxValidator");
|
|
||||||
String[] jsrValidatorBeans = this.context
|
String[] jsrValidatorBeans = this.context
|
||||||
.getBeanNamesForType(javax.validation.Validator.class);
|
.getBeanNamesForType(javax.validation.Validator.class);
|
||||||
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||||
assertThat(webFluxValidator).isNotSameAs(customValidator1)
|
assertThat(jsrValidatorBeans).containsExactly("defaultValidator");
|
||||||
.isNotSameAs(customValidator2);
|
assertThat(springValidatorBeans).containsExactly("defaultValidator", "webFluxValidator");
|
||||||
assertThat(springValidatorBeans).containsExactly("customValidator1",
|
Validator validator = this.context.getBean("webFluxValidator", Validator.class);
|
||||||
"customValidator2", "webFluxValidator");
|
assertThat(validator).isInstanceOf(ValidatorAdapter.class);
|
||||||
assertThat(jsrValidatorBeans).isEmpty();
|
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
|
@Test
|
||||||
public void validatorWhenMultipleValidatorsAndWebFluxValidatorShouldUseWebFlux()
|
public void validatorWithConfigurerShouldUseSpringValidator() {
|
||||||
throws Exception {
|
load(ValidatorWebFluxConfigurer.class,
|
||||||
load(MultipleValidatorsAndWebFluxValidator.class);
|
new Class<?>[] { ValidationAutoConfiguration.class });
|
||||||
Object customValidator = this.context.getBean("customValidator");
|
assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
|
||||||
Object webFluxValidator = this.context.getBean("webFluxValidator");
|
assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
|
||||||
|
.isEmpty();
|
||||||
|
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||||
|
assertThat(springValidatorBeans).containsExactly("webFluxValidator");
|
||||||
|
assertThat(this.context.getBean("webFluxValidator"))
|
||||||
|
.isSameAs(this.context.getBean(ValidatorWebFluxConfigurer.class).validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
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(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 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(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(this.context.getBean("defaultValidator"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void validatorWithCustomSpringValidatorIgnored() {
|
||||||
|
load(CustomSpringValidator.class);
|
||||||
String[] jsrValidatorBeans = this.context
|
String[] jsrValidatorBeans = this.context
|
||||||
.getBeanNamesForType(javax.validation.Validator.class);
|
.getBeanNamesForType(javax.validation.Validator.class);
|
||||||
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||||
assertThat(webFluxValidator).isNotSameAs(customValidator);
|
assertThat(jsrValidatorBeans).containsExactly("defaultValidator");
|
||||||
assertThat(springValidatorBeans).containsExactly("customValidator",
|
assertThat(springValidatorBeans).containsExactly(
|
||||||
"webFluxValidator");
|
"customValidator", "defaultValidator", "webFluxValidator");
|
||||||
assertThat(jsrValidatorBeans).isEmpty();
|
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 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(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) {
|
private void load(String... environment) {
|
||||||
@@ -324,7 +299,6 @@ public class WebFluxAutoConfigurationTests {
|
|||||||
}
|
}
|
||||||
this.context.register(configClasses.toArray(new Class<?>[configClasses.size()]));
|
this.context.register(configClasses.toArray(new Class<?>[configClasses.size()]));
|
||||||
this.context.refresh();
|
this.context.refresh();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@@ -381,25 +355,29 @@ public class WebFluxAutoConfigurationTests {
|
|||||||
@Configuration
|
@Configuration
|
||||||
protected static class ValidatorWebFluxConfigurer implements WebFluxConfigurer {
|
protected static class ValidatorWebFluxConfigurer implements WebFluxConfigurer {
|
||||||
|
|
||||||
|
private final Validator validator = mock(Validator.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Validator> getValidator() {
|
public Optional<Validator> getValidator() {
|
||||||
return Optional.of(mock(Validator.class));
|
return Optional.of(this.validator);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class UserDefinedSpringOnlyValidator {
|
protected static class ValidatorJsr303WebFluxConfigurer implements WebFluxConfigurer {
|
||||||
|
|
||||||
@Bean
|
private final LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||||
public Validator customValidator() {
|
|
||||||
return mock(Validator.class);
|
@Override
|
||||||
|
public Optional<Validator> getValidator() {
|
||||||
|
return Optional.of(this.validator);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class UserDefinedJsr303Validator {
|
static class CustomJsr303Validator {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public javax.validation.Validator customValidator() {
|
public javax.validation.Validator customValidator() {
|
||||||
@@ -409,58 +387,13 @@ public class WebFluxAutoConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class UserDefinedSingleJsr303AndSpringValidator {
|
static class CustomSpringValidator {
|
||||||
|
|
||||||
@Bean
|
|
||||||
public LocalValidatorFactoryBean customValidator() {
|
|
||||||
return new LocalValidatorFactoryBean();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
static class UserDefinedJsr303AndSpringValidator {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public javax.validation.Validator customJsrValidator() {
|
|
||||||
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 {
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Validator customValidator() {
|
public Validator customValidator() {
|
||||||
return mock(Validator.class);
|
return mock(Validator.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
public Validator webFluxValidator() {
|
|
||||||
return mock(Validator.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.validation.ValidatorFactory;
|
||||||
|
|
||||||
import org.assertj.core.api.Condition;
|
import org.assertj.core.api.Condition;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
@@ -36,13 +37,12 @@ import org.junit.Test;
|
|||||||
import org.junit.rules.ExpectedException;
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
import org.springframework.beans.DirectFieldAccessor;
|
import org.springframework.beans.DirectFieldAccessor;
|
||||||
import org.springframework.beans.factory.BeanCreationException;
|
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||||
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
|
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.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.WebMvcAutoConfigurationAdapter;
|
||||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.WelcomePageHandlerMapping;
|
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.WelcomePageHandlerMapping;
|
||||||
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
import org.springframework.boot.test.util.EnvironmentTestUtils;
|
||||||
@@ -659,134 +659,105 @@ public class WebMvcAutoConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validatorWhenSuppliedByConfigurerShouldThrowException() throws Exception {
|
public void validatorWhenNoValidatorShouldUseDefault() {
|
||||||
this.thrown.expect(BeanCreationException.class);
|
load(null, new Class<?>[] { ValidationAutoConfiguration.class });
|
||||||
this.thrown.expectMessage("unexpected validator configuration");
|
assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
|
||||||
load(ValidatorWebMvcConfigurer.class);
|
assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
|
||||||
}
|
.isEmpty();
|
||||||
|
|
||||||
@Test
|
|
||||||
public void validatorWhenAutoConfiguredShouldUseAlias() throws Exception {
|
|
||||||
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);
|
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||||
assertThat(mvcValidator).isSameAs(defaultValidator);
|
|
||||||
assertThat(springValidatorBeans).containsExactly("defaultValidator");
|
|
||||||
assertThat(jsrValidatorBeans).containsExactly("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);
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
@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);
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
@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);
|
|
||||||
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(this.context.getBean(Validator.class))
|
|
||||||
.isEqualTo(customSpringValidator);
|
|
||||||
assertThat(springValidatorBeans).containsExactly("customSpringValidator");
|
|
||||||
assertThat(jsrValidatorBeans).containsExactly("customJsrValidator");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void validatorWhenExcludingValidatorAutoConfigurationShouldUseMvc()
|
|
||||||
throws Exception {
|
|
||||||
load(null, new Class[] { ValidationAutoConfiguration.class });
|
|
||||||
Object mvcValidator = this.context.getBean("mvcValidator");
|
|
||||||
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(springValidatorBeans).containsExactly("mvcValidator");
|
||||||
assertThat(jsrValidatorBeans).isEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void validatorWhenMultipleValidatorsAndNoMvcValidatorShouldAddMvc()
|
public void validatorWhenNoCustomizationShouldUseAutoConfigured() {
|
||||||
throws Exception {
|
load();
|
||||||
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
|
String[] jsrValidatorBeans = this.context
|
||||||
.getBeanNamesForType(javax.validation.Validator.class);
|
.getBeanNamesForType(javax.validation.Validator.class);
|
||||||
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||||
assertThat(mvcValidator).isNotSameAs(customValidator1)
|
assertThat(jsrValidatorBeans).containsExactly("defaultValidator");
|
||||||
.isNotSameAs(customValidator2);
|
assertThat(springValidatorBeans).containsExactly("defaultValidator", "mvcValidator");
|
||||||
assertThat(springValidatorBeans).containsExactly("customValidator1",
|
Validator validator = this.context.getBean("mvcValidator", Validator.class);
|
||||||
"customValidator2", "mvcValidator");
|
assertThat(validator).isInstanceOf(ValidatorAdapter.class);
|
||||||
assertThat(jsrValidatorBeans).isEmpty();
|
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
|
@Test
|
||||||
public void validatorWhenMultipleValidatorsAndMvcValidatorShouldUseMvc()
|
public void validatorWithConfigurerShouldUseSpringValidator() {
|
||||||
throws Exception {
|
load(MvcValidator.class, new Class<?>[] { ValidationAutoConfiguration.class });
|
||||||
load(MultipleValidatorsAndMvcValidator.class);
|
assertThat(this.context.getBeansOfType(ValidatorFactory.class)).isEmpty();
|
||||||
Object customValidator = this.context.getBean("customValidator");
|
assertThat(this.context.getBeansOfType(javax.validation.Validator.class))
|
||||||
Object mvcValidator = this.context.getBean("mvcValidator");
|
.isEmpty();
|
||||||
|
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||||
|
assertThat(springValidatorBeans).containsExactly("mvcValidator");
|
||||||
|
assertThat(this.context.getBean("mvcValidator"))
|
||||||
|
.isSameAs(this.context.getBean(MvcValidator.class).validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void 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(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 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(springValidatorBeans).containsExactly("defaultValidator", "mvcValidator");
|
||||||
|
assertThat(this.context.getBean("mvcValidator"))
|
||||||
|
.isSameAs(this.context.getBean(MvcValidator.class).validator);
|
||||||
|
// Primary Spring validator is the auto-configured one as the MVC one has been
|
||||||
|
// customized via a WebMvcConfigurer
|
||||||
|
assertThat(this.context.getBean(Validator.class))
|
||||||
|
.isEqualTo(this.context.getBean("defaultValidator"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void validatorWithCustomSpringValidatorIgnored() {
|
||||||
|
load(CustomSpringValidator.class);
|
||||||
String[] jsrValidatorBeans = this.context
|
String[] jsrValidatorBeans = this.context
|
||||||
.getBeanNamesForType(javax.validation.Validator.class);
|
.getBeanNamesForType(javax.validation.Validator.class);
|
||||||
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
String[] springValidatorBeans = this.context.getBeanNamesForType(Validator.class);
|
||||||
assertThat(mvcValidator).isNotSameAs(customValidator);
|
assertThat(jsrValidatorBeans).containsExactly("defaultValidator");
|
||||||
assertThat(springValidatorBeans).containsExactly("customValidator",
|
assertThat(springValidatorBeans).containsExactly(
|
||||||
"mvcValidator");
|
"customSpringValidator", "defaultValidator", "mvcValidator");
|
||||||
assertThat(jsrValidatorBeans).isEmpty();
|
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 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(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) {
|
private void load(Class<?> config, String... environment) {
|
||||||
@@ -976,52 +947,41 @@ public class WebMvcAutoConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
protected static class ValidatorWebMvcConfigurer implements WebMvcConfigurer {
|
protected static class MvcValidator implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
private final Validator validator = mock(Validator.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Validator getValidator() {
|
public Validator getValidator() {
|
||||||
return mock(Validator.class);
|
return this.validator;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class UserDefinedSpringOnlyValidator {
|
protected static class MvcJsr303Validator implements WebMvcConfigurer {
|
||||||
|
|
||||||
@Bean
|
private final LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||||
public Validator customValidator() {
|
|
||||||
return mock(Validator.class);
|
@Override
|
||||||
|
public Validator getValidator() {
|
||||||
|
return this.validator;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class UserDefinedJsr303Validator {
|
static class CustomJsr303Validator {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public javax.validation.Validator customValidator() {
|
public javax.validation.Validator customJsr303Validator() {
|
||||||
return mock(javax.validation.Validator.class);
|
return mock(javax.validation.Validator.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class UserDefinedSingleJsr303AndSpringValidator {
|
static class CustomSpringValidator {
|
||||||
|
|
||||||
@Bean
|
|
||||||
public LocalValidatorFactoryBean customValidator() {
|
|
||||||
return new LocalValidatorFactoryBean();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
static class UserDefinedJsr303AndSpringValidator {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public javax.validation.Validator customJsrValidator() {
|
|
||||||
return mock(javax.validation.Validator.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Validator customSpringValidator() {
|
public Validator customSpringValidator() {
|
||||||
@@ -1030,34 +990,4 @@ public class WebMvcAutoConfigurationTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
|
||||||
static class MultipleValidatorsAndNoMvcValidator {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public Validator customValidator1() {
|
|
||||||
return mock(Validator.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public Validator customValidator2() {
|
|
||||||
return mock(Validator.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
static class MultipleValidatorsAndMvcValidator {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public Validator customValidator() {
|
|
||||||
return mock(Validator.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public Validator mvcValidator() {
|
|
||||||
return mock(Validator.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import org.junit.rules.ExpectedException;
|
|||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
|
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.DispatcherServletAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
|
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
|
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
|
||||||
@@ -130,9 +129,9 @@ public class BasicErrorControllerDirectMockMvcTests {
|
|||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Documented
|
@Documented
|
||||||
@Import({ ServletWebServerFactoryAutoConfiguration.class,
|
@Import({ ServletWebServerFactoryAutoConfiguration.class,
|
||||||
DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class,
|
DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||||
WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
HttpMessageConvertersAutoConfiguration.class, ErrorMvcAutoConfiguration.class,
|
||||||
ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class })
|
PropertyPlaceholderAutoConfiguration.class })
|
||||||
protected @interface MinimalWebConfiguration {
|
protected @interface MinimalWebConfiguration {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
|
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.DispatcherServletAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
|
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
|
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
|
||||||
@@ -132,9 +131,9 @@ public class BasicErrorControllerMockMvcTests {
|
|||||||
@Documented
|
@Documented
|
||||||
@Import({ ServletWebServerFactoryAutoConfiguration.EmbeddedTomcat.class,
|
@Import({ ServletWebServerFactoryAutoConfiguration.EmbeddedTomcat.class,
|
||||||
ServletWebServerFactoryAutoConfiguration.class,
|
ServletWebServerFactoryAutoConfiguration.class,
|
||||||
DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class,
|
DispatcherServletAutoConfiguration.class, WebMvcAutoConfiguration.class,
|
||||||
WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
|
HttpMessageConvertersAutoConfiguration.class, ErrorMvcAutoConfiguration.class,
|
||||||
ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class })
|
PropertyPlaceholderAutoConfiguration.class })
|
||||||
private @interface MinimalWebConfiguration {
|
private @interface MinimalWebConfiguration {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user