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
Related
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
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.
Actually have a little problem.
I want switch the url of my bootstrap.yml
It looks as follows:
spring:
application:
name: <project-name>
profiles:
active: dev
cloud:
config:
uri: http://<git-repository>:8080
fail-fast: false
This works, but i want have an propertie or anything what can switch if are in local or another enviroment.
I try to see this documentation but dont see any work for me.
I don't think Spring Cloud is any different from any Spring application, so you could use the Spring profiles.
Something similar is suggested on this answer: https://stackoverflow.com/a/22759706/6908551.
You could define a separate .yml file just for your cloud config uri, like cloud-config-dev.yml, cloud-config-prod.yml. Then, for a Java config, you could have something like:
#Configuration
public class MyApplicationConfiguration {
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
String activeProfile = System.getProperty("spring.profiles.active", "production");
String ymlFilename = "cloud-config-" + activeProfile + ".yml";
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
configurer.setLocation(new ClassPathResource(ymlFilename));
return configurer;
}
}
I would define a bootstrap.yml file by environment.
Define a default bootstrap.yml in src/main/resources and define a specific bootstrap.yml file for each environment.
Then there are multiple ways.
Not exhaustive :
1) For each environment where the configuration file differs, run your spring boot jar by specifying the system property spring.cloud.bootstrap.location with the expected value such as :
java -jar ... -Dspring.cloud.bootstrap.location=bootstrap-dev.yml ....
That overrides the current location of that file.
2) Take advantage of Spring Boot profile feature : bootstrap.yml is compatible with. For example if the dev profile is enabled, the bootstrap-dev.properties in the classpath will be used.
I tend to use the first way because that is more explicit for non Spring Boot users.
Source : 1.3 Changing the Location of Bootstrap Properties
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.
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.