Spring @PropertySource

If you are a Spring developer and and you have created a Java based container configuration, you have probably come across the @PropertySource annotation for importing resources. It was first added as part of Spring 3.1, but Spring 4 has added some welcome improvements.

Basics

Let’s start with a simple example:

@Configuration
@PropertySource(value = "classpath:application.properties")
public class ApplicationConfig {

    // more configuration ...
}

When executed, properties will be imported from the application.properties file, located in the classpath root. classpath is the default location, and can thus be omitted:

@Configuration
@PropertySource("application.properties")
public class ApplicationConfig {
}

Alternatively, it is possible to specify a file: location to appoint a properties file that is located elsewhere on your host environment:

@PropertySource("file:/path/to/application.properties")

Other possible resource strings include http: and ftp:, please see the Resource chapter in the Spring reference documentation for details.

Multiple Properties Files

It is also possible to specify two or more files:

@PropertySource({"default.properties", "overriding.properties"})

Note that the order of the declared files is important. If the same key is defined in two or more files, the value associated with the key in the last declared file will override any previous value(s).

${…} Placeholders

In the @PropertySource JavaDoc it is stated that:

Any ${…} placeholders present in a @PropertySource resource location will be resolved against the set of property sources already registered against the environment.

Thus, it is possible to specify a system property or an environment variable that will be resolved to its actual value when your application starts. For example, ${CONF_DIR} below will be replaced with its associated value when the Spring application starts:

@PropertySource("file:${CONF_DIR}/application.properties")
$ echo $CONF_DIR
/path/to/directory/with/app/config/files

Of course, you can let the file name be included in the environment variable:

@PropertySource("file:${APP_PROPERTIES}")
$ echo $APP_PROPERTIES
/path/to/application.properties

This approach can be very useful if your application needs different properties in different environments, such as client vs. server deployment, Linux vs. Windows target operating system and so on.

Spring 4

Spring 4 brings two new features to the @PropertySource. The first new feature deals with missing files. By default, Spring will throw an exception if it does not find the file that has been declared. Given a project that does not contain a missing.properties file, but has the following declaration:

@PropertySource(value = "missing.properties")

If one attempts to start the application anyway, there will be a stacktrace accordingly:

java.lang.IllegalStateException: Failed to load ApplicationContext
[...]
Caused by: java.io.FileNotFoundException: class path resource [missing.properties] cannot be opened because it does not exist

To overcome this problem, the ignoreResourceNotFound attribute has been added to the @ProperySource annotation. Consequently, the declaration:

@PropertySource(value = "missing.properties", ignoreResourceNotFound = true)

will cause Spring to silently ignore that the missing.properties file cannot be found. This may seem odd at first, if one does not care about the absent file, then why bother to declare it the first place? As will be explained later, there is a very good reason for this.

Secondly, there is a new annotation called @PropertySources that allows you to declare repeated @PropertySource annotations:

@PropertySources({
    @PropertySource("default.properties"),
    @PropertySource("overriding.properties")
})

Yet again, the order of the property file declarations is important. As suggested by the file names in the example above, files declared later will override any previous value(s) if they contain the same key(s).

Putting It Together

To summarize, a property source configuration can be implemented like:

