Main Tutorials

Spring @PropertySource example

Spring @PropertySource example

Spring default loads application.properties into the application’s environment, and we can use @PropertySource to load custom .properties files.

file.properties

file.path=/server1/file/path
Application.java

@Configuration
@PropertySource("classpath:file.properties")
public class Application {

    @Value("${file.path}")
    private String path;

    //...
}

Table of contents:

P.S. Tested with Spring Boot 3.1.2

1. Project Structure

This article shows how to use @PropertySource to read a few of the .properties files and inject the property values via @Value.

project structure

2. Properties Files

Below are two .properties files for testing.

db.properties

# Database
db.name=PostgreSQL
db.cluster.ip=127.0.0.1, 127.0.0.2, 127.0.0.3
file.properties

# File Server
file.path=/server1/file/path

3. @PropertySource and @Value

We can use @PropertySource to load the property values from the properties files and access the property values via @Value.

DatabaseProperties.java

package com.mkyong.config;

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

import java.util.ArrayList;
import java.util.List;

@Component
@PropertySource("classpath:/server/db.properties")
public class DatabaseProperties {

  @Value("${db.name}")
  private String name;

  @Value("${db.cluster.ip}")
  private List<String> clusterIp;

  //getters and setters
}
FileProperties.java

package com.mkyong.config;

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

@Component
@PropertySource("classpath:/server/file.properties")
public class FileProperties {

  @Value("${file.path}")
  private String path;

  //
}

Starts the Spring Boot application and displays the property values.

Application.java

package com.mkyong;

import com.mkyong.config.DatabaseProperties;
import com.mkyong.config.FileProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application implements CommandLineRunner {

  @Autowired
  private DatabaseProperties db;

  @Autowired
  private FileProperties file;

  @Override
  public void run(String... args) {
      System.out.println(db);
      System.out.println(file);
  }

  public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
  }

}

Output

Terminal

DatabaseProperties{name='PostgreSQL', clusterIp=[127.0.0.1, 127.0.0.2, 127.0.0.3]}
FileProperties{path='/server1/file/path'}

4. Loads property files from multiple sources

Below examples show how to load properties from multiple files.

4.1 @PropertySource with an argument of arrays of properties file location.

Application.java

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

@SpringBootApplication
@PropertySource({"classpath:/server/db.properties", "classpath:/server/file.properties"})
public class Application implements CommandLineRunner {

  @Autowired
  private DatabaseProperties db;

  @Autowired
  private FileProperties file;

  //...
}

4.2 Alternatively, try @PropertySources (extra s).

Application.java

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;

@SpringBootApplication
@PropertySources({
      @PropertySource("classpath:/server/db.properties"),
      @PropertySource("classpath:/server/file.properties")
})
public class Application implements CommandLineRunner {

  @Autowired
  private DatabaseProperties db;

  @Autowired
  private FileProperties file;

  //...
}

5. Placeholder ${}

Spring will resolve the ${app.home} by fetching the values from the system property or environment variable app.home.

file.properties

  file.path=${app.home}/server1/file/path

5.1 Set system property

We can set the app.home via the system property.

Terminal

  java -Dapp.home=/home/mkyong -jar spring-boot-app.jar

5.1 Default value

In addition, we can provide a default value for the placeholder ${}.

file.properties

  file.path=${app.home:defaultValue}/server1/file/path

6. Handle missing property file – ignoreResourceNotFound

If Spring can’t find the properties file, it prompts FileNotFoundException and fails to start the application.

Application.java

@SpringBootApplication
@PropertySource("classpath:missing.properties")
public class Application {
  //...
}
Terminal

Caused by: java.io.FileNotFoundException:
class path resource [missing.properties] cannot be opened because it does not exist

In @PropertySource, we can set ignoreResourceNotFound = true to ignore the missing properties file and continue to start the application.

Application.java

  @SpringBootApplication
  @PropertySource(value = "classpath:missing.properties", ignoreResourceNotFound = true)
  public class Application {
    //...
  }

7. Tests the @PropertySource

Read the comments for self-explanatory.

ApplicationTest.java

package com.mkyong;

import com.mkyong.config.DatabaseProperties;
import com.mkyong.config.FileProperties;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

// easy but load entire context, no good.
// @SpringBootTest

// Keep test in minimal configuration
@SpringJUnitConfig
public class ApplicationTest {

    @Autowired
    private DatabaseProperties dbServer;

    @Autowired
    private FileProperties fileServer;

    @BeforeAll
    public static void setUp() {
        System.setProperty("app.home", "/home/other");
    }

    @Test
    public void testFileServer() {
        assertEquals("/home/other/server1/file/path", fileServer.getPath());
    }

    @Test
    public void testDatabaseServer() {

        assertEquals("PostgreSQL", dbServer.getName());
        List<String> clusterIp = dbServer.getClusterIp();
        assertEquals(3, clusterIp.size());
        assertTrue(clusterIp.contains("127.0.0.1"));
        assertTrue(clusterIp.contains("127.0.0.2"));
        assertTrue(clusterIp.contains("127.0.0.3"));

    }

    // Mock Configuration within the test class
    @Configuration
    @PropertySource({"classpath:/server/db.properties",
        "classpath:/server/file.properties"})
    static class TestConfig {
        @Bean
        public DatabaseProperties dbServer() {
            return new DatabaseProperties();
        }

        @Bean
        public FileProperties fileServer() {
            return new FileProperties();
        }

        // supports List from .properties file.
        @Bean
        public ConversionService conversionService() {
            return new DefaultConversionService();
        }
    }

}

8. Download Source Code

$ git clone https://github.com/mkyong/spring-boot.git

$ cd spring-boot-externalize-config-3

$ mvn test

$ mvn spring-boot:run

9. References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
6 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Sai
8 years ago

Thanq so much for your post, it very help full.

I have a doubt in “2.@PropertySource and Environment” in this how to point to “Profile-specific application properties” ?

For Example, i have given Db details of Dev, QA and Prod in 3 property files as follows

application-dev.properties
application-qa.properties
application-prod.properties

and generic one application.properties file in this i have given “spring.profiles.active=dev”

But when i sued @PropertySource , its expecting application-dev.properties instead of application.properties file. can you tell me how to solve this.

Thanks,
Sai

Om Jai
8 years ago

Thanks for this example.
My requirement is the read the property file configured as URL resource in websphere 8. So instead of “classpath:config.properties” how can I refer to URL resource JNDI name??

According to the documentation here http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html I have to put “java:comp/env/”

Zoran I.
9 years ago

Just a note for anyone who wants to use yaml instead of regular property files. Yaml unfortunately can’t be loaded via @PropertySource Annotation. However, I added in property place holder configurer yaml property factory bean and loaded yaml that way and then set properties on the configurer. The @PropertySource was removed but the value were set the usual way. Dependencies were snakeyaml jar and spring boot.

Miral
9 years ago

Hi, looking forward for example, where we can use custom property resolver. e.g. I have third party system where all properties resides, need a way to tell spring boot to resolve all properties from my custom class that will read from other services. How to register custom property resolver to read props rather than reading from application.properties.

Maxi Wu
8 years ago

thank you. I want to ask, if the code is like @Value(“#properties[‘foo.bar’]}”) String arg0 inside @Controller constructor, what does this mean? how does this relate to your example here?

Rohit More
8 years ago

I afraid when I changed value in property file but @value annotation takes old value only. For accepting new changes it should reload the PropertySourcesPlaceholderConfigurer Bean. but stuck with this how to reload property file and initialize new values with the keys?