Read the Application Properties or a YAML file as a Java Map in Spring Boot.
Tutorial Contents
Overview
In a Spring or Spring Boot application, an application properties file or an application YAML file help us externalize important configurations. On top of that, the @ConfigurationProperties annotation in Spring Boot allows us to easily read and bind those configurations into Java objects.
This tutorial focuses on reading application configurations from a property or a YAML file into Java HashMap objects.
To learn more about reading application properties or YAML files into Java beans, please read Using @ConfigurationProperties in Spring Boot.
YAML or a Properties File
For this tutorial, we will work on a YAML-based configuration. However, note that all the examples in this tutorial are also applicable when using any equivalent application properties file.
Look at a typical YAML application file from a Spring Boot application.
application.yaml
spring:
  application:
    name: data-service
  servlet:
    multipart:
      enabled: true
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3309/test
    password: password
    username: test_user
Code language: YAML (yaml)Alternatively, We can rewrite the same configurations in a properties file.
application.properties
spring.application.name=data-service
spring.servlet.multipart.enabled=true
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3309/test
spring.datasource.password=password
spring.datasource.username=test_userCode language: Properties (properties)Both files contain the same configurations, and Spring Boot seamlessly works with YAML and Properties files. However, the YAML syntax is more organized and readable when we compare a properties file to an equivalent YAML file.
YAML file To Java Map
A YAML and Properties files contain sets of key and value pairs. That makes it more similar to a Map data structure. Thus, mapping a YAML or properties file into a Java HashMap is straightforward.
The following snippet demonstrates how we can use plain Java Map instances to model the Properties or YAML-based configurations we saw in the previous section.
Map<String, String> application = Map.of("name", "data-service");
        
Map<String, String> servlet = Map.of(
  "multipart.enabled", "true"
);
Map<String, String> datasource = Map.of(
  "driverClassName", "com.mysql.cj.jdbc.Driver",
  "url", "mysql://localhost:3309/test",
  "password", "password",
  "username", "test_user"
);Code language: Java (java)Interestingly, in our configuration, the sub-group of “servlet” has a nested Map. We can model the nested map using a dot notation, as seen here.
Alternatively, we change the type of the servlet map and make it a nested Map (Map of Maps).
Map<String, Map<String, String>> servlet = Map.of(
  "multipart", Map.of("enabled", "true")
);Code language: Java (java)We understood how a Map, YAML or a Properties file have similar data structures. Next, we will learn how Spring Boot @ConfigurationProperties annotation help map the application configurations from a YAML or Properties file into Java Map instances.
Reading YAML or Properties as Java Map
To read application YAML or Properties configurations as a Java Map, we need to define a Map member in an @ConfigurationProperties class.
Under the root, ‘spring‘, the YAML (or Properties) file contains three nested subgroups of configurations. Let’s use the prefix ‘spring‘ to read them in separate Map instances.
@Configuration
@ConfigurationProperties(prefix = "spring")
public class MapProperties {
  Map<String, String> application;
  Map<String, String> servlet;
  Map<String, String> datasource;
    
  // Constructor, Getter and Setter methods
}Code language: Java (java)The class has all three maps, and their names correspond to the name of the respective properties subgroups. We have also added a well-formatted toString() method that we will use to print the bean when the application starts.
* Java Map based Properties
application:
  name=data-service
servlet:
  multipart.enabled=true
datasource:
  driverClassName=com.mysql.cj.jdbc.Driver
  url=jdbc:mysql://localhost:3309/test
  password=password
  username=test_userCode language: plaintext (plaintext)From the output, we can see all the fields in the map are populated as expected.
Reading YAML Properties as Nested Java Map
To read nested Java Maps from a YAML file or a Properties File, we can change the type of the “servlet” field to Map<String, Map<String, String>>.
@Configuration
@ConfigurationProperties(prefix = "spring")
public class NestedMapProperties {
  Map<String, String> application;
  Map<String, Map<String, String>> servlet;
  Map<String, String> datasource;
  // Constructor, Getter, and Setter methods
}Code language: Java (java)When we print the populated bean, we see that the nested Maps are correctly read from our YAML file.
* Java Map based nested Properties
application:
  name=data-service
servlet:
  multipart={enabled=true}
datasource:
  driverClassName=com.mysql.cj.jdbc.Driver
  url=jdbc:mysql://localhost:3309/test
  password=password
  username=test_userCode language: plaintext (plaintext)Reading YAML Properties as MultiValue Map
Sometimes, we may have a list of values in a YAML or a Properties Files that we want to bind in a Java Bean. Spring Boot @ConfigurationProperties allows binding a list from a YAML as a Java multi-value Map instance.
A list in a YAML file looks like this,
spring:
  application:
    name: data-service
  servlet:
    multipart:
      enabled: true
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3309/test
    password: password
    username: test_user
  profiles:
    active:
      - dev
      - qa
      - staging
      - prodCode language: YAML (yaml)Or, use an in-line list with comma-separated values
spring:
  ## Skipped
  profiles:
    active: dev, qa, staging, prodCode language: YAML (yaml)To read the ‘spring.profiles.active‘, we changed our Map to a multi-value Map.
@Configuration
@ConfigurationProperties(prefix = "spring")
public class NestedMapProperties {
  Map<String, String> application;
  Map<String, Map<String, String>> servlet;
  Map<String, String> datasource;
  Map<String, List<String>> profiles;
  // Constructor, Getter, and Setter methods
}Code language: Java (java)Using that, we can verify list of all the active profiles is loaded correctly.
* Java Map based nested Properties
application:
  name=data-service
servlet:
  multipart={enabled=true}
datasource:
  driverClassName=com.mysql.cj.jdbc.Driver
  url=jdbc:mysql://localhost:3309/test
  password=password
  username=test_user
profiles:
  active=[dev, qa, staging, prod]Code language: plaintext (plaintext)Summary
This tutorial focused on Reading different keys and value pairs from a YAML or a Properties file into a Java HashMap. We understood that a YAML or a Properties file are similar to the Map data structure. Thus, we can easily bind the configurations in Java Maps.
We covered examples of reading a simple Map, Nested Map, and MultiValueMap from a YAML or equivalent application properties file.
Refer to our GitHub Repository for the complete source code.
More like this:
- Using @ConfigurationProperties in Spring Boot
- YAML to Java List of Objects in Spring Boot
- Reading Nested Properties in Spring Boot
- Validations with @ConfigurationProperties in Spring Boot
