Spring Autoconfig order/precedence on Profiles - java

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.

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.profiles.active is not working in springboot application

I have created Profiles in Java class like this,
#Profile(value = "cache")
public class MapCache {
....
}
These profiles are not getting activated when spring.profiles.active used, but if i use spring.profiles.include profiles are working fine.
I would like activate profiles through properties which are added in application.properties
Note: application is running in independent jetty instance.
Any tip would be great on this.
To activate a profile via annotations you need #ActiveProfile("profileName"). The #Profile annotation is used to label an object as being a member of the profile.
you can also try to run the application and pass them as command line args
java -jar -Dspring.profiles.active={your_profile_name} application.jar
or if you run the app via maven:
mvn spring-boot:run -Dspring-boot.run.profiles={your_profile_name}
Here is an nice example I found on the internet with all the ways you can set the spring profile, it should help : https://www.baeldung.com/spring-profiles
I encountered a similar issue where SpringBoot wasn't activating the profiles set in the spring.profiles.active application property.
The issue was the result of the code base using a non standard name and location for the application property file (not my doing). Once I specified the location via the command line arg- --spring.config.location=/non/standard/location/acme.properties- the profile was activated.

Spring Boot 2 use dev profile if prod profile is not exist

I have Spring Boot Application and i have 3 property files: applications.properties, applications-dev.properties, applicaton-prod.properties. In applications.properties i specify that spring.profiles.active=prod. But I want to allow startup of application without prod profile(applicaton-prod.properties). It means that spring must startup application in dev profile(applications-dev.properties) automatically. How can i implement this? May be some MissingOnProfile annotation exist?) My task is to create different application behaviour based on application.properties files. Also i use #Profile annotation in each bean that depends on particular profile. All task is to create WebInstaller, and in finish step i will create application-prod.properties and by using RestartEndpoint i will restart application context and required beans from application-prod.properties will injected. But i need to make startup withoud application-prod.properties, but if this file exist i will startup in prod profile.
You can do this:
SpringApplication application = new SpringApplication(IdMatrixApplication.class);
File file = new File("src/main/resources/dev/application-prod.properties");
if (file.exists()) {
application.setAdditionalProfiles("prod","dev");
}
application.run(args);
You are setting the profile information in the wrong place. The file application.properties contains properties that are common to all profiles (dev, stage, prod etc). For profiles you should, as you suggested, create a file of the name application-{profile}.properties which will override certain properties according to the environemnt defined by variable profile.
The usual approach is to pass this variables as parameters to the JVM (e.g:-Dprofile=dev), which you can set by modifying the run configuration of the servlet container if you are launching from an IDE. In case of a stand-alone tomcat you can pass this information through JAVA_OPTIONS variable found in the file setenv.sh.
If you need to manually implement some kind of business logic with profiles, for example, specify that the active profile by default prod
In application.properties define spring.profiles.active=prod
and for example if the application-prod.properties is missing, then the active profile should be the dev, you can implement this with EnvironmentPostProcessor:
Allows for customization of the application's Environment prior to the application context being refreshed
Implement EnvironmentPostProcessor with your business logic
public class ProfileResolverEnvironmentPostProcessor implements EnvironmentPostProcessor {
#Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
ClassPathResource prodPropertiesResource = new ClassPathResource("application-prod.properties");
// if "application-prod.properties" missing and "prod" profile active
if (!prodPropertiesResource.exists() && environment.acceptsProfiles("prod")) {
environment.setActiveProfiles("dev");
//environment.addActiveProfile("dev");
}
}
}
Register your EnvironmentPostProcessor implementation class in META-INF/spring.factories
org.springframework.boot.env.EnvironmentPostProcessor=\
com.example.ProfileResolverEnvironmentPostProcessor
Also, take look at Spring Boot documentation Customize the
Environment
Additional:
Of course, you can specify beans that will be active if the profile is missing #Profile("!prod")
But this does not work in your case if you define spring.profiles.active=prod, because the active profile prod will be in the Environment but it has nothing to do with the fact that the application-prod.properties is missing
If you want this then why you need application-dev.properties. Keep Your dev properties in application.properties. If profile set then applicatoin.properties value will be overwrite. Spring boot read both application.properties && application.yml and replace value if profile active

Set active Spring Boot profile for Tomcat Webapp internally (via application.properties)

I'd like to use two different spring profiles proda and prodb using Spring Boot 2.0.0 (setting the profile in the application.properties).
In Spring Boot, you can also set the active profile in application.properties, as shown in the following example:
spring.profiles.active=production
Source: 74.6
For now I'm only trying to get proda to work. I've got three different property files:
application-proda.yml
database:
conn:
blablabla: blablaqwer
and
application-prodb.yml
database:
conn:
blablabla: albalbrewq
and also
application.properties
spring.profiles.active=proda
When running the application in the IDE, or packaging it as jar with maven, everything works as expected (active profiles [proda] are set, application-proda.yml is loaded). Calling this in (for example a #PostConstruct of) some class:
System.out.println(Arrays.toString(env.getActiveProfiles()));
will result in
[proda]
but when buildung as war with maven, and deploying it to a Tomcat server, the same code will result in
[]
and application-proda.yml is not loaded. That means the application didn't read the application.properties and therefore didn't load the active profile proda for some reason.
But the finished war has all the needed files under WEB-INF\classes\.
I've seen some solutions where you can set -Dspring.profiles.active=proda as a command line parameter, or set the active profiles in the web.xml, but this is not what I need, as I don't have a web.xml and I'd like to use the Spring Boot feature and declare the profiles in the application.properties. It should work just like in the IDE or packaged as a jar with maven.

Categories

Resources