Auto-configure validation constraints on bean methods

This commit auto-configures `MethodValidationPostProcessor` if necessary
when a JSR-303 validator implementation is detected on the classpath.

Closes gh-6228
This commit is contained in:
Stephane Nicoll 2016-11-24 11:02:56 +01:00
parent 7e25c0dcdd
commit 22208f6a9e
4 changed files with 192 additions and 0 deletions

View File

@ -0,0 +1,45 @@
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.validation;
import javax.validation.Validator;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnResource;
import org.springframework.context.annotation.Bean;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
/**
* {@link EnableAutoConfiguration Auto-configuration} to configure the validation
* infrastructure.
*
* @author Stephane Nicoll
* @since 1.5.0
*/
@ConditionalOnClass({ Validator.class })
public class ValidationAutoConfiguration {
@Bean
@ConditionalOnResource(resources = "META-INF/services/javax.validation.spi.ValidationProvider")
@ConditionalOnMissingBean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}

View File

@ -0,0 +1,20 @@
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Auto-configuration for (JSR-303) Validation.
*/
package org.springframework.boot.autoconfigure.validation;

View File

@ -0,0 +1,99 @@
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.validation;
import javax.validation.ConstraintViolationException;
import javax.validation.constraints.Size;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.annotation.Validated;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link ValidationAutoConfiguration}.
*
* @author Stephane Nicoll
*/
public class ValidationAutoConfigurationTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
private AnnotationConfigApplicationContext context;
@After
public void close() {
if (this.context != null) {
this.context.close();
}
}
@Test
public void validationIsEnabled() {
load(SampleService.class);
SampleService service = this.context.getBean(SampleService.class);
service.doSomething("Valid");
this.thrown.expect(ConstraintViolationException.class);
service.doSomething("KO");
}
@Test
public void userDefinedMethodValidationPostProcessorTakesPrecedence() {
load(SampleConfiguration.class);
assertThat(this.context.getBean(MethodValidationPostProcessor.class))
.isSameAs(this.context.getBean("testMethodValidationPostProcessor"));
assertThat(this.context.getBeansOfType(MethodValidationPostProcessor.class)).hasSize(1);
}
public void load(Class<?> config) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
if (config != null) {
applicationContext.register(config);
}
applicationContext.register(ValidationAutoConfiguration.class);
applicationContext.refresh();
this.context = applicationContext;
}
@Validated
static class SampleService {
public void doSomething(@Size(min = 3, max = 10) String name) {
}
}
@Configuration
static class SampleConfiguration {
@Bean
public MethodValidationPostProcessor testMethodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
}

View File

@ -4616,6 +4616,34 @@ Lastly, the most extreme (and rarely used) option is to create your own
[[boot-features-validation]]
== Validation
The method validation feature supported by Bean Validation 1.1 is automatically enabled
as long as a JSR-303 implementation (e.g. Hibernate validator) is on the classpath. This
allows bean methods to be annotated with `javax.validation` constraints on their
parameters and/or on their return value. Target classes with such annotated methods need
to be annotated with the `@Validated` annotation at the type level for their methods to
be searched for inline constraint annotations.
For instance, the following service triggers the validation of the first argument, making
sure its size is between 8 and 10
[source,java,indent=0]
----
@Service
@Validated
public class MyBean {
public Archive findByCodeAndAuthor(@Size(min = 8, max = 10) String code,
Author author) {
...
}
}
----
[[boot-features-email]]
== Sending email
The Spring Framework provides an easy abstraction for sending email using the