Spring @PropertySource example
Spring default loads application.properties
into the application’s environment, and we can use @PropertySource
to load custom .properties
files.
file.path=/server1/file/path
@Configuration
@PropertySource("classpath:file.properties")
public class Application {
@Value("${file.path}")
private String path;
//...
}
Table of contents:
- 1. Project Structure
- 2. Properties Files
- 3. @PropertySource and @Value
- 4. Loads property files from multiple sources
- 5. Placeholder ${}
- 6. Handle missing property file – ignoreResourceNotFound
- 7. Tests the @PropertySource
- 8. Download Source Code
- 9. References
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
.
2. Properties Files
Below are two .properties
files for testing.
# Database
db.name=PostgreSQL
db.cluster.ip=127.0.0.1, 127.0.0.2, 127.0.0.3
# 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
.
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
}
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.
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
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.
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).
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.path=${app.home}/server1/file/path
5.1 Set system property
We can set the app.home
via the system property.
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.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.
@SpringBootApplication
@PropertySource("classpath:missing.properties")
public class Application {
//...
}
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.
@SpringBootApplication
@PropertySource(value = "classpath:missing.properties", ignoreResourceNotFound = true)
public class Application {
//...
}
7. Tests the @PropertySource
Read the comments for self-explanatory.
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
- SpringDoc – PropertySource
- SpringDoc – PropertySources
- SpringDoc – Configuration
- Spring Boot – Externalized Configuration
- Testing JSON in Spring Boot
- Spring Boot @ConfigurationProperties example
- Access values from application.properties in Spring Boot
- Spring @Value default values
- How to load custom properties files in Spring Boot
- Java Properties file examples
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
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/”
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.
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.
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?
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?