Configuration properties validation is propagated to non-@Valid fields
When a JSR 303 implementation is on the classpath, Spring Boot validates all Configuration Properties classes that are annotated with @Validated (see ConfigurationPropertiesBinder::getValidators). But the validation applies to all nested objects, even if they're not annotated with @Valid. This doesn't comply with the JSR 303 spec (see the notion of traversable properties) and can lead to some surprising results. For example, the bean below will fail validation given a single property props.nested.myprop1=value, even though the field private Nested nested isn't annotated with @Valid. Likewise, nested collections and maps will fail validation if they contain objects that are themselves annotated with jsr 303 annotations (ex: @NotEmpty), even if validation isn't cascaded with an @Valid. See this reproducer.
@Data
@Validated
@ConfigurationProperties(prefix = "props")
static class ConfigPropsClass {
private Nested nested;
@Data
static class Nested {
String myprop1;
@NotEmpty String myprop2;
}
}
The documentation is also somewhat confusing for this. It states:
To ensure that validation is always triggered for nested properties, even when no properties are found, the associated field must be annotated with @Valid.
But nested objects will not be validated if there are no properties to bind. For example, adding @Valid to the private Nested nested field above will not result in a failure if there is no props.nested.myprop1 property.
I can think of two solutions:
- Propagate validation to
@Validfields only. - Modify the documentation to explicitly say that all nested objects will be validated if the configuration properties class is
@Validated.
I personally prefer option 1, because it corresponds to behaviour that is expected from a JSR 303 validator.