mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-05 00:56:58 +08:00
Align cascading of config prop validation with bean validation spec
Closes gh-40345
This commit is contained in:
parent
d9e9a46189
commit
7701201bc3
|
@ -1178,7 +1178,7 @@ include-code::MyProperties[]
|
|||
|
||||
TIP: You can also trigger validation by annotating the `@Bean` method that creates the configuration properties with `@Validated`.
|
||||
|
||||
To ensure that validation is always triggered for nested properties, even when no properties are found, the associated field must be annotated with `@Valid`.
|
||||
To cascade validation to nested properties the associated field must be annotated with `@Valid`.
|
||||
The following example builds on the preceding `MyProperties` example:
|
||||
|
||||
include-code::nested/MyProperties[]
|
||||
|
|
|
@ -76,8 +76,6 @@ class ConfigurationPropertiesBinder {
|
|||
|
||||
private final boolean jsr303Present;
|
||||
|
||||
private volatile Validator jsr303Validator;
|
||||
|
||||
private volatile Binder binder;
|
||||
|
||||
ConfigurationPropertiesBinder(ApplicationContext applicationContext) {
|
||||
|
@ -141,7 +139,7 @@ class ConfigurationPropertiesBinder {
|
|||
validators.add(this.configurationPropertiesValidator);
|
||||
}
|
||||
if (this.jsr303Present && target.getAnnotation(Validated.class) != null) {
|
||||
validators.add(getJsr303Validator());
|
||||
validators.add(getJsr303Validator(target.getType().resolve()));
|
||||
}
|
||||
Validator selfValidator = getSelfValidator(target);
|
||||
if (selfValidator != null) {
|
||||
|
@ -162,11 +160,8 @@ class ConfigurationPropertiesBinder {
|
|||
return null;
|
||||
}
|
||||
|
||||
private Validator getJsr303Validator() {
|
||||
if (this.jsr303Validator == null) {
|
||||
this.jsr303Validator = new ConfigurationPropertiesJsr303Validator(this.applicationContext);
|
||||
}
|
||||
return this.jsr303Validator;
|
||||
private Validator getJsr303Validator(Class<?> type) {
|
||||
return new ConfigurationPropertiesJsr303Validator(this.applicationContext, type);
|
||||
}
|
||||
|
||||
private List<ConfigurationPropertiesBindHandlerAdvisor> getBindHandlerAdvisors() {
|
||||
|
|
|
@ -37,13 +37,16 @@ final class ConfigurationPropertiesJsr303Validator implements Validator {
|
|||
|
||||
private final Delegate delegate;
|
||||
|
||||
ConfigurationPropertiesJsr303Validator(ApplicationContext applicationContext) {
|
||||
private final Class<?> validatedType;
|
||||
|
||||
ConfigurationPropertiesJsr303Validator(ApplicationContext applicationContext, Class<?> validatedType) {
|
||||
this.delegate = new Delegate(applicationContext);
|
||||
this.validatedType = validatedType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> type) {
|
||||
return this.delegate.supports(type);
|
||||
return this.validatedType.equals(type) && this.delegate.supports(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -106,6 +106,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
import static org.assertj.core.api.Assertions.assertThatException;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.assertj.core.api.Assertions.assertThatNoException;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
|
@ -525,10 +526,9 @@ class ConfigurationPropertiesTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void loadWhenJsr303ConstraintDoesNotMatchOnNestedThatIsNotDirectlyAnnotatedShouldFail() {
|
||||
assertThatExceptionOfType(ConfigurationPropertiesBindException.class)
|
||||
.isThrownBy(() -> load(ValidatedNestedJsr303Properties.class, "properties.description="))
|
||||
.withCauseInstanceOf(BindException.class);
|
||||
void loadWhenJsr303ConstraintDoesNotMatchOnNestedThatIsNotAnnotatedWithValidShouldNotFail() {
|
||||
assertThatNoException()
|
||||
.isThrownBy(() -> load(ValidatedNestedJsr303Properties.class, "properties.description="));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1837,7 +1837,7 @@ class ConfigurationPropertiesTests {
|
|||
@Validated
|
||||
static class ValidatedNestedJsr303Properties {
|
||||
|
||||
private Jsr303Properties properties;
|
||||
private final Jsr303Properties properties = new Jsr303Properties();
|
||||
|
||||
Jsr303Properties getProperties() {
|
||||
return this.properties;
|
||||
|
@ -1851,9 +1851,9 @@ class ConfigurationPropertiesTests {
|
|||
static class ValidatedValidNestedJsr303Properties {
|
||||
|
||||
@Valid
|
||||
private final List<Jsr303Properties> properties = Collections.singletonList(new Jsr303Properties());
|
||||
private final Jsr303Properties properties = new Jsr303Properties();
|
||||
|
||||
List<Jsr303Properties> getProperties() {
|
||||
Jsr303Properties getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user