Manage build profiles/configs for Spring Boot application - spring

I have written application using spring boot + scala with sbt and now I need to divide build configurations for dev and prod.
What has been done: created configs application.yml and application(-dev/prod).yml to start application locally, on dev and prod respectively.
What need to be done: find a way to configure spring boot profile (dev, prod) in javaopts or directly write corresponding config, also in javaopts.
I've tried to use these opts:
sbt service/run -Dspring.profiles.active=...
sbt service/run -Dspring.config.location=...

The answer is to configure active profile like this:
sbt service/run --spring.profiles.active=...

Related

How do I override configuration in application.yml in spring boot (2.4.2) generated docker image?

I used spring boot 2.4.2
Generated docker image using the command mvn spring-boot:build-image -Dspring-boot.build-image.imageName=XXXXXX.azurecr.io/fake-XXXXX:0215
I have hostnames in application.yml that I need to override
So I passed -Dspring.data.mongodb.host=mongo_db in docker-compose under command: BUT it is not overriding. .. Below screenshot for reference.
I understand that Buildpacks are used to build the layered jar.
If this was docker image created by me manually and not by spring boot then I would have ENTRYPOINT in Dockerfile and command in docker-compose where I would have given command: Dspring.data.mongodb.host=mongo_db -jar fake-XXXX.jar
I know #6 works but would like to use the latest and greatest spring boot in my new project. Hence kindly let me know your thoughts.
Why don't you try the approach via Spring Config or Harshi Corp Consul KV feature and read your config from there. Check-in your config to a repo and have config framework read it from there and pass it to your app? You can change the config at runtime (probably requires restart of containers to reload the modified KV fields in some case)

Is there any meaning to running -Dspring.profiles.active=dev,runtime when running Spring Boot locally?

In my team I frequently (>10) see Spring Boot projects with the following instructions for running locally:
mvn clean spring-boot:run -Dspring.profiles.active=dev,runtime
My understanding of Spring Boot profiles is that each one corresponds to a particular environment, eg dev, test - so you would never need more than one. Also that each profile name corresponds to a particular env file - eg src/main/java/resources/application-dev.yml application-test.yml etc.
I would have thought that you would run the app on your local machine with:
mvn clean spring-boot:run -Dspring.profiles.active=local
And have the local configuration in:
src/main/java/resources/application-local.yml
This is running:
Java 11
maven parent is org.springframework.boot spring-boot-starter-parent 2.2.6.RELEASE
maven version is 3.3.9
My question is: Is there any meaning to running -Dspring.profiles.active=dev,runtime when running Spring Boot locally?

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

How to Run multiple spring boot application in gradle

I'm a beginner in gradle need to implement multi-module spring boot rest micro-services
sample source code:git-hub
when I give a bootRun command
actual:
this task is running only demo1 module so that that rest API I can access
expected
Need to run both demo1 and demo2 project in a different port.
Environment: jdk8, spring-boot 2, gradle 5
This is a Maven project for running multiple Boot projects in different ports within a single JVM.
https://github.com/rameez4ever/springboot-demo/tree/master/springboot-multi-service-launcher
Changing Maven pom.xml to Gradle build.gradle might be sufficient. Hope this gives some idea.

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.

Resources