Chirag's Blog

Maven Conditional Dependencies with Profiles

August 6, 2024

Maven profiles let you include dependencies only when a particular environment, platform, or build condition is active. Put the conditional dependency inside a <profile>, give the profile an ID, and select it with mvn package -P<profile-id>.

For example, this activates a production-only dependency:

<profile>
    <id>production</id>
    <dependencies>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.6</version>
        </dependency>
    </dependencies>
</profile>

Run it with mvn clean package -Pproduction. The rest of this guide builds a complete project and covers command-line, settings, environment, and operating-system activation.

How Maven profiles manage conditional dependencies

A Maven profile is a set of parameters that alters the default build. Profiles let you define different dependencies and configuration for development, testing, production, target platforms, or other build requirements.

Key Concepts:

Setting Up a Maven Project with Profiles

Let's walk through the process of setting up a Maven project that uses profiles for conditional dependency management.

Step 1: Create a New Maven Project

First, let's create a new Maven project using the command line:

mvn archetype:generate -DgroupId=com.example -DartifactId=profile-demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Output:

This command will create a new Maven project with a basic structure. Here is what the output should look like:

Output of the create new Maven project command

Now, let's take a look at the directory structure that Maven has created for us:

Directory Structure

Step 2: Configure pom.xml

Now, let's modify the pom.xml file to include profiles. We'll create two profiles: development and production, each with its own set of dependencies.

<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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>profile-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- Common dependencies -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <profiles>
        <profile>
            <id>development</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <dependencies>
                <dependency>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-simple</artifactId>
                    <version>1.7.32</version>
                </dependency>
            </dependencies>
        </profile>
        <profile>
            <id>production</id>
            <dependencies>
                <dependency>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                    <version>1.2.6</version>
                </dependency>
            </dependencies>
        </profile>
    </profiles>
</project>

In this configuration:

Step 3: Create Java Classes

Let's create a simple Java class that uses the logger:

package com.example;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class App {
    private static final Logger logger = LoggerFactory.getLogger(App.class);

    public static void main(String[] args) {
        logger.info("Hello, Maven Profiles!");
    }
}

Step 4: Build the Project

Now that we have set up our project with profiles, let's see how to use them.

Building with the Default Profile

To build the project with the default profile (development in our case), simply run:

mvn clean package

This will include the slf4j-simple logger in the build.

Building with a Specific Profile

To build the project with the production profile, use the -P flag:

mvn clean package -Pproduction

This will include the logback-classic logger in the build instead.

Advanced Profile Usage

Profiles can be activated in various ways:

  1. Command Line: As shown above, using -P<profile-id>.

For example, To activate the 'development' profile:

mvn clean package -Pdevelopment
  1. Maven Settings: In the settings.xml file:
<activeProfiles>
  <activeProfile>production</activeProfile>
</activeProfiles>
  1. Environment Variable: In the pom.xml:
<activation>
  <property>
    <name>env</name>
    <value>prod</value>
  </property>
</activation>

Then activate using: mvn clean package -Denv=prod

  1. OS Settings: Activate based on the operating system:
<activation>
  <os>
    <name>Windows 10</name>
    <family>Windows</family>
    <arch>amd64</arch>
    <version>10.0</version>
  </os>
</activation>

Resource Filtering:

Profiles can also be used for resource filtering. For example:

<profile>
    <id>development</id>
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <includes>
                    <include>application-dev.properties</include>
                </includes>
            </resource>
        </resources>
    </build>
</profile>

This will only include the application-dev.properties file when the development profile is active.

Conclusion

Maven Profiles provide a powerful way to manage conditional dependencies and configurations in your Java projects. By using profiles, you can easily switch between different build configurations for various environments or conditions. This flexibility allows for more maintainable and adaptable projects, especially when dealing with complex build requirements or multiple deployment scenarios.

References: