Maven Spring boot: set additional properties file location on test - spring

Currently, I'm setting additional spring boot properties file using spring.config.additional-location:
mvn -DskipTests spring-boot:run -Dspring-boot.run.arguments=--spring.config.additional-location=api-props.properties
I'd like to know how to set this additional properties file when I test it. Up to now, I've tested to put this parameter on test.
mvn test -Dspring-boot.run.arguments=--spring.config.additional-location=api-props.properties
Any ideas?

In general, there are many options.
Start with application.properties in src/test/resources folder.
If the test is marked with #SpringBootTest this properties file will be picked automatically.
It will also override properties specified in "usual" application properties
Another good option is using #TestPropertySources annotation
For complete list see here

Related

Spring Boot - how to include src/main/resources sub-directory to classpath

I have file src/main/resources/dev/important.properties where in fact 'dev' is one of Spring profile names I use.
Somewhere in application this file is referenced as:
#PropertySource(value = "classpath:important.properties")
When I run in Intellij:
mvn spring-boot:run -Dspring-boot.run.profiles=dev
I get FileNotFoundException upon application start. If I move file one level up (to src/main/resources) it works. I can say no surprise here. How to add src/main/resources/dev to classpath so this file would be visible in this directory? This stuff is needed only for local development (Maven+Intellij and dev profile) and it's excluded from runnable jar. I do not want to modify #PropertySource expression.

Maven Failsafe Integration Test Classpath

I have an spring application which reads properties file content from etcd server and then writes the content of that into applications properties file. After that I use that properties file to load my propertyManager.
Code implementation is done but when I try to create integration-tests, there is an small problem:
I use MyClass.class.getResource(configFilePath) to get URL of my properties file and since it points to a file inside of a JAR file while working integration tests. I can't write what I read from etcd server to my properties file since its in JAR file(under target) now.
I tried to add additionalClasspathElement ${project.build.directory}\conf to my classpath and use properties file inside of that folder but its not working.
Is there a way for me to change classpath of integration test via failsafe plugin?
Note: Springs etcd support is not want I want to use. I want to change my classpath when I run my integration tests.

Maven install command with environment variables file

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:
Run the application in different environments with java -DenvFile=/path/<fileName>.env -jar application.jar
Solution for running tests.
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

tomcat7-maven-plugin to deploy spring boot with appropriate spring profile selected

My goal is to be able to use the tomcat-maven plugin to deploy my spring boot application from the command line where an argument is supplied that tells spring which profile to use like this:
mvn tomcat7:deploy -Dspring.profiles.active="dev"
I've tried several different things such as the solution described here but the default application.properties is still always selected.
The only way that I've been able to get the application-dev.properties selected is by using
mvn spring-boot:run -Dspring.profiles.active="dev"
But we don't want to have tomcat packaged in our war
I'm new to maven and spring boot and I've been spinning my wheels for the better part of a a day now so any advice would be appreciated.
Consider using MAVEN_OPTS environment variable to set VM argument. (Linux/osx) example you would need to execute before your maven goal:
export MAVEN_OPTS="-Dspring.profiles.active=dev"
I found out the issue and I was able to get the correct profile selected using
export SPRING_PROFILES_ACTIVE=dev. The problem that I was having was when I was starting my local tomcat server through the eclipse UI my environment variables were being ignored. When starting tomcat through startup.bat the environment variable gets used and spring uses the correct profile.

how to pass application.properties in commandLine for a spring boot application?

I have a spring boot application and I want to pass application.properties file in commandLine when I start-up.
i.e when I run mvn spring-boot:run --application.properties
I will have a default application.properties in src/main/resources. but that is only for testing purposes. In the production run, I would like to pass the property file in commandLine.
I am aware of passing single arguments such as
mvn spring-boot:run --server.port=9001.
But I have many such properties and would prefer to pass a property file if that is possible.
You can do that with spring.config.location property:
mvn spring-boot:run -Dspring.config.location=your.properties
In case if anyone finds it useful as it was for me. If you want to pass in individual application properties as parameters when using the maven spring boot run command you can use the argument spring-boot.run.jvmArguments.
Eg:
mvn spring-boot:run -Dspring-boot.run.jvmArguments='
-Dspring.datasource.url=jdbc:postgresql://localhost:5432/mydb
-Dspring.datasource.username=admin
-Dspring.datasource.password=admin'
With the above command I am setting (overriding) the following properties which were in the application.properties file.
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=admin
spring.datasource.password=admin
mvn spring-boot:run -Dspring-boot.run.arguments=--spring.config.location=classpath:/application-local.properties

Resources