How to set Spring profile from system variable?
JavaSpringSpring ProfilesJava Problem Overview
I have a Spring project which uses another project. Each project has its own spring profile initialize from java code using applicationContext.xml
and *.properties
for each profile. I inject the profile from args[]
. The problem is that second project uses the default configuration for the env from the applicationContext.xml
I can not inject the env from args[]
to the second project and I tried looking for an article which will explain how Spring profile works.
- Is there a hierarchy on which it will look the profile when default is not configured at
applicationContext.xml
? - Is System var stronger than
applicationContext.xml
configuration? - What you think is the best solution to my challenge?
Articles on that subject or even examples would be most appreciated!! Thanks in advance.
Java Solutions
Solution 1 - Java
SPRING_PROFILES_ACTIVE is the environment variable to override/pick Spring profile
Solution 2 - Java
If you provide your JVM the Spring profile there should be no problems:
java -Dspring.profiles.active=development -jar yourApplication.jar
Also see Spring-Documentation:
> 69.5 Set the active Spring profiles > > The Spring Environment has an API for this, but normally you would set > a System property (spring.profiles.active) or an OS environment > variable (SPRING_PROFILES_ACTIVE). E.g. launch your application with a > -D argument (remember to put it before the main class or jar archive): > > $ java -jar -Dspring.profiles.active=production > demo-0.0.1-SNAPSHOT.jar > > In Spring Boot you can also set the active profile in > application.properties, e.g. > > spring.profiles.active=production > > A value set this way is replaced by the System property or environment > variable setting, but not by the SpringApplicationBuilder.profiles() > method. Thus the latter Java API can be used to augment the profiles > without changing the defaults. > > See Chapter 25, Profiles in the ‘Spring Boot features’ section for > more information.
Solution 3 - Java
I normally configure the applicationContext using Annotation based configuration rather than XML based configuration. Anyway, I believe both of them have the same priority.
*Answering your question, system variable has higher priority *
Getting profile based beans from applicationContext##
-
Use @Profile on a Bean
@Component
@Profile("dev")
public class DatasourceConfigForDev
Now, the profile is dev
Note : if the Profile is given as
@Profile("!dev")
then the profile will exclude dev and be for all others.
-
Use profiles attribute in XML
<beans profile="dev">
<bean id="DatasourceConfigForDev" class="org.skoolguy.profiles.DatasourceConfigForDev"/>
</beans>
##Set the value for profile:##
- ##Programmatically via WebApplicationInitializer interface## In web applications, WebApplicationInitializer can be used to configure the ServletContext programmatically
@Configuration
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter("spring.profiles.active", "dev");
}
}
- ##Programmatically via ConfigurableEnvironment## You can also set profiles directly on the environment:
@Autowired
private ConfigurableEnvironment env;
// ...
env.setActiveProfiles("dev");
- ##Context Parameter in web.xml## profiles can be activated in the web.xml of the web application as well, using a context parameter:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-config.xml</param-value>
</context-param>
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>dev</param-value>
</context-param>
-
##JVM System Parameter## The profile names passed as the parameter will be activated during application start-up:
-Dspring.profiles.active=dev
In IDEs, you can set the environment variables and values to use when an application runs. The following is the Run Configuration in Eclipse:
-
##Environment Variable##
to set via command line :
export spring_profiles_active=dev
> Any bean that does not specify a profile belongs to “default” profile.
##The priority order is :##
-
Context parameter in web.xml
-
WebApplicationInitializer
-
JVM System parameter
-
Environment variable
Solution 4 - Java
If you are using docker to deploy the spring boot app, you can set the profile using the flag e:
> docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 -t > r.test.co/myapp:latest
Solution 5 - Java
You can set the spring profile by supplying -Dspring.profiles.active=<env>
For java files in source(src) directory, you can use by
System.getProperty("spring.profiles.active")
For java files in test directory you can supply
SPRING_PROFILES_ACTIVE
to<env>
OR
Since, "environment", "jvmArgs" and "systemProperties" are ignored for the "test" task. In root build.gradle
add a task to set jvm property and environment variable.
test {
def profile = System.properties["spring.profiles.active"]
systemProperty "spring.profiles.active",profile
environment "SPRING.PROFILES_ACTIVE", profile
println "Running ${project} tests with profile: ${profile}"
}
Solution 6 - Java
My solution is to set the environment variable as spring.profiles.active=development
. So that all applications running in that machine will refer the variable and start the application. The order in which spring loads a properties as follows
application.properties
system properties
environment variable
Solution 7 - Java
If i run the command line : java -Dspring.profiles.active=development -jar yourApplication.jar
from my webapplication directory it states that the path is incorrect. So i just defined the profile in manualy in the application.properties file like this :
spring.profiles.active=mysql
or
spring.profiles.active=postgres
or
spring.profiles.active=mongodb
Solution 8 - Java
Too late to the party but here are the new trends for this topic: https://howtodoinjava.com/spring-boot2/logging/profile-specific-logging/
Here is a excellent example:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<property name="LOG_FILE" value="c:/temp/spring.log}"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<file>${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE}.%d</fileNamePattern>
</rollingPolicy>
</appender>
<springProfile name="local | dev">
<logger name="org.springframework" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE" />
</logger>
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</springProfile>
<springProfile name="prod">
<root level="INFO">
<appender-ref ref="FILE" />
</root>
</springProfile>
<springProfile name="!local & !dev & !prod">
<root level="INFO">
<appender-ref ref="FILE" />
</root>
</springProfile>
</configuration>
!NB! If you have problems using &
replace it with &