In Spring Boot application, we can have @ConfigurationProperties classes validated via JSR-303/349 (Java EE Bean Validation specification) annotations. To make it work, we need to use Spring @Validated annotation on our configuration class. We also need to add a JSR-303/349 implementation in the classpath.
Example
Adding Hibernate validator dependency
In this example, we are going to use Hibernate validator (which is the reference implementation of JSR-303/349), so we have to add the related maven dependency:
pom.xml<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
Note that, we did not add the hibernate-validator version, that's because it is already configured in spring-boot-dependencies pom (which is the parent of spring-boot-starter-parent).
The external properties
src/main/resources/application.propertiesspring.main.banner-mode=off
spring.main.logStartupInfo=false
app.admin-contact-number=111-111-111
app.refresh-rate=0
@ConfigurationProperties class
@Component
@ConfigurationProperties("app")
@Validated
public class MyAppProperties {
@Pattern(regexp = "\\d{3}-\\d{3}-\\d{4}")
private String adminContactNumber;
@Min(1)
private int refreshRate;
.............
}
Note that, we have added @Validated annotation to turn on the validation.
Also, we purposely added such values in the external properties files, which should fail per above validation annotations. We are doing that to see whether or not the validation is performed as expected.
The Main class
@SpringBootApplication
public class ExampleMain {
public static void main(String[] args) throws InterruptedException {
ConfigurableApplicationContext context = SpringApplication.run(ExampleMain.class, args);
MyAppProperties bean = context.getBean(MyAppProperties.class);
System.out.println(bean);
}
} Output2017-08-09 15:01:32.304 INFO 14256 --- [mpleMain.main()] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4f1072ab: startup date [Wed Aug 09 15:01:32 CDT 2017]; root of context hierarchy 2017-08-09 15:01:32.572 WARN 14256 --- [mpleMain.main()] o.h.v.m.ParameterMessageInterpolator : HV000184: ParameterMessageInterpolator has been chosen, EL interpolation will not be supported 2017-08-09 15:01:32.636 WARN 14256 --- [mpleMain.main()] o.h.v.m.ParameterMessageInterpolator : HV000184: ParameterMessageInterpolator has been chosen, EL interpolation will not be supported 2017-08-09 15:01:32.706 ERROR 14256 --- [mpleMain.main()] o.s.b.b.PropertiesConfigurationFactory : Properties configuration failed validation 2017-08-09 15:01:32.707 ERROR 14256 --- [mpleMain.main()] o.s.b.b.PropertiesConfigurationFactory : Field error in object 'app' on field 'adminContactNumber': rejected value [111-111-111]; codes [Pattern.app.adminContactNumber,Pattern.adminContactNumber,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [app.adminContactNumber,adminContactNumber]; arguments []; default message [adminContactNumber],[Ljavax.validation.constraints.Pattern$Flag;@57cd9090,org.springframework.validation.beanvalidation.SpringValidatorAdapter$ResolvableAttribute@5f1d413f]; default message [must match "\d{3}-\d{3}-\d{4}"] 2017-08-09 15:01:32.707 ERROR 14256 --- [mpleMain.main()] o.s.b.b.PropertiesConfigurationFactory : Field error in object 'app' on field 'refreshRate': rejected value [0]; codes [Min.app.refreshRate,Min.refreshRate,Min.int,Min]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [app.refreshRate,refreshRate]; arguments []; default message [refreshRate],1]; default message [must be greater than or equal to 1] 2017-08-09 15:01:32.707 WARN 14256 --- [mpleMain.main()] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myAppProperties': Could not bind properties to MyAppProperties (prefix=app, ignoreInvalidFields=false, ignoreUnknownFields=true, ignoreNestedProperties=false); nested exception is org.springframework.validation.BindException: org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanPropertyBindingResult: 2 errors Field error in object 'app' on field 'adminContactNumber': rejected value [111-111-111]; codes [Pattern.app.adminContactNumber,Pattern.adminContactNumber,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [app.adminContactNumber,adminContactNumber]; arguments []; default message [adminContactNumber],[Ljavax.validation.constraints.Pattern$Flag;@57cd9090,org.springframework.validation.beanvalidation.SpringValidatorAdapter$ResolvableAttribute@5f1d413f]; default message [must match "\d{3}-\d{3}-\d{4}"] Field error in object 'app' on field 'refreshRate': rejected value [0]; codes [Min.app.refreshRate,Min.refreshRate,Min.int,Min]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [app.refreshRate,refreshRate]; arguments []; default message [refreshRate],1]; default message [must be greater than or equal to 1] 2017-08-09 15:01:32.711 INFO 14256 --- [mpleMain.main()] utoConfigurationReportLoggingInitializer :
Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. 2017-08-09 15:01:32.713 ERROR 14256 --- [mpleMain.main()] o.s.b.d.LoggingFailureAnalysisReporter :
*************************** APPLICATION FAILED TO START ***************************
Description:
Binding to target MyAppProperties{adminContactNumber='111-111-111', refreshRate=0} failed:
Property: app.adminContactNumber Value: 111-111-111 Reason: must match "\d{3}-\d{3}-\d{4}"
Property: app.refreshRate Value: 0 Reason: must be greater than or equal to 1
Action:
Update your application's configuration
[WARNING] java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:294) at java.lang.Thread.run(Thread.java:745) Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myAppProperties': Could not bind properties to MyAppProperties (prefix=app, ignoreInvalidFields=false, ignoreUnknownFields=true, ignoreNestedProperties=false); nested exception is org.springframework.validation.BindException: org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanPropertyBindingResult: 2 errors Field error in object 'app' on field 'adminContactNumber': rejected value [111-111-111]; codes [Pattern.app.adminContactNumber,Pattern.adminContactNumber,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [app.adminContactNumber,adminContactNumber]; arguments []; default message [adminContactNumber],[Ljavax.validation.constraints.Pattern$Flag;@57cd9090,org.springframework.validation.beanvalidation.SpringValidatorAdapter$ResolvableAttribute@5f1d413f]; default message [must match "\d{3}-\d{3}-\d{4}"] Field error in object 'app' on field 'refreshRate': rejected value [0]; codes [Min.app.refreshRate,Min.refreshRate,Min.int,Min]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [app.refreshRate,refreshRate]; arguments []; default message [refreshRate],1]; default message [must be greater than or equal to 1] at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:334) at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:291) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) at com.logicbig.example.ExampleMain.main(ExampleMain.java:11) ... 6 more Caused by: org.springframework.validation.BindException: org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanPropertyBindingResult: 2 errors Field error in object 'app' on field 'adminContactNumber': rejected value [111-111-111]; codes [Pattern.app.adminContactNumber,Pattern.adminContactNumber,Pattern.java.lang.String,Pattern]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [app.adminContactNumber,adminContactNumber]; arguments []; default message [adminContactNumber],[Ljavax.validation.constraints.Pattern$Flag;@57cd9090,org.springframework.validation.beanvalidation.SpringValidatorAdapter$ResolvableAttribute@5f1d413f]; default message [must match "\d{3}-\d{3}-\d{4}"] Field error in object 'app' on field 'refreshRate': rejected value [0]; codes [Min.app.refreshRate,Min.refreshRate,Min.int,Min]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [app.refreshRate,refreshRate]; arguments []; default message [refreshRate],1]; default message [must be greater than or equal to 1] at org.springframework.boot.bind.PropertiesConfigurationFactory.checkForBindingErrors(PropertiesConfigurationFactory.java:359) at org.springframework.boot.bind.PropertiesConfigurationFactory.doBindPropertiesToTarget(PropertiesConfigurationFactory.java:276) at org.springframework.boot.bind.PropertiesConfigurationFactory.bindPropertiesToTarget(PropertiesConfigurationFactory.java:240) at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:329) ... 24 more
Example ProjectDependencies and Technologies Used: - Spring Boot 1.5.6.RELEASE
Corresponding Spring Version 4.3.10.RELEASE - spring-boot-starter : Core starter, including auto-configuration support, logging and YAML.
- hibernate-validator 5.3.5.Final: Hibernate's Bean Validation (JSR-303) reference implementation.
- JDK 1.8
- Maven 3.3.9
|
|