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

Comment From: nagsuchandra

https://github.com/spring-cloud/spring-cloud-config/pull/1839 ( Pull Request link ) The test ServerMyTestApplicationTests.contextLoads shows the issue , comments added.

Comment From: spencergibb

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.

Comment From: maggmanu77

@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.

Comment From: spencergibb

@philwebb will have to talk about that.

Comment From: maggmanu77

@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.

Comment From: spencergibb

@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.

Comment From: spencergibb

Something else to consider in the documentation https://github.com/spring-cloud/spring-cloud-config/issues/1807#issuecomment-810579138

Comment From: philwebb

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

Comment From: jhitt25

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.