Multiple profiled properties configuration in Spring-boot 2 - java

I have a spring-boot 2.1.3.RELEASE application with multiple properties files.
In my /src/main/resources I have my-app.properties and profiled my-app-local.properties.
Also, outside the project I have another profiled properties file /config/my-app-local.properties.
The point of this configuration is to have the following properties hierarchy:
/resources/my-app.properties
/resources/my-app-local.properties
/config/my-app-local.properties
So when I try to run the application with the following parameters:
--spring.profiles.active=local --spring.config.name=my-app --spring.config.location=config/my-app.properties
the application fails to start because it can't find any properties files.
However, this configuration and parameters worked perfectly on spring-boot 1.5.19.RELEASE. How can the same be achieved in spring-boot 2?

use spring.config.additional-location doc
When custom config locations are configured by using spring.config.location, they replace the default locations. For example, if spring.config.location is configured with the value classpath:/custom-config/,file:./custom-config/, the search order becomes the following:
file:./custom-config/
classpath:custom-config/
Alternatively, when custom config locations are configured by using spring.config.additional-location, they are used in addition to the default locations. Additional locations are searched before the default locations. For example, if additional locations of classpath:/custom-config/,file:./custom-config/ are configured, the search order becomes the following:
file:./custom-config/
classpath:custom-config/
file:./config/
file:./
classpath:/config/
classpath:/

Related

How can I override configuration in logback-spring.xml with properties in Spring's own application.properties?

In my Spring Boot project, I initially set up the logging configuration in the application.properties, e.g.
logging.file=/foo/bar/app.log
logging.file.max-size=1M
logging.file.max-history=10
logging.file.level.root=DEBUG
logging.file.level.root.com.my.app=DEBUG
logging.file.level.org.springframework.boot.diagnostics=DEBUG
logging.file.level.org.springframework.security=DEBUG
Let's say I have other environment-specific properties files named following this pattern application-xxx.properties with xxx being the Spring profile name passed as argument when running the app (via -Dspring.profiles.active=xxx).
In these files, I can override the log levels, e.g. for an application-qa.properties
logging.file.level.root=INFO
logging.file.level.root.com.my.app=INFO
logging.file.level.org.springframework.boot.diagnostics=INFO
logging.file.level.org.springframework.security=INFO
I can also override these in the command line with the same mechanism as explained above (-D ).
Now, I'm asked to transfer all this configuration into a single logback-spring.xml. Using this new style of configuration, is there a way to still override each properties?
Found these resources while looking for an answer:
neither official Spring doc: https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.logging
nor this DZone article mention that: https://dzone.com/articles/configuring-logback-with-spring-boot
this article on CodeJava: https://www.codejava.net/frameworks/spring-boot/logback-rolling-files-example even says it works the other way round: The configuration in XML file will override the logging properties in the application.properties file. !!!

Java Microprofile change properties on already deployed app (Wildfly)

I have an ear artifact deployed on a wildfly server. On some beans I used the following configuration injection
#Inject
private Config config;
I want to change the properties specified on the "microprofile-config.properties" file on runtime. It is not necessary to change the file itself, I just want to change the properties. I think there might be a way using the console, but I cannot find if there is any.
If you take a look at the spec or even at articles like this, you will see that, by default, Microprofile config reads configuration values from the following 3 places in this order - i.e. from wherever it finds it first:
System.getProperties()
System.getenv()
The configuration file
So, you can override values in the configuration file in 2 ways:
Defining -D command line arguments to the VM (e.g. java -DXXX=yyy ...)
Defining system environment variables (e.g. export XXX=yyy in bash or set XXX=yyy in Windows)
Note that there are some rules for defining environment variables and matching them to actual configurations, e.g. for a configuration aaa.bbb.ccc you may need to set an environment variable as AAA_BBB_CCC. Read ch. 5.3.1 in the specs, and experiment a little.
You can always extend the configuration sources with your own custom ones (to read configuration from JNDI, DB, Zookeeper, whatever).

Disable spring-context-indexer by profile

I want to enable Spring Context Indexer on a project but I am having issues with Swagger3 (check here and here).
I understand the limitations and would like to enable it, at least, at the DEV profile where we do not need Swagger running.
My goal is to disable indexing on PROD environment. From docs:
you can fallback to a regular classpath arrangement (as though no index was present at all) by setting spring.index.ignore to true, either as a system property or in a spring.properties file at the root of the classpath.
My first approach (without success) was setting an env var (Windows 10) with the following:
SPRING_APPLICATION_JSON={"spring":{"index":{"ignore":true}}}
If I create a spring.properties file and set the value accordingly it works. But I can't figure how to use different properties for each profile, I imagined it was something like the application.properties file but I was wrong.
How can I achieve that?
EDIT:
Just to be clear, this config (spring.index.ignore) will just work if inside a spring.properties file, not an application.properties one. (Just double-checked before this edit)
Actually I have one application-prod.properties and one application-dev.properties.
I don't know the difference between spring.properties and application.properties but the first one doesn't seem to work with multiple profiles as the later.
Edit 2:
Just went through org.springframework.context.index.CandidateComponentsIndexLoader and it uses SpringProperties.getFlag(IGNORE_INDEX) to read the value.
SpringProperties class is clear about the file it uses:
Reads a spring.properties file from the root of the Spring library classpath, and also allows for programmatically setting properties through setProperty. When checking a property, local entries are being checked first, then falling back to JVM-level system properties through a System.getProperty check.
I think I will need to pass a property to Java runner during initialization. Will research a little bit more about it.
you can use different application.properties file as follow:
add the following files to the resource folder:
application.properties
spring.profiles.active=dev #place profile name you want to use
application-dev.properties
#dev properties
...
You can create many application-env.properties you may wish
application-env.properties
#env properties
...
Spring Boot supports profile-specific properties files. You have to name these files with the following format: application-{profile}.properties. You can activate a profile via JVM system parameter: -Dspring.profiles.active=dev. You can read more about this subject here: https://www.baeldung.com/spring-profiles

