Describe the bug
After I upgraded spring cloud config server from version 2.3.10 to 2.4.5 the order in which properties files are processed changed. Before the upgrade properties from profile specific files, e.g. {application}-{profile}.properties
, had precedence over general files like {application}.properties
, and after the upgrade it is the opposite.
I am using cloud config server with spring.cloud.config.server.git.searchPaths
option set to '**'
so that I can have properties files structured in directories, like this:
- dir1/{application}.properties
- dir1/dir2/{application}-{profile}.properties
I also checked this with v2.4.7-SNAPSHOT and it is the same there
Sample
I created a simple cloud config server based on https://start.spring.io/
code generated . Set the content of application.properties
to
spring.cloud.config.server.git.uri: https://github.com/grabarczyk-t/cloud-config-test.git
spring.cloud.config.server.git.searchPaths: '**'
In the git repository I have two property files:
project/application.properties
project/test/application-test.properties
both with just one property sample.property
, with different value in each file. When I run the server locally and make request to http://localhost:8080/application/test
I get:
In the 2.3.10
version:
{"name":"application","profiles":["test"],"label":null,"version":"32248076b1c298d26c0f4afc9f6464f0e452e18f","state":null,"propertySources":[{"name":"https://github.com/grabarczyk-t/cloud-config-test.git/project/test/application-test.properties","source":{"sample.property":"value from application-test.properties"}},{"name":"https://github.com/grabarczyk-t/cloud-config-test.git/project/application.properties","source":{"sample.property":"value from application.properties"}}]}
In the 2.4.5
version:
{"name":"application","profiles":["test"],"label":null,"version":"32248076b1c298d26c0f4afc9f6464f0e452e18f","state":null,"propertySources":[{"name":"https://github.com/grabarczyk-t/cloud-config-test.git/file:C:\\Users\\Tom\\AppData\\Local\\Temp\\config-repo-14384905862201453365\\project\\application.properties","source":{"sample.property":"value from application.properties"}},{"name":"https://github.com/grabarczyk-t/cloud-config-test.git/file:C:\\Users\\Tom\\AppData\\Local\\Temp\\config-repo-14384905862201453365\\project\\test\\application-test.properties","source":{"sample.property":"value from application-test.properties"}}]}
I also checked it with a simple cloud config client application. I have profile set to test
(spring.profiles.include=test
), and when I check the value of this property using @Value
:
@Value("${sample.property}") private String sampleProperty;
the sampleProperty
has the value from application-test.properties
when the 2.3.10 config server is running, and value from the application.properties
when the 2.4.5
config server is running
Comment From: ryanjbaxter
Can you provide a complete, minimal, verifiable sample that reproduces the problem? It should be available as a GitHub (or similar) project or attached to this issue as a zip file.
Comment From: grabarczyk-t
Yes, sure. I uploaded zip file with code that reproduces this problem. After unzipping the file enter the CloudConfigServer
directory and run mvnw spring-boot:run
, this will run cloud config server. Then do:
curl http://localhost:8080/application/test
this will return similar output that I described in the issue description, and it shows that the propertySources are in wrong order - property source for application.properties
file is before property source for application-test.properties file
and it should be the other way around
Comment From: ryanjbaxter
I think this is due to the way Spring Boot is ordering property sources and profile specific property sources not taking precedence. See https://github.com/spring-projects/spring-boot/issues/26593
Comment From: philwebb
I've applied a change that should fix https://github.com/spring-projects/spring-boot/issues/26593 but we'll probably also need a change in Spring Cloud. The ordering change was actually intentional (see https://github.com/spring-projects/spring-boot/issues/3845) but we overlooked that as well as inside and outside the jar we also have ./
and ./config
to consider. To deal with that I've update the code so that a spring.config.location
entry can contain multiple files or directories. Spring Boot now uses the following:
optional:classpath:/;optional:classpath:/config/,optional:file:./;optional:file:./config/;optional:file:./config/*/
This is defining two location groups (one for the classpath in the jar and one for files outside of the jar). The groups themselves define the actual locations.
I suspect that this part of the code will need to change to build the correct location string. Perhaps replacing arrayToCommaDelimitedString(...)
with delimitedListToStringArray(..., ";")
?
Comment From: ryanjbaxter
Thanks @philwebb. Yeah that is one place that we need to change. But also this logic is no longer valid
https://github.com/spring-cloud/spring-cloud-config/blob/b1e795d8d191c04d1221ab88a30a6b2f431bba7f/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java#L256
A ConfigDataLocation
now contains a list of locations instead of just a single location. Probably need to wrap that logic in a loop of some kind. I see ConfigDataLocation
now has a split
method to get an array delimited by ;
, I can probably use that.
I plan on looking at this more tomorrow.