Skip to content
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

Document property source precendence using spring.config.import defined in application.yml vs adding as -Dspring.config.import #1838

Open
nagsuchandra opened this issue Mar 16, 2021 · 9 comments

Comments

@nagsuchandra
Copy link

nagsuchandra commented Mar 16, 2021

Describe the bug
When we add spring.config.import in application.yml of an application's src/main/resources vs the same property is added as -D parameter during the start up of the application, the behavior changes in terms of property order.

Sample
A test case is added namely ServerMyTestApplicationTests under spring-cloud-config/spring-cloud-config-sample/src/test/java (https://github.com/nagsuchandra/spring-cloud-config.git) and it's method contextLoads shows the issue. There is documentation added to the source file .

Error case:
application.yml has the following

spring:
  cloud:
    config:
      uri: http://localhost:${config.port:8888}
  config:
    import: configserver:${spring.cloud.config.uri}

Now if we run the test ServerMyTestApplicationTests.contextLoads, the property sources are as follows.

  • Config resource 'class path resource [application-baz.yml]' via location 'optional:classpath:/':{key=jarlocal-app-baz-yml}
  • configserver:file:././target/repos/configmytest-repo//payroll-baz.yml:{key=remote-payroll-baz-yml}
  • configserver:file:././target/repos/configmytest-repo//application-baz.yml:{key=remote-app-baz-yml}
  • configserver:file:././target/repos/configmytest-repo//payroll.yml:{key=remote-payroll-yml}
  • configserver:file:././target/repos/configmytest-repo//application.yml:{info.foo=bar}
  • Config resource 'class path resource [application.yml]' via location 'optional:classpath:/':{info.component=Config Samples, endpoints.restart.enabled=true, logging.levels.org.springframework.boot.env.PropertySourcesLoader=TRACE, logging.levels.org.springframework.web=DEBUG, spring.cloud.config.uri=http://localhost:${config.port:8888}, spring.config.import=configserver:${spring.cloud.config.uri}}

application.yml does NOT have the spring.config.import in there and -Dspring.config.import is passed in

  • configserver:file:././target/repos/configmytest-repo//payroll-baz.yml:{key=remote-payroll-baz-yml}
  • configserver:file:././target/repos/configmytest-repo//application-baz.yml:{key=remote-app-baz-yml}
  • configserver:file:././target/repos/configmytest-repo//payroll.yml:{key=remote-payroll-yml}
  • configserver:file:././target/repos/configmytest-repo//application.yml:{info.foo=bar}
  • Config resource 'class path resource [application-baz.yml]' via location 'optional:classpath:/':{key=jarlocal-app-baz-yml}
  • Config resource 'class path resource [application.yml]' via location 'optional:classpath:/':{info.component=Config Samples, endpoints.restart.enabled=true, logging.levels.org.springframework.boot.env.PropertySourcesLoader=TRACE, logging.levels.org.springframework.web=DEBUG}

Config data files ordering gets reversed if application.yml has spring.config.import defined in it , but -D maintains the ordering in the right precedence.

  1. Application properties packaged inside your jar (application.properties and YAML variants).
  2. Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants).
  3. Application properties outside of your packaged jar (application.properties and YAML variants).
  4. Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants). – highest priority
@nagsuchandra
Copy link
Author

#1839 ( Pull Request link )
The test ServerMyTestApplicationTests.contextLoads shows the issue , comments added.

@spencergibb spencergibb changed the title Application behavior changes between spring.config.import defined in application.yml vs adding that as -Dspring.cofnig.import Document property source precendence using spring.config.import defined in application.yml vs adding as -Dspring.cofnig.import Mar 16, 2021
@spencergibb
Copy link
Member

Spring cloud has no control over the precedence anymore, it is controlled by spring boot. IIRC @philwebb and I had a conversation about this and he said this is the working behavior of boot.

@maggmanu77
Copy link

maggmanu77 commented Mar 17, 2021

@spencergibb , there is no consistency in working behavior of boot then.
i.e.,

  1. class path resource [application-baz.yml] i.e., application-baz.yml local to jar is given precedence when spring.config.import is supplied via application.yml local to jar
  2. application-baz.yml from spring cloud config repo gets precedence when spring.config.import is supplied via system properties

latter is the best fit (abides by spring cloud documentation) logically - which should be made uniform irrespective of how spring.config.import is supplied.

@spencergibb
Copy link
Member

@philwebb will have to talk about that.

@maggmanu77
Copy link

@philwebb @spencergibb : this is not a documentation bug (it is incorrectly labelled so).
As illustrated, classpath:application-{profile-name} (local to jar) is overriding cloud config repo's application-{profile-name} which is incorrect.

@spencergibb
Copy link
Member

@maggmanu77 as I've said, spring cloud can only document this, I can't change the behavior. You'll need to file an issue in spring boot.

@spencergibb spencergibb changed the title Document property source precendence using spring.config.import defined in application.yml vs adding as -Dspring.cofnig.import Document property source precendence using spring.config.import defined in application.yml vs adding as -Dspring.config.import Mar 23, 2021
@spencergibb
Copy link
Member

Something else to consider in the documentation #1807 (comment)

@philwebb
Copy link

philwebb commented Apr 6, 2021

I've pushed something to Spring Boot that will allow imported ConfigData items to indicate that specific property sources should be considered "profile specific".

@jhitt25
Copy link

jhitt25 commented Feb 14, 2023

We started running into this recently when we finally started upgrading Spring Boot, and I believe the issue is slightly more involved than described. We are running on Spring Boot 2.7.4 and Cloud Config Server 2022.0.1 and we are experiencing different results depending on where we run the application from.

Basic setup: Application class files and application.yml are under /app

Example 1:
Our working directory is /app and we run java -cp . Main - spring.config.import cannot be in application.yml without breaking precedence (cloud config cannot override any properties specified in application.yml).

Example 2:
Our working directory is / and we run java -cp /app Main - spring.config.import can safely be included in application.yml and precedence works as expected (cloud config taking priority over all other settings)

I'm not sure if this is Cloud or Boot, but this is the only issue i still see open, so I started here. Is this something expected, or should I try fleshing out an example to provide?

Edit - further trace logging out of ConfigDataEnvironment makes me think this is definitely a boot issue. It appears that the application.yml is being read twice if it is both in your current directory and also your classpath (java -classpath .) and this is why spring.config.import fails to give Cloud Config precedence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants