How to select profiles in spring-boot - java

I have application files according to my environment: application.yml and application-uat.yml. I'm running the application by providing the SPRING_PROFILES_ACTIVE as environment variable so that the correct file is selected. I have a problem with defining additional profiles inside application.
Suppose I have a bean with profile mock-rest that mocks the rest client and I have a bean with profile actual-rest.
I've tried two do it in those ways:
#inside application.yml
spring:
profiles:
include: mock-rest
And for UAT:
#inside application-uat.yml
spring:
profiles:
include: actual-rest
But the problem is that spring will include both profiles, because it takes the both files and only replaces the values from uat yml file.
If I try to use spring.profiles.active inside yml files Spring will ignore that as the SPRING_PROFILES_ACTIVE environment variable will have priority.
So, the question is what is the way to overcome described problem? Basically, I need to define profiles inside application.yml files and I want to only define environment as my SPRING_PROFILES_ACTIVE env variable. Is this possible? If not, what are my options to consider?

The application.yml file is read whatsoever. This is an indented behaviour. Usually, all values in application.yml would be overrided by other more specific application-*.yml.
But profiles are not a single values, you can have multiple one enabled at the same time, so i does not oeverride the profile, instead it cumulate both.
If you want to get rid of the mock-rest on prod environment you might want to remove the mock-rest profile from application.yml and move it to a new application-mock.yml that you can activate using an environment variable.
application.yml
# some default configuration
application-mock.yml
spring:
profiles:
include: actual-rest
application-uat.yml
spring:
profiles:
include: actual-rest

Related

How does spring boot know which property file to use based on environment

I have 4 files in my project:
application.properties
application-dev.properties
application-qa.properties
application-prod.properties
application.properties has a property spring.profiles.active = #active.profile#
When running on local, it uses application-dev.properties file. But in UAT and Prod, it uses respective property files. My question is how does spring boot know to use dev when im running in local and and qa in uat and prod in prod?
What does #active.profile# mean?
This is decided by the "profiles" variable. This is a Set<String>.
The exact way spring detect the profiles depends on the way you run your application.
The most common way is through the System Parameter: -Dspring.profiles.active=dev. So I assume somwhere in your production enviroment this variable gets set.
Alternativelly, if you run your spring app via a builder, you can define the profiles explicitly (code is in kotlin):
SpringApplicationBuilder(MyApp::class.java)
.profiles(*profiles)
.run(*args)
Check this article for more info: https://www.baeldung.com/spring-profiles

How to autoselect springprofile when running tests

I am looking for a solution to automatically add the environment variable SPRING_PROFILES_ACTIVE="test" when running unit-tests. The solution should fulfill the following criteria :
Ideally it should be configured via maven pom.xml
If 1 is not possible configuration should be done for IntelliJ via configuration file in the project not via UI setting
The particular environment variable should only be set when running unit tests not when generally launching the app.
Any idea on how to approach this goal is appreciated.
Best
Andy
The SPRING_PROFILES_ACTIVE is a property value that should be set in a file like application-test.properties or application-test.yml
In a yml file it would look like,
spring:
profiles:
active: test
Additionally, there are specific annotations to help identify certain classes/methods as test specific such as #Profile("test") or #ActiveProfiles("test").

Spring Boot read environment variables inside application-properties

So I have been trying to figure out how to use environment-variables in either application.properties or application.yaml. Since this works in countless frameworks (such as Laravel for example), I assumed this would also work in Spring Boot. Now as I have found out, this is not the case.
I saw a post about Spring Environment API, that started that the environment-variable SPRING_DATASOURCE_URL would be equivalent to setting spring.datasource.url inside my application. However, this also didn't work for me.
Is there any quick way that allows using variables that are declared inside a .env file?
I'd like to use it like this inside the application.properties if possible.
spring.datasource.url=jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
.env is way of Python. If you use spring cloud, you can read env variable from configServer then inject them into application.properties.
add some dependency into pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
define a yml to locate config-server. for example, called myBootstrap.yml
spring:
cloud:
config:
fail-fast: true
uri: http://[config-server-git]
name: cc
profile: config
label: maste
define a file named cc-config.properties and push it into config-server git. The env variables are written in this properties.
use below way to run application jar
java -jar [your-application-jar] --spring.cloud.bootstrap.location=myBootstrap.yml

Spring Autoconfig order/precedence on Profiles

I've just been reading through some of the Spring documentation and I have a question about the way the autoconfigs work. So if we run a Java app with specific profiles, it will automatically use profiles that are named in the format:
application-{{profileName}}.properties
So lets say I'm running the application with the profiles dev and personal. This means that the following properties files with be run:
application.properties, application-dev.properties, and application-personal.properties. I'm confused as to how spring determines the precedence of these profiles. Like, if I define something in dev that overwrites personal, which one will be used?
Thanks!
Spring Boot uses your defaut profile default then overrides it sequentially with the profiles you listed.
For example, if you specify in your application.properties :
spring.profiles.active=dev,personnal
key1=default-value1
key2=default-value2
key3=default-value3
All values defined in personnal profile will override those from dev and default.
application-dev.properties :
key2=dev-value2
key3=dev-value3
application-personnal.properties :
key3=personnal-value3
Your app will match theses values :
key1=default-value1
key2=dev-value2
key3=personnal-value3
You can also use spring.profiles.include in application-personnal.properties to unconditionnally include dev profile in personnal profile for example :
spring.profiles.include=dev
Regards
You can think of application.properties file as 'file of default values'.
When you specify a profile on bootstrap, for example 'dev', first of all, application.properties file is processed, after that, these values are overwritten by values imported from application-dev.properties file. So values on 'application-personal.properties' are not imported.

Spring Datasources based on Environment

I am trying to configure my Spring Boot application to use specific datasources when certain environmental variables exist. For example, if the MY_PROD_DATASOURCE environmental variable exists, I would like to use my production datasource; otherwise, I would like to use my local datasource (of the same type).
I have found something in the Spring reference that explains how a single datasource could be declared in my application.properties. Specifically, a MySQL datasource could look like:
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driverClassName=com.mysql.jdbc.Driver
However, I do not see how I could change the datasource properties conditionally in this file. Is there another way to do it?
In Spring Boot you can:
Externalize application.properties from your jar and provide file per environment by adding path as a startup parameter:
java -jar your-app.jar --spring.config.location=/path/to/app.properties
Use Spring profiles. Create application-${profile}.properties for each profile, in each one different datasource properties
Use Spring profiles and instead of application.properties, put your properties to application.yaml where you can put properties for all environments using convention as below:
spring:
profiles: development
server:
port: 9001
---
spring:
profiles: production
server:
port: 0
Use environment variables and set SPRING_DATASOURCE_URL, SPRING_DATASOURCE_USERNAME, SPRING_DATASOURCE_PASSWORD, and (optionally) SPRING_DATASOURCE_DRIVER_CLASS_NAME.
Learn more in the Spring Boot reference section on How to change configuration depending on the environment and External Configuration.

Categories

Resources