Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue overriding application properties in Spring-boot (profile-specific) application launched with PropertiesLauncher

I'm having difficulty trying to override a property declared in a profile-specific application properties file on the classpath with another value declared in an overrides file on the file system.

I have an auto-configured Spring-boot application (that is, using @EnableAutoconfiguration) that has multiple profiles, which I launch using PropertiesLauncher rather than JarLauncher (the reason having to do with deployment constraints - I need to deploy an exploded directory rather than an archive into a read-only filesystem.)

Within the root of my application, I have some profile-specific application properties, for example:

application-dev.properties
application-qa.properties
application-prd.properties

And let's say, for the sake of argument that application-dev.properties contains:

foo.bar=baz
foo.baz=other

For any environment, it may be necessary to override an existing property, as well as supply an absent one (like a production password, for example), and the issue I'm seeing is with overriding properties already declared in an application-${profile}.properties file on the classpath. (Supplying properties not present in the classpath file works fine, this is not the issue.)

Say I have an overrides properties file in a file system location such as:

/local/appname/dev/overrides/application.properties

and I want to override the property, foo.bar, as well as declare a new property, foo.password.

Therefore the contents of the overrides file are:

foo.bar=overridden-value
foo.password=something

When I launch the application, I use a command line something like this:

java -Dspring.config.location=file:/local/appname/dev/overrides/ 
     -Dspring.profiles.active=dev 
     org.springframework.boot.loader.PropertiesLauncher 
     --debug &

The issue I am seeing is that although foo.password, the property not declared in the application-dev.properties file is picked up, the override of foo.bar is ignored - I still see the value, baz from application-dev.properties rather than the value, overridden-value from /local/appname/dev/overrides/application.properties.

With the --debug option enabled, I can see the ConfigFileApplicationListener logging that it has loaded both the overrides file (from the filesystem) and the profile-specific file (from the classpath), in that order.

I'm tempted into the perhaps naïve conclusion that because the overrides file is listed first, it is being loaded first then overridden by the 'default' profile-specific file from the classpath, which is listed later. I do appreciate however, that order of listing in the log doesn't necessarily correlate with behaviour. And I have tried varying the order of paths declared on the spring.config.location property, so that classpath: is listed before file:... but this hasn't helped and I't not convinced it would anyway, given that the Spring-boot documentation clearly states that the default properties locations are always searched even if you supply a value for spring.config.location.

The Spring-boot documentation is very specific about the order that properties are resolved for a Spring-boot executable JAR, in descending order of precedence:

  1. Command line arguments.
  2. Java System properties (System.getProperties()).
  3. OS environment variables.
  4. JNDI attributes from java:comp/env
  5. A RandomValuePropertySource that only has properties in random.*.
  6. Application properties outside of your packaged jar (application.properties including YAML and profile variants).
  7. Application properties packaged inside your jar (application.properties including YAML and profile variants).
  8. @PropertySource annotations on your @Configuration classes.
  9. Default properties (specified using SpringApplication.setDefaultProperties).

Take note of lines 6 and 7 - properties outside over properties inside your jar.

What's not stated, as far as I can see, and which may be the source of my confusion/issue, is what happens when you're not using a JAR but an exploded directory (and therefore PropertiesLauncher.)

If the behaviour of an exploded directory were consistent with what's stated for a JAR, I'd expect that the values of properties declared in /local/appname/dev/overrides/application.properties would override any of the same name declared in classpath:application-dev.properties, but this doesn't seem to be the case.

Also noted from the Spring-boot documentation (appendix C.4 on PropertiesLauncher) is mention of the loader.home property, which is described as '... [the] Location of additional properties file, e.g. /opt/app (defaults to ${user.dir})'.

So I tried using loader.home instead of spring.config.location, but to no avail.

(Update: I also tried using loader.config.location and I have two notes: it seems to want a file rather than a directory (so its behaviour is not analogous with spring.config.location), and when I did supply a file path rather than the parent directory, it still didn't help.)

Can anyone spot what I'm doing wrong, or what incorrect assumption(s) I'm making?

like image 738
Damian Avatar asked Oct 30 '14 20:10

Damian


People also ask

Which Spring Boot property sets the profile for an application?

Spring Boot will automatically load the properties in an application. properties file for all profiles, and the ones in profile-specific . properties files only for the specified profile. In this way, we can easily provide different configurations for different environments.

Which property needs to be added in the application properties file to activate a particular profile?

active properties to activate or include profiles from an application.

How do I change the application properties on a dynamic boot spring?

run(SpringBootTestApplication. class, args); and used SpringApplicationBuilder class to add properties to the app. Now, these properties are defined in the program, You can apply condition and change property values based on your requirements. Save this answer.

Can we change application properties in Spring Boot?

Spring boot provides command line configuration called spring.config.name using that we can change the name of application. properties. Here properties file name will be my-config.


1 Answers

Thanks, Dave, your suggestion was 100% correct.

If I rename the properties file in /local/appname/dev/overrides to application-dev.properties then the property values from that file do override the ones in classpath:application-dev.properties.

I was sure I had tried this combination yesterday, but I think what must have stopped it working was when I was playing around with specifying the spring.config.location and got that wrong so it wasn't looking for the override file in the right place.

like image 133
Damian Avatar answered Oct 24 '22 06:10

Damian