Introduction
Application properties may vary in different environments like how the hosts on your QA environment may vary from your local and production environments. Using Spring Boot, different environments can be configured and updated separately without affecting other environments with the use of property files.
In this article, we'll be demonstrating ways to access values defined within a property file in a Spring Boot project and ways to manipulate them in the code.
Spring Boot Property Files
Spring Boot provides a way to externalize configurations using property files that are located within the project's classpath. This is very useful for multi-environment set-ups so that properties can be dynamically configured per environment.
The default property file that Spring Boot generates is named application.properties
which is located in the project's src/main/resources/
directory. When initializing a project, the default property file is blank.
Here's an example of an application.properties
file containing two sample properties:
spring.datasource.username=user
logging.level.root=INFO
This sample file contains values for the username of a datasource
and the root logging level of the application. The properties follow the same key=value
syntax.
YAML Property Files
Alternatively, instead of the default .properties
syntax, Spring Boot also supports property files in YAML format. So instead of the default application.properties
file, you can create a new property file application.yml
if you prefer your properties in YAML format:
spring:
datasource:
username: user
logging:
level:
root: INFO
The only difference that this would entail is the formatting of the contents within the file so the choice is based solely on preference.
Spring Boot allows the declaration of multiple property files using the @PropertySource annotation defined through a configuration class.
Accessing Values Within Property Files in Spring Boot
Now we move on to the main topic which is - how to access the values within the aforementioned property files.
Using the @Value Annotation
The @Value
annotation is a predefined annotation used to read values from any property files under the project's classpath.
To access a single property's value from a property file using this annotation, you provide the property name as the argument:
@Value("${spring.sample.property}")
Following this syntax, let's take a look at an example where we set the value of a string variable to the datasource.username
defined within the property file in the example above:
@Value("${spring.datasource.username}")
String username;
If we print the variable above without any further manipulation, the output should be the value of the specified property declared in the @Value
annotation. In this case, it should print out the string user
:
System.out.println(username);
// user
If the property declared in the annotation does not exist within any property file, then the default initialization of the data type will be observed. In this case, the variable username
would be set to null
.
Updating the value of the variable annotated with the @Value
annotation also changes the actual value of the property injected into the variable during runtime:
username = "new_user"
This changes the value of the variable username
as well as temporarily changing the value of the property spring.datasource.username
.
Note that the changes made during runtime will be flushed once the program stops running so the changes won't reflect in the actual property file. This implies that property values are more dynamic instead of just being a constant value.
Here's a link to our comprehensive guide on the @Value
annotation if you want to know more about it.
Using the Environment Object
Another method to access values defined in Spring Boot is by autowiring the Environment
object and calling the getProperty()
method to access the value of a property file.
The getProperty()
method accepts a single required parameter which is a string containing the property name and returns the value of that property if it exists. If the property doesn't exist, the method will return a null
value.
For this example, let's access the logging.level.root
property and store it within a string value:
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
@Autowired
private Environment env;
public void getRootLogLevel() {
return env.getProperty("logging.level.root");
}
If the getRootLogLevel()
method is called and printed out, it will print out the value of the property if it exists. With the example property file stated above, this method should output INFO
.
Using the @ConfigurationProperties Annotation
The @ConfigurationProperties
annotation is a more expansive approach than the @Value
annotation and the Environment
object.
This method is used to access related groups of properties by storing the configuration in a POJO (Plain Old Java Object) and using the POJO for further access, unlike the previous solutions where the properties are accessed individually.
The @ConfigurationProperties
annotation will map values given the prefix of the group of properties.
For this solution, let's make a new application.properties
file:
spring.demo.username=user
spring.demo.password=password
spring.demo.email=[email protected]
All 3 properties configured in the file all have the same prefix spring.demo
.
Now, let's create a configuration class to map the values of these properties using the @ConfigurationProperties
annotation.
Note that besides annotating the class with @ConfigurationProperties
, you also need to annotate it with @Configuration
to inform the system that the class is a configuration class.
Also, the variable names within the class must be the same as the names within the property file with the given prefix. Let's make a DemoProperties
class:
@ConfigurationProperties(prefix="spring.demo")
@Configuration
public class DemoProperties {
private String username;
private String password;
private String email;
// Getters, Setters, Constructors, etc...
}
Now that the configuration is declared, the DemoProperties
instance can be used anywhere within the service layer to access property values just by autowiring the class:
@Autowired
private DemoProperties demoProperties;
public void printDemoProperties() {
System.out.println("Username: " + demoProperties.getUsername());
System.out.println("Password: " + demoProperties.getPassword());
System.out.println("Email Address: " + demoProperties.getEmail());
}
Calling the printDemoProperties()
method will output:
Username: user
Password: password
Email Address: [email protected]
Conclusion
This article covered three different ways of accessing values defined in Spring Boot. All of which are fairly easy to comprehend and apply to your projects!
The @Value
annotation is the most commonly used solution to access property values in Spring Boot. The Environment
object isn't used as often but still is a viable way to access a property value.
The @ConfigurationProperties
annotation is a bit more comprehensive and should only be used for bigger groups of properties that have the same prefix and the same context since you would need to accommodate this solution by creating a POJO to store the group of property values.