Spring-boot: External config file not overriding bundled profile configs

Created on 15 Feb 2016  Â·  4Comments  Â·  Source: spring-projects/spring-boot

I'm using 1.3.2.
I am experiencing a strange issue with regard to standard configuration files, profiles, and external files set with spring.config.location. I'm not really sure I understand the interplay correctly so maybe this is intended behavior.

(The setup described below might seem a bit silly and is not my actual setup, but it is the easiest configuration of settings that allows me to reproduce the issue.)

I have an application which has a resource in the classpath root called application-profileA.properties. Then, I start the application (packaged into a fat jar) and set the profile to profileA and define external configuration, like this:

java -Dspring.profiles.active=profileA -Dspring.config.location=/full/path/to/application-external.properties -jar app.jar

(using --sprint.profiles.active and --spring.config.location doesn't change anything)

When the application starts, I see that the external file is not overriding the properties of the bundled properties file causing my application to fail startup. Here are a few logging statements that I see:

Activated profiles profileA
Loaded config file 'file:/full/path/to/application-external.properties'
(a bunch of 'skipped' files)
Loaded config file 'classpath:/application-profileA.properties'
Skipped (empty) config file 'classpath:/application-profileA.properties' for profile profileA

What is also strange is that once the application-profileA.properties file is loaded, and then another time is is skipped as being empty.

When I don't set a profile, and change the name of the bundled file to application-default.properties (since the 'default' profile is used by default), the same error exists, with log output changed correspondingly:

No active profile set, falling back to default profiles: default
Loaded config file 'file:/full/path/to/application-external.properties'
(a bunch of 'skipped' files)
Loaded config file 'classpath:/application-default.properties'
Skipped (empty) config file 'classpath:/application-default.properties' for profile default

Note also the final log line avobe, seems strange.

When I change the bundled file to application.properties and do not activate any profile, it works the way I would expect it to, which makes me think there might be something wrong with regard to profile-related files. However, the log output is still strange (I mean the final line, this time it reports the external file as being empty for profile 'default'):

No active profile set, falling back to default profiles: default
Loaded config file 'file:/full/path/to/application-external.properties'
(a bunch of 'skipped' files)
Loaded config file 'classpath:/application.properties'
Skipped (empty) config file 'file:/full/path/to/application-external.properties' for profile default

What my expectation are: when I start the application by activating 'profileA' and also specifying the external location, the bundled file application-profileA is used, and than the external file is used and is able to override the settings in the bundled file.

Are my expectations wrong and is what I'm seeing correct, intended behavior when profile-related files come into play?

documentation

Most helpful comment

Oh, it wasn't at all clear to me that files specified with the spring.config.location were also profile-enabled

They are as long as you either specify a directory (rather than a specific .properties file), or a YAML file that contains multiple profiles.

Sorry, but I can't get a clear answer from the documentation, maybe it's the fact I'm not a native speaker.

I think it's much more likely that the documentation is unclear. It currently says:

If spring.config.location contains directories (as opposed to files) they should end in / (and will be appended with the names generated from spring.config.name before being loaded)

And then goes on to say:

In addition to application.properties files, profile-specific properties can also be defined using the naming convention application-{profile}.properties. … Profile-specific properties are loaded from the same locations as standard application.properties, with profile-specific files always overriding the non-specific ones irrespective of whether the profile-specific files are inside or outside your packaged jar.

At the very least, I think this could be improved by describing what happens when spring.config.location points to a specific .properties file rather than a directory. If you have other suggestions on how we could improve things, please let us know.

The log output is a bit misleading and strange

Agreed. All three lines you've listed are misleading or not as informative as they could be.

Loaded config file 'file:./application-profileA.properties'

This is saying that profileA is active and, therefore, the profile-specific file application-profileA.properties has been loaded.

Skipped (empty) config file 'file:./application-profileA.properties' for profile profileA
Skipped (empty) config file 'file:./application.properties' for profile profileA

Both of these lines are actually saying that .properties files don't support multiple profiles in the same file.

The misleading logging is an unfortunate side-effect of it being performed in a generic location that doesn't (and shouldn't) understand the difference between .properties and .yaml configuration files.

All 4 comments

When you configure a custom config location, those locations take precedence over the default locations for each individual property source. The ordering of those property sources is described in the documentation. For example, a profile-specific file in a custom location will take precedence over a profile-specific file in a default location, but a profile-specific file in one of the default locations will still take precedence over a normal application properties file in a custom location.

When the application starts, I see that the external file is not overriding the properties of the bundled properties file causing my application to fail startup

As the bundled properties file is profile-specific it takes precedence over the normal application properties file in the custom location.

However, the log output is still strange (I mean the final line, this time it reports the external file as being empty for profile 'default'):

That log message could be worded a little better, I think. What it's trying to tell you was that there was no profile-specific variant of the application-external.properties file. We can use this issue to make an improvement there.

To summarise:

What my expectation are: when I start the application by activating 'profileA' and also specifying the external location, the bundled file application-profileA is used, and than the external file is used and is able to override the settings in the bundled file.

Are my expectations wrong and is what I'm seeing correct, intended behavior when profile-related files come into play?

I think your expectations are wrong. As listed in the documentation profile-specific files take precedence over normal application properties files. Configuring custom locations doesn't change the overall ordering, it just changes the ordering for each individual source so, for example, an application-specific properties file in a custom location will override an application-specific properties file in a default location.

I think we can probably make this clearer in the documentation, so we'll use this issue to do that too.

Oh, it wasn't at all clear to me that files specified with the spring.config.location were also profile-enabled, it might be that I missed that one in the docs. I though that when it points to a valid file, the file is the thing with the highest precedence, that's it, no profiles are considered.

What it's trying to tell you was that there was no profile-specific variant of the application-external.properties

So, to summarize, when I say

--spring.config.location=/path/to/localdev.properties --spring.profiles.active=profileA

the following will also be used:

/path/to/localdev-profileA.properties?

I can't make it work. Or is the file supposed to be named differently? Sorry, but I can't get a clear answer from the documentation, maybe it's the fact I'm not a native speaker.

The log output is a bit misleading and strange. When I don't set the config name nor the location, just use a profile, and rename the files to application.properties and application-profileA.properties, I get:

Loaded config file 'file:./application-profileA.properties'
Skipped (empty) config file 'file:./application-profileA.properties' for profile profileA
Skipped (empty) config file 'file:./application.properties' for profile profileA

So it does load the profile version of the application.properties, but then it goes on to try and load them again, this time skipping them.

Oh, it wasn't at all clear to me that files specified with the spring.config.location were also profile-enabled

They are as long as you either specify a directory (rather than a specific .properties file), or a YAML file that contains multiple profiles.

Sorry, but I can't get a clear answer from the documentation, maybe it's the fact I'm not a native speaker.

I think it's much more likely that the documentation is unclear. It currently says:

If spring.config.location contains directories (as opposed to files) they should end in / (and will be appended with the names generated from spring.config.name before being loaded)

And then goes on to say:

In addition to application.properties files, profile-specific properties can also be defined using the naming convention application-{profile}.properties. … Profile-specific properties are loaded from the same locations as standard application.properties, with profile-specific files always overriding the non-specific ones irrespective of whether the profile-specific files are inside or outside your packaged jar.

At the very least, I think this could be improved by describing what happens when spring.config.location points to a specific .properties file rather than a directory. If you have other suggestions on how we could improve things, please let us know.

The log output is a bit misleading and strange

Agreed. All three lines you've listed are misleading or not as informative as they could be.

Loaded config file 'file:./application-profileA.properties'

This is saying that profileA is active and, therefore, the profile-specific file application-profileA.properties has been loaded.

Skipped (empty) config file 'file:./application-profileA.properties' for profile profileA
Skipped (empty) config file 'file:./application.properties' for profile profileA

Both of these lines are actually saying that .properties files don't support multiple profiles in the same file.

The misleading logging is an unfortunate side-effect of it being performed in a generic location that doesn't (and shouldn't) understand the difference between .properties and .yaml configuration files.

Was this page helpful?
0 / 5 - 0 ratings