Many times we face situation in which we want certain things configured as per the environment or on certain complex condition. Spring provides great features in easing the developer job for this use-case. We will look at such a scenario along with solution spring provides in this case.
Environments and Profiles:
One of the most challenging part of any application is to transitioning of the software into different environments (DEV, QA, STG, PROD). Certain choices that we make in DEV environments are not suitable when we run the same setup on PROD environment.
Consider basic use of using different database as per the deployment environment.
for DEV we might setup a datasource something like below:
@Bean(destroyMethod = "shutdown") public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .addScript("classpath:devCreate.sql") .addScript("classpath:devInsert.sql") .build(); }
So for your PROD environment your datasource configuration might look like below:
@Bean(destroyMethod = "shutdown") public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://mydevdb.com:3306/mydb"); dataSource.setUsername("dbUserName"); dataSource.setPassword("dbPassword"); return dataSource; }
Using Profiles:
You can have both above beans defined in same java configuration file as below:@Profile("dev") @Bean(destroyMethod = "shutdown") public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .addScript("classpath:devCreate.sql") .addScript("classpath:devInsert.sql") .build(); } @Profile("prod") @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://mydevdb.com:3306/mydb"); dataSource.setUsername("dbUserName"); dataSource.setPassword("dbPassword"); return dataSource; }
You can define the annotation on class-level as well if you have different java configuration class for different environment.
Using Old xml based configuration:?😓 Dont worry !
You can activate profiles in xml configuration as below:
<beans profile="dev" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<jdbc:embedded-database id="dataSource">
<jdbc:script location="classpath:devCreate.sql"/>
<jdbc:script location="classpath:devInsert.sql"/>
</jdbc:embedded-database>
</beans>
<beans profile="prod">
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="username" value="dbUserName"/>
<property name="password" value="dbPassword"/>
<property name="”url”" value="jdbc:mysql://mydevdb.com:3306/mydb"/>
</bean>
</beans>
Activate Profiles:
Once you have defined the beans using @Profile annotation you need to activate the profile to create and register those beans with ApplicationContext.- spring.profiles.active: This property is used to set the active profiles on the current configuration. You can set the property by many ways:
//setting parameter on context directly AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); context.getEnvironment().setActiveProfiles("DEV" ) // OR using java system properties java -jar jarName -Dspring.active.profiles=DEV // OR as servletContext parameter servletContext.setInitParameter("spring.profiles.active", "DEV");
- spring.profiles.default:
Any bean that does not specify a profile belongs to "default" profile.
Spring also provides a way to set the default profile when no other profile is active – by using the "spring.profiles.default" property.