Spring boot external properties file

I'm trying to run a java8 app using spring boot version 2.2.4. The app is then packed in a docker image.
The way I run my app as specified in a Dockerfile which ends liek this:
FROM openjdk:8
.....
CMD /usr/local/openjdk-8/bin/java -jar -Dspring.config.location=/opt/$APP/ /opt/$APP/$APP.jar
The problem I encounter is the loading of external properties files.
For example I have application.properties file similar to this, which is packaed inside the JAR:
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=db1
application.queue.sqs.queue_name=somesqs
In addition, I also inject the docker image an addition application.properties file located at /opt/myapp/. This external file is similar to this:
spring.data.mongodb.uri=mongodb://username:password#MONGO_URL:27017/db_name
application.queue.sqs.queue_name=another_sqs
Expected Behavior: the app will load both new another_sqs location, and external mongo connection.
However, Actual Behavior: when reading the logs I can see that t the new sqs url (i.e. another_sqs) is loaded properly, although the new value for mongo connection is discarded and is therefore using the local embedded mongo engine.
I consulted the following post on stackoverflow to try and understand what I am experiencing:
Spring Boot and multiple external configuration files
But for my understanding, when using spring 2.X and above, the -Dspring.config.location should override all other properties file.
Here is where I started debugging:
TRY 1 : I attached into the docker container, cd into /opt/$APP/ where both my app.jar and application.properties are located, executed the following command java -jar app.jar and viola - it works! A connection to the external mongo source is established. This may be explained by the priority of spring loading properties files as specified in spring's docs.
TRY 2 : Attach the container, cd into $HOME/, execute java -jar /opt/$APP/app.jar -Dspring.config.location=/opt/$APP/ - Do not connect to external mongo, however does connects to the another_sqs. Strange thing - only part of the application.properties values are loaded? Isn't it the way spring 1.X works by adding value from multiple files?
TRY 3 : Attach the container, cd into $HOME/, execute java -jar /opt/$APP/app.jar -Dspring.config.location=file:/opt/$APP/applicartion.properties - same behavior.
Try 4: Edited Dockerfile to include the following execution:
CMD usr/local/openjdk-8/bin/java -jar -Dspring.config.location=classpath:/application.properties,file:/opt/$APP/application.properties /opt/$APP/$APP-$VER.jar
And it works again. Both another_sqs and external mongo are loaded properly on "Try 4".
My question is therefore:
Why should I explicitly specify the classpath:/application.proeprties? Isn't -Dspring.config.location=/opt/$APP/ or -Dspring.config.location=file:/opt/$APP/application.properties should be enough?
When you specify -Dspring.config.location=file:/opt/$APP/application.properties you're overriding the default value of config.location with your application.properties. If you want to use another application.properties, but still using the default properties without declaring them you should use
-Dspring.config.additional-location=file:/opt/$APP/application.properties
In this way, config.location will still have the default value and you will load the external properties as an additional-location.
From the Spring Documentation:
You can also refer to an explicit location by using the spring.config.location environment property (which is a comma-separated list of directory locations or file paths).
When custom config locations are configured by using spring.config.location, they replace the default locations
Alternatively, when custom config locations are configured by using spring.config.additional-location, they are used in addition to the default locations.

tokenize application.conf in play java app

I want to tokenize a few keys in my application.conf file to use variables from another properties file. How can I do so? Here is an example.
my-play-project/conf/application.conf
db.default.url=${env.db.url}
db.default.driver=${env.db.driver}
db.default.user=${env.db.user}
db.default.pass=${env.db.password}
my-play-project/conf/env/devlab/project.properties
db.url=myoracleserver.lab.org:1521
db.driver=oracle.thin
db.user=myname
db.password=mypassword
my-play-project/conf/env/devlab2/project.properties
db.url=myoracleserver2.lab.org:1521
db.driver=oracle.thin
db.user=myname
db.password=mypassword
Q. Is there a way to set devlab/project.properties to be part of system resolvable properties?
Play's configuration uses Typesafe Config. There are several ways of combining configuration together on the classpath and at runtime.
Creating multiple application.conf and application.properties files and putting them all on the classpath (i.e. in different JARs). The configuration will be combined. See Standard Behavior.
Using includes to pull in files with different names.
Using substitutions to pull in values from other config files.
Using substitutions to pull in environment variables or system properties.

Categories