Is there any way to execute the environment variables file .env
along with maven commands such as mvn clean install
or mvn clean deploy
. The main idea behind the concept that I'm looking for similar kind of solution:
mvn clean install -DenvFile=/path/<filename>.env
OR
mvn clean deploy -DenvFile=/path/<filename>.env
OR
mvn clean package -DenvFile=/path/<filename>.env
Note: Not trying to produce the environment specific builds. In dev environment, my intention to run the junit tests with all the environment variables configured from
<filename>.env
.
where, the above maven commands should set all the environment variables from <filename>.env
and then execute the maven plugins. In IntelliJ, there's a envFile
plugin which exactly do the same.
Don't want to have environment specific properties dev|staging|prod.properties
in my project because it's messy and hard to manage. I'd rather prefer to have one single environment specific file filename.env
which contains all the dynamic/changeable properties.
application.properties
spring:
cloud:
config:
uri: http://config-service:${CONFIG_SERVICE_PORT}
fail-fast: true
password: ${CONFIG_SERVICE_PASSWORD}
username: user
Environment File: .env
CONFIG_SERVICE_PORT=8080
CONFIG_SERVICE_PASSWORD=123
Now when I deploy the application in different environments like AWS, GCP and Azure. All I need to change the environment variables in the .env
file and run the application java -DenvFile=/path/<fileName>.env -jar application.jar
and it will do the magic.
My problem is related with maven-sure-fire
plugin for testing in dev-mode
, which require these environments variables for spring context
.
Any help would be appreciated.
Ok from your comments it seems like you're looks for two different solutions:
java -DenvFile=/path/<fileName>.env -jar application.jar
These are different issues I'll try to address both
Issue 1
When you run java -jar
this means that the artifact is already assembled (with the help of spring boot maven plugin as far as I understand).
This jar is a ready to go spring boot application and maven is basically irrelevant here - maven is a build system, spring is a runtime framework and we're talking about the runtime.
Spring boot has a lot of ways to achieve what you want. A "Native" spring boot way which is close to your situation is running the application with "--spring.config.location=file:// with all the required configurations
It looks like this (see here for complete documentation):
java -jar application.jar --spring.config.location=myprops.properties
Even if you have some properties defined in src/main/resources/application.properties
this method allows to override them effectively providing a way to run different configurations in different environments.
This has an advantage over the .env files because it can run in the same way in all the OS-es, even Windows ;) Since Java is OS independent - I believe its the best you can achieve.
Of course you can wrap the java -jar
line in some kind of bash script and load / execute a series of export
commands before running the jvm, but again, its less "spring-y" way.
Issue 2
Maven runs the tests (unit/integration) in a way that spring boot maven plugin is irrelevant. Its all about surefire/failsafe and spring boot testing framework.
I'll assume you're asking about integration tests because I believe this is all irrelevant for unit tests, since those should not require any environment variables at all and should be run without spring at all (junit/mockito should do the job)
I'll also allow myself to keep the assumption that the way of overriding/configuring the spring boot application via yaml or properties file is better than .env and will provide spring test configuration solution here:
With these assumptions you can create a yaml file in the following path: src/test/resources/application-test.yml
This file can contain configurations relevant for tests and will override anything written in src/main/resources/application.yml
. Note, since application-test.yml
resides in test sources, spring boot maven plugin won't package it into the application.
Depending on the exact way of doing integration tests you might consider also using @TestPropertySource
annotation to provide the custom properties/yaml file that doesn't follow spring boot's default convention. Its especially useful for spring driven tests that do not bootstrap with the spring boot full fledged support (read the tests that use junit's spring runner but don't have annotation @SpringBootTest
)
Another possibly useful annotation is @ActiveProfile("myprofile")
. This will cause spring boot tests to automatically load file src/test/resources/application-myprofile.yml
(or application-myprofile.properties
)
Last but not least I'll refer the second comment with "dev/prod/staging/properties" in the source.
When it comes to tests - there should be only one file application-test.yml
. However note that when you're using yaml, its possible to define configurations for many spring boot profiles in the same file:
# default value
foo:
bar: 1
---
spring:
profiles: staging
foo:
bar: 2
---
spring:
profiles: prod
foo:
bar: 3
Some relevant SO thread