Skip to content

Config file same key overriding order/precedence bug #2205

@blackr1234

Description

@blackr1234

Describe the bug

Library versions

  • Spring Boot 2.7.1
  • Spring Cloud 2021.0.3
  • Spring Cloud Config 3.1.3 (managed)

Issue

I have a minimal Spring Cloud Config setup with Git backend using a GitHub public repo.

I deliberately put properties of the same keys in multiple config files to test the behavior of Spring Cloud Config in resolving config values.

These are the types of my config files:

  1. application.yaml
  2. {spring.application.name}.yaml
  3. application-{profile}.yaml
  4. {spring.application.name}-{profile}.yaml

My expectation is, values in profile-specific files should override values in files of the default profile.
The overriding order should be "similar" to the order of the above ordered list, so if the exact same property key exists in all 4 files, the final value should come from the last one (the 4th list item).

However, the actual result is as follows:

  1. application-{profile}.yaml
  2. {spring.application.name}-{profile}.yaml
  3. application.yaml
  4. {spring.application.name}.yaml

From the Spring Cloud Config official doc, it says:

If there are profile-specific YAML (or properties) files, these are also applied with higher precedence than the defaults. Higher precedence translates to a PropertySource listed earlier in the Environment. (These same rules apply in a standalone Spring Boot application.)

Reference: https://docs.spring.io/spring-cloud-config/docs/3.1.3/reference/html/

As it says the behavior should be the same as standalone Spring Boot, the Spring Boot official doc says:

Config data files are considered in the following order:

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

Reference: https://docs.spring.io/spring-boot/docs/2.7.1/reference/htmlsingle/#features.external-config

From my testing with config files within the Spring Cloud Config Client application (under src/main/resources), it works fine and this is the overriding order:

  1. application.yaml
  2. application-{profile}.yaml

The value comes from the 2nd file.


Sample

Project source code and config files can be found in my public Git repos:

Test command and environment

The command for starting the 2 projects in local:

mvn spring-boot:run

Results of Maven version command (mvn -v):

Apache Maven 3.8.6 (84538c9988a25aec085021c365c560670ad80f63)
Maven home: C:\maven
Java version: 11.0.17, vendor: Azul Systems, Inc., runtime: C:\zulu11
Default locale: en_US, platform encoding: MS950
OS name: "windows 11", version: "10.0", arch: "amd64", family: "windows"

Explanation of the code

It is a minimal Spring Cloud Config setup with Git backend using a GitHub public repo. I have 4 config files that are named with the aforementioned naming conventions.

The active Spring profile is dev only.

Test config properties:

  • my.prop is for manual testing, by removing the greatest value one by one, I am able to find out the order of config overriding in Spring Cloud Config. Current output value should be 4 which comes from the application config file of the default profile (spring-cloud-config-client-demo.yaml).
  • my.prop2 is for proving that the overriding order in config files within the project code are working fine. Current output value should be 2.
  • order-test.* is for proving this bug. There are 4 properties in total. Values are simply the name of the config files and these files have 1~4 properties, so we can tell which files "win" in overriding. If you run the config client application, you will see from the log that all 4 properties have unique values and thus the aforementioned order is the only possible order. The class ConfigFileLoadOrderTestConfig.java contains Hiberate Validator annotations to validate the config values automatically. Error will be thrown if values do not match and the application will terminate.

Log

(I added newlines below for readability)

order-test object: ConfigFileLoadOrderTestConfig(
loadOrder01=application-dev.yaml,
loadOrder02=spring-cloud-config-client-demo-dev.yaml,
loadOrder03=application.yaml,
loadOrder04=spring-cloud-config-client-demo.yaml
)
my.prop: 4
my.prop2: 2

My thought

The official documentation isn't very clear as it lacks examples. Perhaps my understanding of "higher precedence" is wrong but apparently the behavior in Spring Cloud Config (at least the Git implementation) does not match the behavior of reading config files within src/main/resources in the project.

If A has a "higher precedence" than B, then I will expect that A gets applied but not B. In other words, A "wins".

Last but not least, if this is a known issue in some old versions of Spring, please provide the corresponding issue details and let me know the status of fix.

If you are also facing this issue or think that my issue is valid, I'd appreciate if you could provide quick feedback with👍 or ❤️ on this issue post.

Thanks a lot everyone and have a wonderful year ahead!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions