Skip to content

Profile-specific property files are incorrectly ordered when both '.' and './config' folders are used in the same application #26593

@focdanisch

Description

@focdanisch

Hello,

when upgrading our application from 2.3.0.RELEASE to spring boot 2.4.5, I realised that spring boot now sorts the application*.properties files in a different order. I was reading the upgrade documentation for 2.4.x, but as far as I understand it, we should not have to make any adjustments in our configuration. Furthermore, the sort order I see does not match your documented behaviour. Quote from here: https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-files-profile-specific

Profile-specific properties are loaded from the same locations as standard application.properties, with profile-specific files always overriding the non-specific ones. If several profiles are specified, a last-wins strategy applies. For example, if profiles prod,live are specified by the spring.profiles.active property, values in application-prod.properties can be overridden by those in application-live.properties.

I created a small spring boot project from your initial sample project (git clone https://github.com/spring-guides/gs-spring-boot.git) from the gs-spring-boot/initial folder. You can find it here: https://github.com/focdanisch/spring-boot-properties-order

As we are using maven as our build system, I only built the test project with maven. I changed the following things: I added two modules and switched the parent pom.xml to pom packaging. module1 only contains a collection of application*.properties in src/main/resources:

config/application-config.properties
config/application-local.properties
application.properties
application-root.properties

module2 has another collection of application*.properties:

in src/main/resources:

application.properties
application-local.properties

in config folder under root:
application-local.properties

application.properties defines the active profiles as local,config,root. According to your documentation, application-root.properties must win.

In module2 under src/test/resources is a junit test class (TestProfileSpecificOrder) which passes with 2.3.10.RELEASE (I used the latest 2.3.x version for the test) and fails with 2.4.5 (you can easily switch the versions in the root pom, I left both version tags in the file). The test class contains two tests:

For the first test,

@Value("${test.prop}")
String testProp;

is injected, and it is simply checked if the value of this property is "root" (which must be that way, as application-root.properties must win).

For the second test, the environment gets injected:

@Autowired
Environment environment;

With 2.3.10.RELEASE, I see this order of propertySources (when I import the project into Eclipse and put a breakpoint at the beginning of the method):

ConfigurationPropertySourcesPropertySource {name='configurationProperties'}
MapPropertySource {name='Inlined Test Properties'}
PropertiesPropertySource {name='systemProperties'}
OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}
RandomValuePropertySource {name='random'}
OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application-root.properties]'}
OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/config/application-config.properties]'}
OriginTrackedMapPropertySource {name='applicationConfig: [file:./config/application-local.properties]'}
OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/config/application-local.properties]'}
OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application-local.properties]'}
OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.properties]'}

which seems correct and matches your documentstion. The properties are primarily sorted by the active profiles, and secondarily by classpath/file. Spring searches properties from specific to general, so the result is correct.

With 2.4.5, I see this order:

ConfigurationPropertySourcesPropertySource {name='configurationProperties'}
MapPropertySource {name='test'}MapPropertySource {name='Inlined Test Properties'}
PropertiesPropertySource {name='systemProperties'}
OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}
RandomValuePropertySource {name='random'}
OriginTrackedMapPropertySource {name='Config resource 'file [config\application-local.properties]' via location 'optional:file:./config/''}
OriginTrackedMapPropertySource {name='Config resource 'class path resource [config/application-config.properties]' via location 'optional:classpath:/config/''}
OriginTrackedMapPropertySource {name='Config resource 'class path resource [config/application-local.properties]' via location 'optional:classpath:/config/''}
OriginTrackedMapPropertySource {name='Config resource 'class path resource [application-root.properties]' via location 'optional:classpath:/''}
OriginTrackedMapPropertySource {name='Config resource 'class path resource [application-local.properties]' via location 'optional:classpath:/''}
OriginTrackedMapPropertySource {name='Config resource 'class path resource [application.properties]' via location 'optional:classpath:/''}

So it sorts by classpath/file, then by root folder/config folder, and then by active profiles. That seems wrong to me, as this way, the file [config\application-local.properties] overwrites everything else, even though "local" is the first in the active profiles list and therefore should be overriden by [config/application-config.properties] as well as [application-root.properties]. Also, the remaining properties are not ordered correctly, as the files should be listed in the reverse order of the active profiles, so all application-root.properties files should be on top, followed by all all application-config.properties files, followed by all application-local.properties files.

Our application is dependent on a working last win strategy. We could theoretically combine some of the separate property files into one of the new multi-property-files, but not all of them. Our application has not only two, but a lot of maven modules, and some of them must be able to override or even add additional profile specific property files, and the active profiles setting allows us to specify the correct order.

Am I missing something here? Is there something I have misunderstood in your upgrade guide? Or is this now intended behaviour with 2.4.5 (in that case, the documentation would be incorrect)?

Best regards,
Manuel

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions