Profile-specific spring.config.additional-location? - spring

I have specified an external properties file to a Spring Boot app by setting spring.config.additional-location in the SpringApplicationBuilder.
new SpringApplicationBuilder(MyApplication)
.properties(['spring.config.additional-location': myExternalProperties])
.run(myArgs)
This works insofar as it allows me to override properties in the application.properties file using myExternalProperties.
However, myExternalProperties are in turn overridden by any profile-specific properties, e.g. application-myProfile.properties.
I understand this to be consistent with Spring's prioritization of Externalized Configuration, but I want myExternalProperties to override even profile-specific properties.
How can I achieve that order of priority?
I do not control the file name or location of myExternalProperties. This variable is a System property that is preset in the environment.
I have been looking at Profile-specific Properties and in particular this quote.
If you have specified any files in spring.config.location, profile-specific variants of those files are not considered. Use directories in spring.config.location if you want to also use profile-specific properties.
I assume this note applies equally to spring.config.additional-location, but without control over the property file name or location I don't think that helps me.

I'm afraid it cannot be achieved in a non-hacky way.
The docs state:
Profile-specific files always overriding the non-specific ones.
Also:
If several profiles are specified, a last-wins strategy applies. For example, profiles specified by the spring.profiles.active property are added after those configured through the SpringApplication API and therefore take precedence.
Could you consider using profile based configuration for myExternalProperties?
You can even use env vars as placeholders.
Hope this helps: Env vars in Spring boot properties

Related

Quarkus #ConfigMapping: when no prefix defined, skip/ignore system and environment variables, only scan properties with defined keys

Some properties defined in my app are used by other applications in the same organization, so I cannot add a dedicated namespace before them to differentiate. While moving to Quarkus #ConfigMapping, I found Quarkus by default scans all system and environment variables as well as application scoped properties, and non-mapped properties will stop app from launching, showing a lot of "cannot find any root to map" error.
Quarkus YAML config is based on Smallrye config, which has:
smallrye.config.mapping.validate-unknown=false
to stop this behaviour.
https://smallrye.io/smallrye-config/2.11.1/config/mappings/#retrieval
For a Config Mapping to be valid, it needs to match every configuration property name contained in the Config under the specified prefix set in #ConfigMapping. This prevents unknown configuration properties in the Config. This behaviour can be disabled with the configuration smallrye.config.mapping.validate-unknown=false.

Using Expressions in Spring application.properties file

Can expressions be used as a right-hand-side value in a Spring application.properties file?
For example, something like this:
logging.level.com.acme=#{'${MY_RUN_ENV}'=='PROD'?'WARN':'DEBUG'}
That, specifically, does not work. But, I'm wondering if I can do something similar to what's intended there
No you can not use SpEL within properties files.
Finally, while you can write a SpEL expression in #Value, such
expressions are not processed from Application property files.
You can however use placeholders within properties files, eg:
app.name=MyApp
app.description=${app.name} is a Spring Boot application
For your use case, you should look at the profile-specific configuration mechanism.
Which allows you to load different config based on an environment profile.
No this is not possible, From spring boot reference:
Feature #ConfigurationProperties
SpEL evaluation No
Instead you can have an application-default.properties in production and in it define loglevel=WARN.
And in your application.properties:
loglevel=DEBUG
logging.level.com.acme=${loglevel}
The profile-specific properties file(-default by default) should override the properties from application.properties, more info here.
Use profile based properties file.
In application-dev.properties :
logging.level.com.acme=WARN
and in application-prod.properties :
logging.level.com.acme=DEBUG
FYI when spring boot doesn't find a propertie in a profile based file it use the value in the default one . So you can set properties in application.properties and override them in a profile based file when their value changed.

spring boot YAML default and environment variable override like HOCON files

Is there a way in spring-boot YAML file to do the same as in HOCON files where you can have a default and be able to override it with an environment variable like this:
basedir = "/whatever/whatever"
basedir = ${?FORCED_BASEDIR}
In this case in HOCON if you don't define a environment variable named FORCED_BASEDIR then basedir will be "/whatever/whatever" but if you do then the value of basedir will be whatever is defined in the environment variable.
Thanks
So based on webdizz answer below I looked up a little bit and I found a pretty good description in book "Spring Boot in Action". Here is the hierarchy:
There are, in fact, several ways to set properties for a Spring Boot application. Spring
Boot will draw properties from several property sources, including the following:
Command-line arguments
JNDI attributes from java:comp/env
JVM system properties
Operating system environment variables
Randomly generated values for properties prefixed with random.* (referenced
when setting other properties, such as `${random.long})
An application.properties or application.yml file outside of the application
Licensed to Thomas Snead 58 CHAPTER 3 Customizing configuration
An application.properties or application.yml file packaged inside of the
application
Property sources specified by #PropertySource
Default properties
Spring Boot provides means to define variables at many levels and your case is supported, you just need to define variable in following way:
in application.yml:
basedir: "/whatever/whatever"
and in environment:
export BASEDIR = "/another/whatever"
Then in runtime application will use value from environment.
For more details check this out enter link description here.

parent properties for application-{profile}.properties with Spring-Boot app

There are common properties which are shared among different profiles for e.g. path location for temp files and path remains same among different env(tst,prd).
Is there a way to have a parent application-{parent}.properties from which all the profile specific properties files can inherit the properties.
That will help in avoiding writing same properties in all application-{profile}.properties
In addition, each application-{profile}.properties have something like :
profileLocation=xxx
abc=${profileLocation}/tempPath
Here can I move abc to a common location? I cannot in application.properties as it gets loaded before application-{profile}.properties
Actually, that is not entirely true that application.properties are loaded before any others. They are processed together. To set common properties that are used by all profiles, you should use the ordinary application.properties file. Two main thing you should know are described below.
Case 1. The keys that are placed inside the application.properties file can be overridden by profile specific configuration.
common.path.for.all.envs=/some/path
default.path=/another/path
Than in your e.g. application-dev.properties you can override some values.
default.path=/dev/path
At runtime with dev profile your application will have access to two keys. The value of common.path.for.all.envs will be set to /some/path as declared only in the main file and default.path will be set to /dev/path because you override the property in the profile configuration.
Case 2. The values defines in the application.properties file can use placeholders for the values included in profile configurations. For instance, in your application.properties define the following variable:
abc=${profileLocation}/tempPath
Next, in the application-dev.properties declare the missing variable:
profileLocation=xxx
Then running with the dev profile the value of abc will be set to xxx/tempPath. As you see, the variable declared in the profile configuration can be used in the main application.properties file as well.

How do I access Spring properties in a logback configuration

Is there a way to access Spring properties within a logback.xml file?
I know one can import a properties file if you know its location, but I'm using Spring profiles to control where the properties file should be loaded or not.
Is there done kind of connector that asked me to feed Spring data into logback? This would only be at startup; I don't need to be able to do this on the fly.
I'm guessing you do have to import a property file (common property file, non-environment specific one) that will contain the name of the property that you are going to use in the logback.xml, and that you want to optionally override the value of the property for some environment (you need at least one property file containing the name of the property, because you will be using that property in the logback.xml, and you need it to be available to be able to use it).
For the optional environment-override, how about including an additional property file? For example, we use both application.properties and application-${spring.profiles.active}.properties files. Then if we don't need to override the property for some environment, we simply don't include it in the environment specific property file (application-dev.properties, etc.)

Resources