Did you know you can validate configuration properties at spring application startup with @ConfigurationProperties
annotation? This can validate properties on application startup when used in conjunction with JSR-380 bean validation annotations such as @Min
, @NotNull
.
List of built in validation constraints in JSR 380
The @Validated
annotation at the class level in conjunction with @ConfigurationProperties
is used to enable validation.
@Getter @Setter @Component @Validated @ConfigurationProperties(prefix = "importer.service") public class ImporterProperties { @NotNull private String filePath; @Min(3) private int threadPoolSize; }
application.properties
importer.service.filePath=/nfs/files importer.service.threadPoolSize=1
It will bind these properties to the ImporterProperties
object and validate them at application startup, thus ensuring the application doesn't run with invalid configurations.
If the validation fails it will result in BindException
as shown below:
*************************** APPLICATION FAILED TO START *************************** Description: Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'importer.service' to com.stacktips.app.config.ImporterProperties failed: Property: importer.service.threadPoolSize Value: "1" Origin: class path resource [application.properties] - 4:35 Reason: must be greater than or equal to 3 Action: Update your application's configuration
Please note, for this validation to work, we need to have a JSR-380 implementation like Hibernate Validator on your classpath and we need to explicitly enable the configuration properties validation.
implementation 'org.springframework.boot:spring-boot-starter-validation'
Considerations for using Records
Starting with Spring Boot 2.6 and Java 16 you can use record classes with @ConfigurationProperties
. But there are few things you need to consider when using records.
@Validated @ConfigurationProperties(prefix = "importer.service") public record ImporterProperties( @NotNull String filePath, @Min(3) int threadPoolSize) { }
Notice that, you cannot use @Componenet
annotation when using records. Your IDE will show annotated with @ConstructorBinding but defined as Spring component
error.
To fix this, we need to remove the @Component
annotation and @EnableConfigurationProperties
or explicitly do the bean registration using the @Bean
annotation in one of your @Configuration
class.
For example:
@EnableConfigurationProperties(ImporterProperties.class) @SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }