You are here
Home > java >

How to Write Spring Boot Application Properties Files

How to Write Spring Boot Application Properties FilesIf you are a Spring Boot developer, you must have come across the ‘application.properties’ or ‘application.yml’ file. Needless to say, these files reduces your development effort by minimizing the amount of XMLs that you were writing in a standard Spring based project. Moreover, we accommodate the common properties of our project in the form of key-value pairs in these files. Therefore, it becomes more than important to know all about these files. These are application properties file with the extension of either ‘.properties’ or ‘.yml’. The topic of discussion for this article is ‘How to Write Spring Boot Application Properties Files’.

Furthermore, Spring Boot already provides some of the ready-made keys that we use most of the times in our project. Sometimes, we need to create custom properties files in order to fulfil the business requirements. So, we will discuss all about them in this article step by step. Additionally, if you are going to appear in any Spring Boot interview, you are expected to get at least one question from this article. Let’s go through our article ‘How to Write Spring Boot Application Properties Files’ and its related concepts step by step.

Table of Contents

What is application.properties in Spring Boot?

In a Spring Boot Application, ‘application.properties’ is an input file to set the application up. Unlike the standard Spring framework configuration, this file is auto detected in a Spring Boot Application. It is placed inside “src/main/resources” directory. Therefore, we don’t need to specifically register a PropertySource, or even provide a path to a property file.

An application.properties file stores various properties in key=value format. These properties are used to provide input to Spring container object, which behaves like one time input or static data.

What types of keys does an application.properties contain?

An application.properties file contains two types of keys : pre-defined keys, and programmer defined keys.

Pre-defined Keys

Spring framework provides several common default properties to specify inside application.properties such as to support database, email, JPA, Hibernate,  Logging, AOP etc. We can find the list of Common Application Properties from Spring Official Documentation.

However, we don’t need to define all the default properties every time. We can define what are required for our application at present. This is also a benefit of using Spring Boot where it reduces XML based configurations and customize them to simple properties.

Programmer-defined Keys

A programmer can also define project specific keys whenever required. We will discuss about how to define them in the following sections of this article.

What are the valid locations of Properties files in the Project? How to load them?

Generally, there are two valid locations for Properties file:

1) src/main/resource (classpath:)
Syntax for this is: @PropertySource(“classpath:application.properties”)

2) Inside project folder ( file:/)
Syntax for this is:@PropertySource(“file:/application.properties”)

How to read keys of the properties file into the application?

In order to read values from keys, we have two approaches:

Using @Value Annotation

This annotation is provided by the Spring Framework. To read one key from the properties file, we need to declare one variable in our class. Moreover, we need to apply the @Value annotation at the variable with the key as a parameter to it. It’s like @Value(“${key}”)

♥ At a time we can read one key value into one variable. For example, if we have 10 keys, then we should write @Value on top of 10 variables.

♥ If the key is not present in the properties file and we try to read using @Value() then it will throw an Exception:
IllegalArgumentException: Could not resolve placeholder ‘my.app.id’ in value “${my.app.id}”

Using @ConfigurationProperties Annotation

This is provided by Spring Boot. We will discuss about in detail in the subsequent sections.

How does the @Value work internally in Spring?

First ‘application.properties’ file is loaded using code like @PropertySource(“classpath:application.properties”). Now, Spring container creates one MEMORY “Environment” (key-val pairs) that holds all the key-vals given by Properties file. We can read those values into variable using Syntax
@Value(“${key}”). Then, @Value will search for key in Environment memory. If found then value is updated into container object.

How to write Custom Properties file in Spring Boot?

There are some certain steps to write our own properties file. Let’s follow below steps:

Step#1:  Define your properties file with any name with extension .properties

Right click on ‘src/main/resources’ > new > file > Enter name : product.properties
Additionally, Enter content as applicable. For example,

-----product.properties------
product.title=my product
product.version=2.5

Step#2: At Main class/Starter class, apply @PropertySource annotation
In our case, the Syntax will be: @PropertySource(“classpath:product.properties”)

Example: 

For Example, let’s assume we are going to define a ‘product.properties’

Step #1: Create a Spring Boot Project

Here, we will use STS(Spring Tool Suite) to create our Spring Boot Project. If you are new to Spring Boot, visit Internal Link to create a sample project in spring boot.

Step#2: Create a new properties file under src/main/resources folder

Let’s name it product.properties.

product.title=my product
product.version=2.5

Step#3: Create a class to read values from properties file

In order to read values from properties file, let’s create a class Product.java as below. Don’t forget to apply @Component annotation.

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Product {

    @Value("${product.title}")
    private String title;

    @Value("${product.version}")
    private Double version;

    @Override
    public String toString() {
       return "Product [title=" + title + ", version=" + version + "]";
    }
}

Step#4: Apply @PropertySource(“—“) at the main/starter class

In main or starter class whichever is applicable in your case, apply @PropertySource(“classpath:product.properties”) in order to tell Spring Container that you are using a custom properties file as below. Moreover, we need to print the product class to check the values.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.PropertySource;

@SpringBootApplication
@PropertySource("classpath:product.properties")
public class SpringBootPropertiesApplication {

    public static void main(String[] args) {

       ApplicationContext applicationContext = SpringApplication.run(SpringBootPropertiesApplication.class, args);
       Product product= applicationContext.getBean("product", Product.class);
       System.out.println(product);
    }
}

Step#4: Test the output

Right click on the project, Run As > Spring Boot App. Now check the output at console. You will see the below output.

Product [title=my product, version=2.5]

How can we create and load multiple properties files in the application?

It is absolutely possible to create & load multiple properties files in the application with the help of @PropertySource itself. Below is the syntax to use it in case of multiple properties.

@PropertySource({
     "classpath:abc.properties",
     "classpath:pqr.properties",
     "classpath:xyz.properties",
     "....",
     "...."
})

If we define the same key with different values in different properties files, which one will be selected?

In this case, the last loaded properties file key will be considered.

For example, consider the below properties file declaration.

@PropertySource({
     "classpath : abc.properties",     //  loading order 1st
     "classpath : xyz. properties"     //   loading order 2nd
})

From the above example, first it will check in ‘abc.properties’ for the given key, if the key also exists in ‘xyz.properties’, the values will be reflected from ‘xyz.properties’, as it is loaded at the last.
♦ if it doesn’t exist in both the files, priority is for ‘application.properties’.

How to map multiple properties with a single variable? When to use @ConfigurationProperties annotation?

As aforementioned, we can use @Value annotation to read only one property from the properties file at a time into our code. Spring core framework provides this feature. Suppose we have a requirement where we need to read multiple properties from properties file in our code. Here, we will make use of @ConfigurationProperties annotation. Furthermore, @ConfigurationProperties also supports working with Collections and Bean Type (class Type). Actually, we will have this kind of scenario multiple times in our project. Let’s be aware that Spring Boot provides the @ConfigurationProperties annotation.

What are the general guidelines/rules to use @ConfigurationProperties annotation?

1) The prefix provided inside the @ConfigurationProperties annotation must match with the prefix given in the properties file, else variable will not get the correct values.

2) We must generate getters and setters for the variables that we used to map with the keys of properties file.

♥ Note: Since @Value uses refection based data read, hence getters & setters are not required in that case.

♥ Note: While applying @ConfigurationProperties annotation, you may get a warning “When using @ConfigurationProperties it is recommended to use ‘spring-boot-configuration-processor’ to your classpath to generate configuration metadata’. You can resolve it by clicking on the warning and selecting ‘Add to spring-boot-configuration-processor pom.xml’ as shown below in the screenshot. Alternative way to resolve it is that you can manually add the dependency of  ‘spring-boot-configuration-processor’ in your pom.xml file.

Spring Boot Configuration Processor

Example: How to read multiple values from the properties file in our code?

Let’s develop an example of reading multiple values from the properties file in our code. However, in this example we will consider the simplest case. Further, in the subsequent sections, we will cover the complex scenarios.

Step#1: Update the application.properties file 

For example, let’s consider below values. Here, each entry is in the form of ‘prefix.variable=value’. Obviously, ‘prefix.variable’ forms the key. Therefore, the last word of the key becomes the variable in our class. On the other hand, the remaining left side part becomes the prefix, which in turn becomes the parameter of @ConfigurationProperties annotation.

product.app.id=1024
product.app.code=QS5329D
product.app.version=3.34

Step#2: Create a Runner class and define variables

Let’s create a class and define variables. Here we are taking a Runner class just to test the example easily. Also, let’s follow below guidelines.

1) Apply annotation @ConfigurationProperties(“product.app”) on top of the class. Make sure that prefix as a parameter of this annotation must match with the prefix given in the keys of the properties file. In our case, ‘product.app’ is the prefix.

2) After prefix we have id, code & version respectively in the keys. Hence, these parts of the keys will become the variable names in our class as below.

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties("product.app")
@PropertySource("classpath:product.properties")
public class ProductDataReader implements CommandLineRunner {

    private Integer id;
    private String code;
    private Double version;

    @Override
    public void run(String... args) throws Exception {
       System.out.println(this);
    }

    @Override
    public String toString() {
       return "ProductDataReader [id=" + id + ", code=" + code + ", version=" + version + "]";
    }

    public Integer getId() {
       return id;
    }

    public void setId(Integer id) {
       this.id = id;
    }

    public String getCode() {
       return code;
    }

    public void setCode(String code) {
       this.code = code;
    }

    public Double getVersion() {
       return version;
    }

    public void setVersion(Double version) {
       this.version = version;
    }
}

However, in this example, we have applied @PropertySource(“classpath:product.properties”) in Runner class. We can also apply it at the main class optionally.

Step#3: Check the Output

Now, run the application and check the output. It will be like below.

ProductDataReader [id=1024, code=QS5329D, version=3.34]

How to read multiple values from the properties file in our code as a Collection?

We need to follow some guidelines in order to read values from properties file in the form of a Collection in our code. Every developer knows how to define a collection variable in the class. But how can we define the respective values in the properties file is the point of discussion here. Let’s discuss it step by step as below.

List/Set/Array 

In case of List, Set and Array, we should use index that starts with zero as below.

prefix.variable[index]=value
For example: product.app.info[0]=InfoValue1,  product.app.info[1]=InfoValue2, …..and so on.

Map/Properties

Let’s understand a basic difference between Map & Properties first. Map (Interface) Generics Types are provided by Programmer and having multiple Implementations. Properties is a class that stores data with single format key=val (by default converted as String). Here, Map & Properties takes the same format key=value as shown below.

prefix.variable.key=value
For example: product.app.category.C1=CategoryValue1, product.app.category.C2=CategoryValue2, …..and so on.

Example

Step#1: Update the application.properties file 

Let’s update the product.properties file as per the guidelines given above.

product.app.info[0]=InfoValue1
product.app.info[1]=InfoValue2
product.app.info[2]=InfoValue3

product.app.category.C1=CategoryValue1
product.app.category.C2=CategoryValue2

Step#2: Create a Runner class and define variables

As we have already discussed why we are using a Runner class here, let’s jump to the example directly as below.

import java.util.List;
import java.util.Map;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties("product.app")
@PropertySource("classpath:product.properties")
public class ProductDataReader implements CommandLineRunner {

    private List<String> info;
    //private Set<String> info;
    //private String[] info;

    private Map<String,String> category;
    //private Properties category;

    @Override
    public void run(String... args) throws Exception {
       System.out.println(this);
    }

    public List<String> getInfo() {
       return info;
    }

    public void setInfo(List<String> info) {
       this.info = info;
    }

    public Map<String, String> getCategory() {
       return category;
    }

    public void setCategory(Map<String, String> category) {
       this.category = category;
    }

    @Override
    public String toString() {
       return "ProductDataReader [info=" + info + ", category=" + category + "]";
    }
}

Step#3: Check the Output

Now, run the application and check the output. It will be like below.

ProductDataReader [info=[InfoValue1, InfoValue2, InfoValue3], category={C2=CategoryValue2, C1=CategoryValue1}]

How to read multiple values from the properties file in our code as an Object?

Instead of being a Collection type, suppose our variable is an instance of a particular type. In this case also, we need to follow some guidelines in order to read values from properties file. Let’s discuss it step by step as below.

We can even read properties data into one class object by using HAS-A relation and syntax is as below:

prefix.objectName.variable=value     

              OR    

prefix.hasAVariable.variable=value

Step#1: Update the application.properties file 

Let’s update the product.properties file as per the guidelines given above.

product.app.brand.name=brandName
product.app.brand.price=4569.75

Step#2: Create a model class and define its properties 

In order to make a variable of a particular type(Class type), let’s create a model class & define some properties. To illustrate, let’s assume that we have a Brand of the Product. Therefore, we will create a Brand class as step by step as below.

1)  Create one class with variables(properties)
2)  Generate getters, setters, toString.
3)  Use this class as Data Type and create HAS-A variable(reference variable) in other class.

Note:  Do not apply @Component over this class type. This object is created only on condition: ‘If data exists in properties file’. This work is taken care by the annotation @ConfigurationProperties.

public class Brand {

    private String name;

    private Double price;

    public String getName() {
       return name;
    }

    public void setName(String name) {
       this.name = name;
    }

    public Double getPrice() {
       return price;
    }

    public void setPrice(Double price) {
       this.price = price;
    }

    @Override
    public String toString() {
       return "Brand [name=" + name + ", price=" + price + "]";
    }
}

Step#3: Create a Runner class and define variables

As we have already discussed why we are using a Runner class here, let’s jump to the example directly as below.

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties("product.app")
@PropertySource("classpath:product.properties")
public class ProductDataReader implements CommandLineRunner {

    private Brand brand; //HAS-A 

    @Override
    public void run(String... args) throws Exception {
       System.out.println(this);
    }

    public Brand getBrand() {
       return brand;
    }

    public void setBrand(Brand brand) {
       this.brand = brand;
    }

    @Override
    public String toString() {
       return "ProductDataReader [brand=" + brand + "]";
    }
}

Step#4: Check the Output

Now, run the application and check the output. It will be like below.

ProductDataReader [brand=Brand [name=brandName, price=4569.75]]

Spring Boot Application Properties

What is YAML(.yml) file? 

YAML is a latest format to define key:val pairs without having duplicate words in more than one key. In other words, YAML is a convenient format for specifying hierarchical configuration data. It uses “Snake YAML” API and it is added by default in every Spring Boot Application. Moreover, it has following benefits for the developer.

1) It has a good look and feel and even easy to read.
2)  No duplicate words in levels/keys.
3)  Auto-Parsing supported using Snake-YAML API.
4)  Also, easy to write.

What are the rules/guidelines to write a YAML(.yml) file?

1) Unlike .properties file, dot(.) and equals(=) are not allowed, but only colon(:) is allowed.
2) Before each value in .yml file, we must provide exactly one blank space.
3) After every colon(:) symbols, go to new line/change line and provide spaces, if key is still incomplete.
4) Spaces count/indentation/alignment must be matching for the same level of key.
5) Do not provide any duplicate levels/hierarchy.

How to convert into YAML(.yml) file from a .properties file?

Typically, there are two ways to convert a .properties file into a .yml file:

1) Manually  2) With the help of IDE like STS.

Manually

1) Replace all occurrences of dot(.) and equals(=) with colon(:)
2) Follow rules/guidelines given in the above section.

If your file has lengthy content, it will take too much effort to convert.

Using STS

If you are using an IDE like STS(Spring Tool Suite), you can perform conversion in a single click as below.

Right click on .properties file and select option: Convert .properties to .yaml’ and finally click on ‘OK’. You will get a .yml file in less than a minute.

Example: Converting ‘.properties’ into ‘.yml’

For example, Let’s convert our ‘product.properties’ into ‘product.yml’.

product.properties

product.app.id=1024
product.app.code=QS5329D
product.app.version=3.34

product.app.info[0]=InfoValue1
product.app.info[1]=InfoValue2
product.app.info[2]=InfoValue3

product.app.category.C1=CategoryValue1
product.app.category.C2=CategoryValue2

product.app.brand.name=brandName
product.app.brand.price=4569.75

Apply any one of the method of conversion given in above section. Your final ‘product.yml’ file will look like below.

product.yml

product:
  app:
  brand:
    name: brandName
    price: 4569.75
  category:
    C1: CategoryValue1
    C2: CategoryValue2
  code: QS5329D
  id: 1024
  info:
  - InfoValue1
  - InfoValue2
  - InfoValue3
  version: 3.34

FAQ

Can we modify/rename file name application.properties in Spring Boot?

Yes we can, but it is not loaded by Spring Boot by default. By default, Spring Boot checks ‘application.properties’ under location ‘src/main/resources’. If we want to load other files, follow below steps:

1) Create your custom file at the same location (‘src/main/resources’)
2) Apply @PropertySource annotation at starter/runner class and provide the name of your custom file as a parameter to it.
For example: @PropertySource(“classpath:xyz.properties”)
here, the classpath is ‘src/main/resource’ folder

Alternatively, we can also keep this file inside project folder (file:/ = project folder)

If a key is present in both application.properties and our custom properties file, then which one will be selected?

Key from ‘application.properties’ will always have a higher priority.

Leave a Reply


Top