We have an application that can be deployed with different profiles. Some features are disabled via feature toggle. When a feature is enabled, we want to make sure that the necessary configuration is valid. Today we have @NotBlank annotation, so when a feature is disabled we put a dummy value for that property. What is important is to make sure it's well configured when the feature is enabled.

We tried to clean the configuration by removing the @NotBlank and make the validation by using a Validator based on active profiles. The issue is that the validate method is not called.

Sample Application:

@SpringBootApplication
public class ConfigurationPropertiesValidationApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigurationPropertiesValidationApplication.class, args);
    }

}

@Configuration
@EnableConfigurationProperties(MyProperties.class)
class AppConfig {
}

@ConstructorBinding
@ConfigurationProperties(prefix = "experiment")
@Validated
class MyProperties implements Validator {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyProperties.class);

// The NotBlank validation would be handled by the validate method
//    @NotBlank
    private final String value;

    MyProperties(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return MyProperties.class.isAssignableFrom(aClass);
    }

    @Override
    public void validate(Object o, Errors errors) {
        // Validate based on active profiles
    }
}

application-aws.yaml

experiment:
  value: mandatory on AWS

Spring Boot 2.3.4 +

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Comment From: wilkinsona

This isn't how the Validator interface is intended to be used. A Validator implementation is intended to perform validation of various types of objects rather than being an indication that an object should validate itself. There's nothing that knows to use yourMyProperties as a validator so there's nothing that calls validate(Object, Errors).

As you are using constructor binding, you could perform your manual validation in the constructor. Alternatively you could implement InitializingBean and perform the validation in afterPropertiesSet.

If you have any further questions, please follow up on Stack Overflow or Gitter. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.