Use Maven to configure active environment profile (with spring profile)

Environment profiles are templates that are used to derive concrete environments based on pre-defined templates. Essentially, they are abstract environment definitions that allow environments to be categorized or classified by associating a given environment with an underlying environment profile. Typical examples of profiles are dev, prod, QA, Test, etc.

In this post, we are only focusing on using maven to configure active environment profile with spring profiles in a web application. Certainly, there are different ways to allow us to configure environment profiles even within spring profiles explained in this article : https://www.baeldung.com/spring-profiles

The idea is basically from 4.6 from the above posts with more details to elaborate further on this approach within the web application scope.

Step 1 Configure different environment profiles in pom.xml

For eg, to simplify the problem, I only have two environments for configuration respectively defined as dev and prod. Adding the code below into pom.xml. You will have dev as the default environment when maven build your project.

<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<activeProfile>dev</activeProfile>
</properties>
<build>
<directory>target/dev</directory>
</build>
</profile>
<profile>
<id>prod</id>
<properties>
<activeProfile>prod</activeProfile>
</properties>
<build>
<directory>target/prod</directory>
</build>
</profile>
</profiles>

Step 2 Enable resource filtering in pom.xml

Note: Spring provides spring.profiles.active environment property to specify which profile is active. The question here is: how to populate the value from our configuration property defined as activeProfile in the pom file to this spring environment property. The answer is that you could include it in your application.propertie(dir: src/main/resources ).

Before proceeding below, you have to answer one simple question: Are you using Spring Boot?

If yes, this application.properties file is already ready for you under “src/main/resources” directory, and it will be auto-detected. We can then inject any loaded properties from it as normal. However, if you are not using Spring Boot, create the application.properties under “src/main/resources” directory. Add the following line into your application.properties file. (Here we use the placeholder activeProfile to get value populated to spring.profiles.active when maven build the project).

spring.profiles.active=@activeProfile@

Still, in order to populate the value defined in activeProfile from the pom.xml to the @activeProfile@ placeholder. You have to enable source filtering in pom.xml.

Here is how to do that:

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<targetPath>WEB-INF</targetPath>
</resource>
</resources>

</build>

What is happening under the hood:

By turning on the filter( <filtering>true</filtering>), the code above works as charm when you use the command line mvn clean package. Since you didn’t specify the active profile. Maven will use dev as the default active profile as described by activeByDefault property. And then the activeProfile property will have dev as value and then in application.properties, the line above becomes

spring.profiles.active=dev

By setting the targetPath to WEB-INF( <targetPath>WEB-INF</targetPath> ). After the build, you will see your application.properties get deployed under WEB-INF.

Learn more about the resource filtering over here:https://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html

Step 3 Use spring.profiles.active value in Java config class

In your java config file, you might want to introduce different logic based on different profiles. One practical example is if you would want to set the static content like html, js, css to not cache in dev environment whereas get cached well in prod environment. Then you have to use the value from spring.profiles.active property from application.properties file. You might skip this session if you are very familiar with how spring wire in the property variables.

Now if you answer Yes that if you are using Spring boot in step 2, You can skip the line below, because spring boot will auto detect application.properties. However, if you are not using spring boot, in your Java config file, specify the property file as this:

@PropertySource(value = {“/WEB-INF/application.properties” })

Now let’s talk about how to get the value from the property variable spring.profiles.active, I will introduce two intuitive ways to do it:

  1. Use environment variable

@Autowired

private Environment env;

In the actual logic, simply use like this:

if( env.getProperty(“spring.profiles.active”).equals(“dev”) ) …

2. Use @Value notation.

@Value(“${spring.profiles.active}”)
private String activeProfile;

In the actual logic, simply use like this:

if(activeProfile.equals(“dev”)) …

Note: in order to use @Value annotation to resolve ${} in Spring,  you need to declare a STATIC PropertySourcesPlaceholderConfigurer bean manually. Otherwise if it will show as ${spring.profiles.active} instead of a resolved value like “dev” or “prod”.

Add the following code in the Java config file if you have not declared the bean:

@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}

There are certainly more ways to manipulate the properties, read more on properties with spring with this link: https://www.baeldung.com/properties-with-spring

Step 4 Switch to prod profile

Now, if you want to switch to prod environment. You could do like this:Append a -P parameter to switch which Maven profile will be applied:

mvn clean package -Pprod

This command will package the application for prod profile. It also applies the spring.profiles.active value ‘prod’ for this application when it is running.

You can find the corresponding xml configuration if you are not using Java configuration. I won’t cover this part in the post since it is already too long 🙂

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s