Maven POM - Build profiles per project

Maven POM

Introduction to Build Profiles

In my work experience till date, there had been requirements where we had to download dependencies, activate plugins based on the platform where we were planning to install/deploy our project. We needed a way to differentiate automatically which dependencies and plugins need to be downloaded to properly build the project depending on the platform.
There were cases where different customers had different platforms and to make our project work in that specific platform we had two ways to go forward with:
1. Ask customers if they can change the platform and use the one where we can install our project:
Doing this will not only make a bad remark on our company name but will also make a strong point that our engineers are not agile enough to make changes to suit customer demands. 
2. Make changes to our project in such a way that we support each and every platform our customers are using:
Doing this will not help us in making our project compatible with the current customer but will also help us in the future to support any other platform or to easily remove the support for platforms that are now deprecated.

The only way we could go forward was to make changes in our project such that we support each platform that our customers are using. To achieve this, we made use of maven build profiles.
Using Maven build profiles, we can add configurations very specific to each profile. During runtime, we can then provide the profile in the maven command to build the project thus downloading profile-specific dependencies.

Ways to define Profile

Following are the ways to define profile:

Per Project

Defined in the POM

Per User

Defined in Maven-settings (%USER_HOME%/.m2/settings.xml)

Global 

Defined in global Maven-settings (${maven.home}/conf/settings.xml)

Profile descriptor

Descriptor located in project basedir (profiles.xml) (no longer supported in Maven 3.0 and above; see Maven 3 compatibility notes)


In this blog, we will be exploring more on defining profiles per project.

Profile per project

Following is the way to define profiles in the POM:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0   
http://maven.apache.org/xsd/maven-4.0.0.xsd">
....
    <profiles>
        <profile>
            <id>profile-1</id>
        ...
        </profile>
            <profile>
                <id>profile-2</id>
            ...
            </profile>
        </profiles>
....
</project>

In the example above, there are 2 different profiles defined with unique id's and an activation tag. The need for an ID is to uniquely identify each profile. When running Maven command, we can provide profile id runtime so that maven builds the project according to the profile id passed.

mvn clean install -P profile-1


Along with id, the other way to differentiate between profiles is by using the activation tag where you can provide <property> tag depending on which you want to build the project.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0   
http://maven.apache.org/xsd/maven-4.0.0.xsd">
....
    <profiles>
        <profile>
            <id>profile-1</id>
            <activation>
                <property>
                    <name>Platform1</name>
                </property>
            </activation>
        ...
        </profile>
        <profile>
            <id>profile-2</id>
            <activation>
                <property>
                    <name>Platform2</name>
                </property>
            </activation>
        ...
        </profile>
    </profiles>
....
</project>


The maven command to activate profile depending on the property is:

mvn clean install –Dplatform1


In each of the profiles, following tags can be added:

<repositories>
<pluginRepositories>
<dependencies>
<plugins>
<properties> (not available in the main POM, used behind the scenes )
<modules>
<reports>
<reporting>
<dependencyManagement>
<distributionManagement>


There was a case in my project where I had multiple common dependencies between all the profiles that I had defined. I was looking out for ways to address this issue. I wanted a place to add these dependencies such that irrespective of the profile configured, these dependencies should still be installed as configured.
The answer to this was pretty simple. You now need to add the dependency tag outside of the profiles tag.

Following is how you do it:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0   
http://maven.apache.org/xsd/maven-4.0.0.xsd">
....
    <profiles>
        <profile>
            <id>profile-1</id>
            <activation>
                <property>
                    <name>Platform1</name>
                </property>
            </activation>
            <dependencies>
                <dependency>
                    <groupId>org.apache.maven</groupId>
                    <artifactId>maven-artifact-pf1</artifactId>
                    <version>1.1</version>
                </dependency>
            </dependencies>
        ...
        </profile>
        <profile>
            <id>profile-2</id>
            <activation>
                <property>
                    <name>Platform2</name>
                </property>
            </activation>
            <dependencies>
                <dependency>
                    <groupId>org.apache.maven</groupId>
                    <artifactId>maven-artifact-pf2</artifactId>
                    <version>1.4</version>
                </dependency>
            </dependencies>
        ...
        </profile>
    </profiles>
    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.0</version>
        </dependency>
    </dependencies>
....
</project>

As shown in the example above, any dependency or any other configuration that has to used as a common configuration across the POM, can be added just after the <profiles> tag.

Ignore a profile

There can be situations where different profiles can have same activation conditions. But depending on the requirement, either of the profiles needs to be ignored. This can be done via maven command.

Consider the following example:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0   
http://maven.apache.org/xsd/maven-4.0.0.xsd">
....
    <profiles>
        <profile>
            <id>profile-1</id>
            <activation>
                <property>
                    <name>platform1</name>
                </property>
            </activation>
        ...
        </profile>
        <profile>
            <id>profile-2</id>
            <activation>
                <property>
                    <name>platform1</name>
                </property>
            </activation>
        ...
        </profile>
        <profile>
            <id>profile-3</id>
            <activation>
                <property>
                    <name>!platform1</name>
                </property>
            </activation>
        ...
        </profile>
    </profiles>
....
</project>


To ignore profile-1 and profile-3, following will be the maven command:

mvn clean install –Dplatform1 –P !profile1

In the command above, profile-3 is ignored as the activation conditions are not meet. To ignore profile-1, we have to explicitly mention it as the activation condition for both profile-1 and profile-2 are meet.

Similarly to install profile-3, following is the command:

mvn clean install –D!platform1


References

Post a Comment

0 Comments