-
Notifications
You must be signed in to change notification settings - Fork 41.6k
Description
Current documentation for @ConfigurationProperties validation kind of implies that nested property validation can be done correctly even without @Valid on nested property fields:
Although nested properties will also be validated when bound, it’s good practice to also annotate the associated field as
@Valid.
And validation does work if I have no @Valid on a nested property field foo.nested1.nested2 but start the app with an invalid value (say foo.nested1.nested2.text=abc):
@Getter
@Setter
@Validated
@Component
@ConfigurationProperties(prefix = "foo")
public class FooProperties {
@NotNull
@Valid
private Nested1 nested1 = new Nested1();
@Getter
@Setter
public static class Nested1 {
@NotNull
private Nested2 nested2 = new Nested2();
@Getter
@Setter
public static class Nested2 {
@NotBlank
@Size(max = 2)
private String text; // "abc" is longer than 2, so we get a nice error
}
}
}However when we omit foo.nested1.nested2.text=abc from application.properties altogether, everything works fine until something tries to use the text value in runtime.
This behavior (breaking on invalid values and ignoring missing values) seems to be due to the way Spring Boot does configuration property binding (please correct me if I'm wrong here), but is not consistent with javax.validation.Validator behavior:
FooProperties foo = new FooProperties();
foo.getNested1().getNested2().setText("abc");
int size = Validation.buildDefaultValidatorFactory().getValidator().validate(foo).size();
System.out.println(size); // prints 0Hibernate Validator spec on object graph validation specifically mentions that @Valid is mandatory for nested properties:
The validation of object graphs is recursive, i.e. if a reference marked for cascaded validation points to an object which itself has properties annotated with
@Valid, these references will be followed up by the validation engine as well.
In other words I feel that simply stating
This ensures that validation is triggered even if no nested properties are found.
...does not emphasize that @Valid is not merely good practice but is needed in 99% of cases when a valid nested configuration is expected. It should be clearly pointed out that no validation is done on missing values without the annotation.