Skip to content

Document precedence of property source with @ConfigurationProperties#locations #5111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vcetinick opened this issue Feb 8, 2016 · 10 comments
Assignees
Labels
type: documentation A documentation update
Milestone

Comments

@vcetinick
Copy link

I am experiencing some strange behaviour with spring boot when using @ConfigurationProperties on yaml files.

It seems that when i declare a pojo as follows and use config.yml to store my configuration settings
@ConfigurationProperties(location = 'config.yml', prefix='settings')

That my command line arguments are lower in precedence than the values inside the config.yml file. Reading the documentation i would expect that the Command line arguments are always higher.

However, when i declare a pojo as follows and use application.yml to store my configuration settings
@ConfigurationProperties(prefix='settings')

The command line arguments are higher in precedence.

Is that expected behaviour?

Github project (https://github.com/vcetinick/spring-boot-yaml-test)

I have written on stack overflow (http://stackoverflow.com/questions/35262664/spring-boot-configuration-behaviour-with-configurationproperties-and-command-li)

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Feb 8, 2016
@wilkinsona
Copy link
Member

It sounds like we need to clarify the documentation as this is working as designed.

When you specify one of more explicit locations for @ConfigurationProperties to use, the configuration loaded from those locations take precedence over anything that's already in the environment (from application.properties, System properties, environment variables, etc).

@wilkinsona wilkinsona added type: documentation A documentation update and removed status: waiting-for-triage An issue we've not yet triaged labels Feb 9, 2016
@wilkinsona wilkinsona added this to the 1.3.3 milestone Feb 9, 2016
@vcetinick
Copy link
Author

Perhaps it would be nice to introduce an attribute on configurationproperties to allow this behaviour to be overriden. At least in my case I just want to include this file as a configuration source and allow the default behaviour of the spring boot configuration to take over with overrides from the command line

@snicoll
Copy link
Member

snicoll commented Feb 11, 2016

@vcetinick that's not how you should do it then. That locations attribute is a real corner case in the configuration story in Spring Boot. If you want that file to participate in the environment "in the regular way", configure it accordingly.

@snicoll snicoll self-assigned this Feb 11, 2016
@snicoll snicoll changed the title Yaml Configuration behaviour with @ConfigurationProperties inconsistent when location attribute used Documentation precedence of property source with @ConfigurationProperties#locations Feb 11, 2016
@snicoll snicoll changed the title Documentation precedence of property source with @ConfigurationProperties#locations Document precedence of property source with @ConfigurationProperties#locations Feb 11, 2016
@vcetinick
Copy link
Author

Just a note on how I went down this path.

I have a multi module project and to keep my configuration dry, I want to keep each modules configuration isolated (by classpath) by uniquely naming each modules configuration i.e. database.yml inside a database.jar. This meant that the parent jar (the main application) would have its configuration defined the normal spring way in application.yml and would not compete with the child modules.

@magaton
Copy link

magaton commented Jun 21, 2016

@snicoll we share very same goals and problems with @vcetinick and I don't see the way out.
We tried these 2 ways, none seems to be good enough.

  1. Imagine that you have spring boot ProjectA with its own ProjectAConfigurationProperties and application.yml and spring-boot ProjectB which depends on ProjectA with ProjectBConfigurationProperties with its own application yml.
    If we don't copy the properties from ProjectA application.yml to ProjectB application.yml, properties from ProjectA will not be loaded when we start ProjectB.
  2. After reading many blog posts and SO questions, we changed the yml files to match project name: projectA.yml and projectB.yml and then load them with ConfigurationProperties by specifying locations. This caused another 2 problems:
  • we cannot override the properties neither with ENV variable nor with command line.
  • locations are deprecated in spring-boot 1.4

Note, that we have to use ConfigurationProperties since we rely on spring cloud config server in cloud environment, so we need to be able to change properties in real-time.

Can you suggest the optimal way to solve this problem?
Thanks,
Milan

@wilkinsona
Copy link
Member

I would use spring.config.name and/or spring.config.location. See the documentation for further details.

@magaton
Copy link

magaton commented Jun 21, 2016

Not sure I understand.
Where / when should we specify spring.config.name and/or spring.config.location?
Can you also please be more specific:

  • How should yml files be named in ProjectA and ProjectB which depends on ProjectA?
  • how should @ConfigurationProperties in ProjectA and ProjectB load these yml files?
    Thanks

@wilkinsona
Copy link
Member

wilkinsona commented Jun 21, 2016

Where / when should we specify spring.config.name and/or spring.config.location?

As the documentation states, you can configure them using System properties or environment variables. You can also pass them into your application as command line arguments or configure them as default properties on your SpringApplication.

How should yml files be named in ProjectA and ProjectB which depends on ProjectA?

By configuring spring.config.name, you can use any name you choose. For example, you could launch your app with -Dspring.config.name=projectA,projectB and name the files projectA.yml and projectB.yml

how should @ConfigurationProperties in ProjectA and ProjectB load these yml files?

@ConfigurationProperties doesn't load these yml files. The files that are identified by spring.config.name and spring.config.location are automatically read during startup and their configuration is added to the Environment. Any beans annotated with @ConfigurationProperties are then configured using the contents of the Environment.

@magaton
Copy link

magaton commented Jun 21, 2016

Thanks, clearly I can launch the apps with -Dspring.config.name=projectA,projectB.
But what about the tests in projectB? It seems like I cannot specify spring.config.name as a property in yml file, it has to be specified either as ENV var or command line param. ENV variable doesn't look attractive, since we are working on multiple projects. Is it then the only way to pass spring.config.name as runtime args of the surefire plugin or you have some better suggestion?

@wilkinsona
Copy link
Member

The only requirement is to get the configuration of spring.config.name into the Environment before your application is started. If you want a test-specific approach you could use @TestPropertySource.

This issue isn't really the right place to continue this discussion as we've gone way beyond the behaviour of @ConfigurationProperties' location attribute. I can recommend reading Spring Boot's documentation on externalised configuration and the documentation for Spring Framework's testing support. If you still have questions after reading those, Stack Overflow is a better place to ask. If you're looking for more of a discussion then we're also on Gitter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: documentation A documentation update
Projects
None yet
Development

No branches or pull requests

5 participants