@Configuration
@PropertySources({
    @PropertySource("default.properties"),
    @PropertySource(value = "file:${CONF_DIR}/optional-override.properties", ignoreResourceNotFound = true)
}
public class ApplicationConfig {
}

The default.properties file is part of the project jar or war file, and consequently availible on the classpath. However, now we can see that the addition of the ignoreResourcesNotFound attribute allow us to optionally override one or more of the properties depending on the deployment environment. Additionally, the use of file and the ${...} placeholder enable a configurable location of this optional properties file.
For the record, it is possible to conditionally import properties files in earlier Spring versions as well using placeholders and :, but then it was an either / or inclusion on file level. Prior to Spring 4, you were forced to copy all properties to the overriding file even if you only had the need of overriding a single property value. See the JavaDoc for details.

Java 8

When you migrate update to Java 8, the @PropertySources annotation will be redundant, because Java 8 will support repeating annotations:

@Configuration
@PropertySource("default.properties")
@PropertySource(value = "file:${CONF_DIR}/optional-override.properties", ignoreResourceNotFound = true)
public class ApplicationConfig {
}

Edit

In the earlier version of Spring 4, i.e. versions below 4.0.2, an exception will be thrown if a placeholder such as the ${CONF_DIR} above cannot be resolved, despite that ignoreResourceNotFound attribute has been set to true. SPR-11524 addresses this issue, and a solution is scheduled to be released as part of the 4.0.3 version.

References

Mattias Severson

Mattias is a senior software engineer specialized in backend architecture and development with experience of cloud based applications and scalable solutions. He is a clean code proponent who appreciates Agile methodologies and pragmatic Test Driven Development. Mattias has experience from many different environments, including everything between big international projects that last for years and solo, single day jobs. He is open-minded and curious about new technologies. Mattias believes in continuous improvement on a personal level as well as in the projects that he is working on. Additionally, Mattias is a frequent speaker at user groups, companies and conferences.

This Post Has 41 Comments

  1. Murphree

    Great article, I was unsure about the ${…} placeholders feature in @PropertySource, glad to know that this works!

  2. Howdy! This is my first visit to your blog! We are a group of volunteers and starting a new initiative in a community in the same niche.
    Your blog provided us beneficial information to work on.

    You have done a outstanding job!

  3. Spyro

    This is the most complete blog post I’ve ever seen!! It helped me with placeholder exception. Also it made me think about moving to Java 8 since multiple annotations are supported.

    Thanks!

  4. Boris Tarasov

    Thanks for the article. Made my day.

  5. Mark

    Does “file:/path/to/application.properties” works?
    For me, it does not work but file:///path/to/applicaiton.properties works.
    Am I misunderstanding?

    1. Mattias Severson

      @Mark: Thank you for your question. Up to and including Spring version 4.0, the file:/path/to/application.properties (with a single slash) was the standard way of defining a file system resource string as stated in the Spring Reference Docs. As of Spring version 4.1, the documentation has been updated to file:///path/to/application.properties (triple slashes). That said, I believe that both the file: resorce string prefix, as well as the file:// resource string prefix (the last / is not part of the prefix, it is the root of the file system) work in both versions.

      Please double check the name of the properties file, you have misspelled applicaiton.properties in your question (and perhaps also in your source code).

  6. v.a.k

    Hi
    thanks for the wonderful post
    Is it possible in Spring 4 that the application.properties and/or application.yaml will be loaded dynamically during runtime. Meaning, I don’t want to rerun the JVM in order to get up-to-date properties’ values in case I need to change some properties values (for example, I want to change some scheduling data that I set as a property)

    tnx

      1. Daniel Wind

        @Mattias
        Thanks for posting such an informative article, it’s pretty concise and well written.

        @v.a.k
        Another solution for dynamic runtime configuration loading is https://commons.apache.org/proper/commons-configuration/ which integrates pretty well with spring. You basically define a bean with the reloadingStrategy property (xml sample below). With these approach, you can change a property’s value in runtime and the application will read it immediately.

        file:/Users/dw/config/app.properties

        and you use it in your class as:

        @Component
        public class ExternalProperties {

        @Autowired
        PropertiesConfiguration externalConfig;

        public String getSomeConfigValue() {
        return externalConfig.getString(“someconfig”);
        }

  7. alexey nesterov

    Great article, short and clear, as definition.

    Thank you, bro!

  8. chaitanya

    Awesome article. Thanks a lot :)

  9. Nestor Moreno

    Thanks, perfect solution!

  10. Ramana Reddy

    I am trying to use one of the environment variable in PropertySource annotation. It is throwing could not resolve place holder CONFIG_PATH error.

    Please help me.

  11. Vikas

    Awesome Post. Very clear explanation of PropertySource.

    Thanks,
    Vikas

  12. sne

    thanks for info….

  13. Dylan

    Can JNDI from embedded Tomcat fit in with ${..}? I am having trouble getting that to work.

  14. Mahesh Babu

    Does @Propertysource support YML file to load fields

  15. Saravanan S

    Great Article.
    Is there any way we can load locale specific properties file here ?
    For example: message_en_US.properties or message_es_US.properties ?
    Thanks.

    1. Mattias Severson

      @Saravanan: Thanks. If you need different property files for translation support (which I guess is the case since you have added a full locale, i.e. both language and country codes to you example) you can fall back to standard Java, see the Internationalization tutorial, specifically about ResourceBundle.

      Additionally, you can take a look at Spring Boot’s Profile Specific Properties for different configurations options not related to translations.

  16. Griffin Tom

    Great article, Mattias.

    Adding property names to annotation “@ProperySources({…})” would work well when there are a handful of files. But in large production-like projects/environments, there could be many more files. Additionally, if you want to list base files, as well as, environemt specific files then the list could get really long. Such example would be,
    @ProperySources({
    “/base/file1.properties”,

    “/base/file10.properties”,
    “/{env}/file1.properties”,

    “/{env}/file10.properties”
    })

    Is there a cleaner approach to this? Wildcard property would have been the perfect solution here, since it’s not supported do you have a better idea to solve this?
    Thank you in advance, Mattias.

    1. Mattias Severson

      @Tom: Thank you for your question.

      First I would consider to use a single property file and keep all properties there. Especially if your application is based on micro service, one property file per micro service makes sense IMHO.

      For traditional large, n-tier projects I typically create one @Configuration class for each purpose. For example, there could be a WebConfig class (that among other things contains @EnableWebMvc), a PersistenceConfig for database related stuff, a SecurityConfig that deals with Spring Security beans and configuration, etc. In these cases, I include a @PropertySource("web.properties"), @PropertySource("persistence.properties") and a @PropertySource("security.properties") in each config class respectively (if necessary).

      However, nowadays you typically divide your application in components rather than layers (i.e. you slice the architecture in vertical slices instead of horizontal layers). In that case, I adopt the config classes and property files accordingly, e.g. an e-commerce platform could include files such as LoginConfig.java, CatalogConfig.java and PaymentConfig.java. Consequently, the property files would have corresponding names login.properties, catalogue.properties, payment.properties etc.

  17. Santosh kumar

    Hi I am working on spring boot on there are different module in project i want to pass properties file from one main module to efferent module. i am using @PropertySource to read properties file?

    1. Mattias Severson

      @Santosh: For large, multi-module project, my advice is to use separate properties files for separate modules. The main reason is to preserve separation of concerns (after all, that is why you created separated modules in the first place). That said, for smaller projects it can also make sense to put all properties in a single file, especially if it only contains a few properties.

  18. Jaswanth

    I am reading message.properties from config server as @PropertySource(“http://ConfigserverUrl/messages.properties” ).
    But the properties are not getting updated whenever I change in the config-repo. I have to restart the app everytime to see those changes.
    Is there a way that config server updates those values immediately whenever we update in the config-repo without making the app to restart.

    1. Mattias Severson

      @Jaswanth: Yes, that is correct. Spring Beans are stateful Java objects that will only get their configuration injected when they are initialized, unless given additional privileges. Please read the Refresh Scope paragraph in the Spring Cloud documentation for more information. Additionally, you can implement a working example by studying the Centralized Configuration Spring Guide.

  19. Jaswanth

    Great! Thanks! I have read the documentation and tried to implement it. When I add @RefreshScope to the @Component class which have error messages . It is not getting those properties after hitting /actuator/refresh endpoint.

    I am getting the values of these messages from config-repo (@PropertySource(“http://ConfigserverUrl/messages.properties” )) which is defined in a controller class. After hitting the /actuator/refresh endpoint will it again load properties from @PropertySource?

    1. Mattias Severson

      @Jaswanth: Yes, I believe so. However, I have not played with the property reload feature in practice, so I am afraid I cannot assist you further.

  20. Goldest

    I am using Spring Boot and have the default application.properties file. I don’t really use @PropertySource to load the properties file. It gets detected by Boot automatically and I can still use @Value annotation to read the properties inside it. So what exactly will be the situation when I will need to use @PropertySource while working on Spring Boot project?

    1. Mattias Severson

      @Goldest: @PropertySource is part of Spring Framework and not Spring Boot. Consequently, if you are not using Spring Boot (like in this blog post), you cannot rely on Spring Boot’s default behaviour such as relying on the application.properties for externalized configuration. Moreover, it is not unusual that an application relies on other sources of configuration (i.e. you fetch your properties from disk, an external service, environment variables, etc) and the @PropertySource is one of the tools for making this possible. Please read the Externalized Configuration chapter in the Spring Boot documentation for Spring Boot configuration options and the overriding rules or the Spring Cloud Config if you need a central place for managing external properties for applications across different environments.

  21. Michel

    Great article! Very clear! Thank you.

    I am using @PropertySource in Spring boot application.
    I have multiple microservices that using a MongoConfiguration class for Mongo configuration:

    @PropertySource(“classpath:/mongo-${env}.properties”)
    public class MongoConfiguration

    However I am externalizing the config files to a Spring Cloud Config server.
    This works well for application.yml files.
    However I can’t make it work with those other config files like mongo-env.properties.

    Is @PropertySource compatible with Spring Cloud Config (I am using Git as the external data source)

    1. Lakshman

      Hi, I am facing same here. Did you get through this issue?

Leave a Reply