1

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?

Nati Koli
  • 46
  • 6
  • Did you try out the solution of my answer? Did you find any other solution for it? – robertobatts Apr 23 '20 at 16:17
  • @robertobatts - your solution seems to work, however I wanted a more comprehensive explanation for the behavior I described in the post. – Nati Koli Apr 25 '20 at 18:09
  • 1
    Actually there is no other explanation, because that's just how Spring works. I updated my answer swith quotes from Spring documentation – robertobatts Apr 26 '20 at 14:58

1 Answers1

2

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.

robertobatts
  • 965
  • 11
  • 22