moffeltje
moffeltje

Reputation: 4658

Why is @PropertySource not used when application.properties is present?

The situation I'm in requires a file with some properties (eventually containing a list of ID's and Email addresses) to be mapped to a HashMap. In Spring I found that a properties file can be mapped to an object with @ConfigurationProperties and @PropertySource. To test this mechanism, I created a test project, but @PropertySource seems to be ignored when default application.properties file exists. I'm wondering how this is possible and how I can solve it so that it uses the properties file specified.

Application.java

@SpringBootApplication
@EnableConfigurationProperties
public class Application {

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

DemoProperties.java

@Component
@Configuration
@ConfigurationProperties("test")
@PropertySource("classpath:test.properties")
public class DemoProperties {
    private String name;

    public String getName() {
        return name;
    }

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

test.properties

test.name=myNameGood

application.properties

test.name=myNameBad

ApplicationTests.java

@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {

    @Autowired
    DemoProperties demoProperties;

    @Test
    public void contextLoads() {
        System.out.println(demoProperties.getName());
    }

}

So this Test prints myNameBad when application.properties is present, but when I delete or rename that file, the output is myNameGood (which is desired).

Upvotes: 2

Views: 4473

Answers (1)

davidxxx
davidxxx

Reputation: 131346

Properties coming from the default locations (here application.properties) has higher priority as custom properties used in a class.

From the Spring Boot documentation :

72.3 Change the location of external properties of an application

A nice way to augment and modify this is to add @PropertySource annotations to your application sources. Classes passed to the SpringApplication static convenience methods, and those added using setSources() are inspected to see if they have @PropertySources, and if they do, those properties are added to the Environment early enough to be used in all phases of the ApplicationContext lifecycle. Properties added in this way have lower priority than any added using the default locations (e.g. application.properties), system properties, environment variables or the command line.

And this priority makes sense as configuration that you can provide at the runtime (such as application.properties) should always be able to override configuration "hardcoded" in the application.


To test this mechanism, I created a test project,

To test a class or a behavior, you should rather write a unit test.
You could so use one of these way to override application.properties values:

  • Renaming test.properties into application.properties and moving it into src/test/resources.

  • using @TestPropertySource. From the javadoc :

Test property sources have higher precedence than those loaded from the operating system's environment or Java system properties as well as property sources added by the application declaratively via @PropertySource or programmatically

Upvotes: 4

Related Questions