The following nested constructor-binding configuration properties don't seem to work with validation:

@ConfigurationProperties("constructor-binding")
@ConstructorBinding
@Validated
@Data
@AllArgsConstructor
public class ConstructorBindingProperties {

    @NotEmpty
    private final String firstName;
    @NotEmpty
    private final String lastName;

    // Validation doesn't work.
    @Valid
    private final Nested nested;

    @Data
    public static class Nested {

        @NotEmpty
        private String first;
        @NotEmpty
        private String second;

    }

}

For setter-binding, initialized nested configuration properties work with validation, but uninitialized ones don't seem to work with validation. The following code is what I used:

@ConfigurationProperties("setter-binding")
@Validated
@Data
public class SetterBindingProperties {

    @NotEmpty
    private String firstName;
    @NotEmpty
    private String lastName;

    // Validation doesn't work.
    @Valid
    private Nested nested;

    // Validation works.
    @Valid
    private Nested initializedNested = new Nested();

    @Data
    public static class Nested {

        @NotEmpty
        private String first;
        @NotEmpty
        private String second;

    }

}

This is a sample project to reproduce it: https://github.com/izeye/spring-boot-throwaway-branches/tree/configprops

Comment From: snicoll

Unfortunately, there's nothing we can do about that. That's part of the validation contract to ignore null references. In the first case, rather than using Lombok, you should write the constructor and use @DefaultValue to indicate you want an instance rather than null if no fields of Nested are set.