The Spring Boot @ConfigurationProperties annotation enables us to bind the external property file or YAML file to a Java Bean Object. In this article let’s learn how to use Spring Boot @ConfigurationProperties annotation.
Folder Structure:
- Create a Maven project (maven-archetype-quickstart) “SpringBootConfigurationProperties” and create a package for our source files “com.javainterviewpoint” under src/main/java
- Now add the following dependency in the POM.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javainterviewpoint</groupId> <artifactId>SpringBootConfigrationProperties</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>SpringBootConfigrationProperties</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.18.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.5.Final</version> </dependency> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>2.0.1.Final</version> </dependency> <!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> --> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
- Create the Java classes SpringBootApp.java and JdbcProperties.java under com.javainterviewpoint folder.
The spring-boot-starter-parent is a special starter, it provides useful Maven defaults.
Spring Boot @ConfigurationProperties Example
Dependency Tree
[INFO] ------------------------------------------------------------------------ [INFO] Building SpringBootConfigrationProperties 0.0.1-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-dependency-plugin:3.1.1:tree (default-cli) @ SpringBootConfigrationProperties --- [INFO] com.javainterviewpoint:SpringBootConfigrationProperties:jar:0.0.1-SNAPSHOT [INFO] +- org.springframework.boot:spring-boot-starter:jar:2.1.1.RELEASE:compile [INFO] | +- org.springframework.boot:spring-boot:jar:2.1.1.RELEASE:compile [INFO] | | \- org.springframework:spring-context:jar:5.1.3.RELEASE:compile [INFO] | | +- org.springframework:spring-aop:jar:5.1.3.RELEASE:compile [INFO] | | +- org.springframework:spring-beans:jar:5.1.3.RELEASE:compile [INFO] | | \- org.springframework:spring-expression:jar:5.1.3.RELEASE:compile [INFO] | +- org.springframework.boot:spring-boot-autoconfigure:jar:2.1.1.RELEASE:compile [INFO] | +- org.springframework.boot:spring-boot-starter-logging:jar:2.1.1.RELEASE:compile [INFO] | | +- ch.qos.logback:logback-classic:jar:1.2.3:compile [INFO] | | | +- ch.qos.logback:logback-core:jar:1.2.3:compile [INFO] | | | \- org.slf4j:slf4j-api:jar:1.7.25:compile [INFO] | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.11.1:compile [INFO] | | | \- org.apache.logging.log4j:log4j-api:jar:2.11.1:compile [INFO] | | \- org.slf4j:jul-to-slf4j:jar:1.7.25:compile [INFO] | +- javax.annotation:javax.annotation-api:jar:1.3.2:compile [INFO] | +- org.springframework:spring-core:jar:5.1.3.RELEASE:compile [INFO] | | \- org.springframework:spring-jcl:jar:5.1.3.RELEASE:compile [INFO] | \- org.yaml:snakeyaml:jar:1.23:runtime [INFO] +- org.hibernate.validator:hibernate-validator:jar:6.0.13.Final:compile [INFO] | +- org.jboss.logging:jboss-logging:jar:3.3.2.Final:compile [INFO] | \- com.fasterxml:classmate:jar:1.4.0:compile [INFO] \- javax.validation:validation-api:jar:2.0.0.Final:compile [INFO] ------------------------------------------------------------------------
Defining Properties file [application.properties]
Spring Boot by default loads the application.properties located in the classpath. Place the application.properties file under src/main/resources folder.
# MySQL DB properties jdbc.driver = com.mysql.jdbc.Driver jdbc.url = jdbc:mysql://localhost:3306/mydb jdbc.username = root jdbc.password = admin
equivalent YAML file [application.yaml]
jdbc: driver: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/mydb username: root password: admin
Binding External Properties using @ConfigurationProperties annotation
The @ConfigurationProperties annotation reads and maps the property file based on the namespace specified through prefix attribute. In our case we have specified the prefix as “jdbc”
We have also added @Configuration annotation to the our JdbcProperties class in order to spring be able find this bean class and make it available for injection.
JdbcProperties class is a simple POJO containing the getters and setters for the properties driver, url, username and password.
package com.javainterviewpoint; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @Configuration @ConfigurationProperties(prefix = "jdbc") public class JdbcProperties { public String driver; public String url; public String username; public String password; public String getDriver() { return driver; } public void setDriver(String driver) { this.driver = driver; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "JdbcProperties [driver=" + driver + ", url=" + url + ", username=" + username + ", password=" + password + "]"; } }
SpringBootApp.java
package com.javainterviewpoint; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootApp { @Autowired private JdbcProperties jdbcProperties; public static void main(String[] args) throws Exception { SpringApplication.run(SpringBootApp.class, args); } @PostConstruct public void display() { System.out.println("*** Read from Property file ***"); System.out.println("Url : "+jdbcProperties.getUrl()); System.out.println("Driver : "+jdbcProperties.getDriver()); System.out.println("Username : "+jdbcProperties.getUsername()); System.out.println("Password : "+jdbcProperties.getPassword()); } }
- @SpringBootApplication annotation does the work of @EnableAutoConfiguration, @Configuration and @ComponentScan annotations together
- We have injected the JdbcProperties class using the @Autowired annotation
- @PostConstruct annotation runs after the service is initialized and prints the property file data.
Output:
Select the Project –>Run As –> Run Configuration –>Maven –> New. In the Main tab, key in the Goals as “spring-boot:run” and click on Run.
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.1.RELEASE) 2018-12-21 22:58:46.525 INFO 7468 --- [ main] com.javainterviewpoint.SpringBootApp : Starting SpringBootApp on Jack-PC with PID 7468 (D:\sts-3.8.3.RELEASE\Workspace\SpringBootConfigurationProperties\target\classes started by Jack in D:\sts-3.8.3.RELEASE\Workspace\SpringBootConfigurationProperties) 2018-12-21 22:58:46.531 INFO 7468 --- [ main] com.javainterviewpoint.SpringBootApp : No active profile set, falling back to default profiles: default *** Read from Property file *** Url : jdbc:mysql://localhost:3306/mydb Driver : com.mysql.jdbc.Driver Username : root Password : admin
Validation of properties
Additionally we can validate the properties with validation constraints like @NotNull, @NotEmpty, @Email etc. In order to enable validation we need to add @Validated annotation to the @ConfigurationProperties class.
Lets add the validation constraint annotation and check
package com.javainterviewpoint; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @Configuration @ConfigurationProperties(prefix = "jdbc") public class JdbcProperties { @NotNull public String driver; @NotEmpty public String url; public String username; public String password; public String getDriver() { return driver; } public void setDriver(String driver) { this.driver = driver; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "JdbcProperties [driver=" + driver + ", url=" + url + ", username=" + username + ", password=" + password + "]"; } }
We have missed to provide value to the url property and lets see if spring is throwing a validation error.
# MySQL DB properties
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url
jdbc.username = root
jdbc.password = admin
Output
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.5.8.RELEASE) 2018-12-21 23:19:53.418 INFO 3228 --- [ main] com.javainterviewpoint.SpringBootApp : Starting SpringBootApp on Jack-PC with PID 3228 (D:\sts-3.8.3.RELEASE\Workspace\SpringBootConfigurationProperties\target\classes started by Jack in D:\sts-3.8.3.RELEASE\Workspace\SpringBootConfigurationProperties) 2018-12-21 23:19:53.423 INFO 3228 --- [ main] com.javainterviewpoint.SpringBootApp : No active profile set, falling back to default profiles: default 2018-12-21 23:19:54.684 ERROR 3228 --- [ main] o.s.b.b.PropertiesConfigurationFactory : Properties configuration failed validation 2018-12-21 23:19:54.684 ERROR 3228 --- [ main] o.s.b.b.PropertiesConfigurationFactory : Field error in object 'jdbc' on field 'url': rejected value []; codes [NotEmpty.jdbc.url,NotEmpty.url,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [jdbc.url,url]; arguments []; default message [url]]; default message [must not be empty] 2018-12-21 23:19:54.685 WARN 3228 --- [ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'springBootApp': Unsatisfied dependency expressed through field 'jdbcProperties'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jdbcProperties': Could not bind properties to JdbcProperties (prefix=jdbc, ignoreInvalidFields=false, ignoreUnknownFields=true, ignoreNestedProperties=false); nested exception is org.springframework.validation.BindException: org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanPropertyBindingResult: 1 errors Field error in object 'jdbc' on field 'url': rejected value []; codes [NotEmpty.jdbc.url,NotEmpty.url,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [jdbc.url,url]; arguments []; default message [url]]; default message [must not be empty] 2018-12-21 23:19:54.698 INFO 3228 --- [ main] utoConfigurationReportLoggingInitializer : Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled. 2018-12-21 23:19:54.702 ERROR 3228 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPLICATION FAILED TO START *************************** Description: Binding to target JdbcProperties [driver=com.mysql.jdbc.Driver, url=, username=root, password=admin] failed: Property: jdbc.url Value: Reason: must not be empty Action: Update your application's configuration
Leave a Reply