DEV Community

Vincent A. Cicirello
Vincent A. Cicirello

Posted on

How to Use Maven Profiles to Selectively Activate Plugins and Other Configuration from the Command Line

Apache Maven is the software project management and build tool that is preferred by many Java and Kotlin developers, as well as those developing for the JVM more generally. In this post, I explain how you can define profiles in your Maven pom.xml that you can selectively activate from the command line at the time of your build. There are a variety of reasons that you might use this feature. For example, perhaps you deploy build artifacts to different Maven repositories, each requiring different configuration. Or perhaps there is a plugin that you only wish to run during some (but not all) builds. Profiles can be used to accomplish both of these.

We'll use two examples. In the first, we'll use a profile to enable selectively activating the jacoco-maven-plugin to generate a code coverage report during the Maven test phase, but only if the profile was activated at the command line. In the second example, we'll use the case of deploying artifacts to both the Maven Central Repository as well as GitHub Packages.

Table of Contents:

How to Specify Profiles

Before jumping into specific examples, let's begin with an explanation of how to define profiles in your pom.xml. To do so, you will add a profiles section to your pom.xml with the following:



<profiles>

</profiles>


Enter fullscreen mode Exit fullscreen mode

Within that profiles section, you then add one or more profiles. We're going to focus on profiles that are activated with command line options. To use that feature, we will need to give each of our profiles an id. The profile's id is what we'll use at the command line to activate it.



<profiles>
    <profile>
        <id>profileOne</id>

    </profile>
    <profile>
        <id>profileTwo</id>

    </profile>
    <profile>
        <id>profileThree</id>

    </profile>
</profiles>


Enter fullscreen mode Exit fullscreen mode

In the above, we have three profiles with the ids profileOne, profileTwo, and profileThree. To activate a profile from the command line at the time of your build, you use the command line option -P. For example, the following command activates profileTwo while executing the package lifecycle phase:



mvn package -PprofileTwo


Enter fullscreen mode Exit fullscreen mode

The next couple sections of this post provide more specific examples of what you might use a profile for.

Profile to Enable (De)Activating a Plugin at Build Time

One of the ways that I sometimes use Maven profiles is if there is a plugin that I only want to use sometimes. Rather than configuring it in the usual <build></build> section of the pom.xml, you instead configure it within an additional <build></build> section within a profile. Here is a general example of what it will look like:



<profiles>
    <profile>
        <id>profileOne</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>com.example</groupId>
                    <artifactId>example-plugin</artifactId>
                    <version>1.2.3</version>

                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>


Enter fullscreen mode Exit fullscreen mode

Above we see a profile named profileOne that includes version 1.2.3 of a plugin named example-plugin with a groupId of com.example. Any configuration required by that plugin would be inserted there as well. Note that our pom.xml will also have the usual <build></build> section elsewhere that we'd use to configure all of our other plugins.

One specific example where I regularly use a profile in this way is for configuring code coverage. In all of my Java projects, I use JaCoCo for generating code coverage reports. I use JaCoCo during the Maven test phase. However, while developing I find it useful at times to exclude coverage reporting to reduce the build time. But in my CI/CD workflows in GitHub Actions, I activate the code coverage profile during pull-requests and pushes to the default branch. For pull-requests, my GitHub Actions workflow comments the code coverage on the PR and uploads the coverage report as a workflow artifact, where I can inspect it as necessary. And during a push to the default branch, my workflow updates coverage badges to keep them up to date with the current state of the default branch. I can also activate the code coverage profile locally while developing, such as prior to submitting a pull-request, to ensure that I didn't miss testing something.

Here is a specific example from a library that I develop called Chips-n-Salsa where I have configured JaCoCo code coverage using a Maven profile in this way.



<profiles>
    <profile>
        <id>coverage</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.jacoco</groupId>
                    <artifactId>jacoco-maven-plugin</artifactId>
                    <version>0.8.8</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>prepare-agent</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>generate-code-coverage-report</id>
                            <phase>test</phase>
                            <goals>
                                <goal>report</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>


Enter fullscreen mode Exit fullscreen mode

In the above example, JaCoCo is configured to generate a coverage report during the Maven test phase. But because I've put it within a profile (here named coverage), rather than in the regular <build></build> section, we need to activate the coverage profile from the command line at the time of the build, with the following:



mvn test -Pcoverage


Enter fullscreen mode Exit fullscreen mode

Or, we can use mvn package or anything else that includes the test phase, with something like:



mvn package -Pcoverage


Enter fullscreen mode Exit fullscreen mode

Profiles for Deploying to Multiple Maven Repositories

Are plugins the only thing that you can configure within a Maven profile? No, they are not. They are also highly useful if you regularly deploy artifacts to multiple Maven repositories. Here is an example:



<profiles>
    <profile>
        <id>profileOne</id>
        <distributionManagement>
            <repository>
                <id>repo1</id>
                <name>Name of Repo 1</name>
                <url>https://example.com/url/of/repo1</url>
            </repository>
        </distributionManagement>
    </profile>
    <profile>
        <id>profileTwo</id>
        <distributionManagement>
            <repository>
                <id>repo2</id>
                <name>Name of Repo 2</name>
                <url>https://example.com/url/of/repo2</url>
            </repository>
        </distributionManagement>
    </profile>
</profiles>


Enter fullscreen mode Exit fullscreen mode

The above example defines two profiles, profileOne and profileTwo, for deploying artifacts to two different Maven repositories. The <distributionManagement> section of a pom.xml only allows specifying one <repository> (although you can also specify a <snapshotRepository>). Profiles offer a way to configure more than one, such that we activate at most one from the command line during deployment.

With the above example, if we want to deploy to repo1, we use:



mvn deploy -PprofileOne


Enter fullscreen mode Exit fullscreen mode

And if we want to deploy to repo2, we use:



mvn deploy -PprofileTwo


Enter fullscreen mode Exit fullscreen mode

Let's look at a real example, again from Chips-n-Salsa, where I publish artifacts of the library on both Maven Central as well as to GitHub Packages. We'll build up to the full example. First, consider the <distributionManagement> configuration below:



<profiles>
    <profile>
        <id>githubDeploy</id>
        <distributionManagement>
            <repository>
                <id>github</id>
                <name>GitHub cicirello Apache Maven Packages</name>
                <url>https://maven.pkg.github.com/cicirello/Chips-n-Salsa</url>
            </repository>
        </distributionManagement>
    </profile>
    <profile>
        <id>ossrhDeploy</id>
        <distributionManagement>
            <repository>
                <id>ossrh</id>
                <name>Central Repository OSSRH</name>
                <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
            </repository>
        </distributionManagement>
    </profile>
</profiles>


Enter fullscreen mode Exit fullscreen mode

So far this is just like the earlier generic example. However, we are not quite done. The githubDeploy profile is all that we need for GitHub Packages. However, we need a bit more for Maven Central. Specifically, there are a couple plugins that we'll need to add to the ossrhDeploy profile above. Maven Central requires that all of our artifacts are signed with GPG. So we'll need to configure the plugin maven-gpg-plugin. Additionally, for Maven Central, our artifacts will initially end up in a Sonatype staging repository. To avoid the need to login to manually release from staging, we'll configure the nexus-staging-maven-plugin to do that for us.

Here is the full example:



<profiles>
    <profile>
        <id>githubDeploy</id>
        <distributionManagement>
            <repository>
                <id>github</id>
                <name>GitHub cicirello Apache Maven Packages</name>
                <url>https://maven.pkg.github.com/cicirello/Chips-n-Salsa</url>
            </repository>
        </distributionManagement>
    </profile>
    <profile>
        <id>ossrhDeploy</id>
        <distributionManagement>
            <repository>
                <id>ossrh</id>
                <name>Central Repository OSSRH</name>
                <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
            </repository>
        </distributionManagement>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-gpg-plugin</artifactId>
                    <version>3.0.1</version>
                    <executions>
                        <execution>
                            <id>sign-artifacts</id>
                            <phase>verify</phase>
                            <goals>
                                <goal>sign</goal>
                            </goals>
                            <configuration>
                                <gpgArguments>
                                    <arg>--pinentry-mode</arg>
                                    <arg>loopback</arg>
                                </gpgArguments>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.sonatype.plugins</groupId>
                    <artifactId>nexus-staging-maven-plugin</artifactId>
                    <version>1.6.13</version>
                    <extensions>true</extensions>
                    <configuration>
                        <serverId>ossrh</serverId>
                        <nexusUrl>https://oss.sonatype.org/</nexusUrl>
                        <autoReleaseAfterClose>true</autoReleaseAfterClose>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>


Enter fullscreen mode Exit fullscreen mode

Given the above in the pom.xml, to deploy to Maven Central, we use:



mvn deploy -PossrhDeploy


Enter fullscreen mode Exit fullscreen mode

Or to instead deploy to GitHub Packages, we use:



mvn deploy -PgithubDeploy


Enter fullscreen mode Exit fullscreen mode

Live Example

To see a live example of both of these uses of Maven profiles, consult the pom.xml of one of my projects. Here is the GitHub repository:

GitHub logo cicirello / Chips-n-Salsa

A Java library of Customizable, Hybridizable, Iterative, Parallel, Stochastic, and Self-Adaptive Local Search Algorithms

Chips-n-Salsa - A Java library of customizable, hybridizable, iterative, parallel, stochastic, and self-adaptive local search algorithms

Chips-n-Salsa Mentioned in Awesome Machine Learning

Copyright (C) 2002-2024 Vincent A. Cicirello.

Website: https://chips-n-salsa.cicirello.org/

API documentation: https://chips-n-salsa.cicirello.org/api/






































Publications About the Library DOI
Packages and Releases
Maven Central GitHub release (latest by date)
Build Status
build docs CodeQL
JaCoCo Test Coverage
coverage branches coverage
Security
Snyk security score Snyk Known Vulnerabilities
DOI DOI
Other Information
GitHub style
Support
GitHub Sponsors Liberapay Ko-Fi

How to Cite

If you use this library in your research, please cite the following paper:

Cicirello, V. A., (2020). Chips-n-Salsa: A Java Library of Customizable, Hybridizable, Iterative, Parallel, Stochastic, and Self-Adaptive Local Search Algorithms. Journal of Open Source Software, 5(52), 2448, https://doi.org/10.21105/joss.02448 .

Overview

Chips-n-Salsa is a Java library of customizable, hybridizable, iterative, parallel, stochastic, and self-adaptive local search algorithms. The library includes implementations of several stochastic local search algorithms, including simulated annealing, hill climbers, as well as constructive search algorithms such as stochastic sampling. Chips-n-Salsa now also includes genetic algorithms as well as evolutionary algorithms more generally. The library very extensively supports simulated annealing. It includes several classes for representing solutions to a variety of optimization problems…




Where You Can Find Me

Follow me here on DEV:

Follow me on GitHub:

GitHub logo cicirello / cicirello

My GitHub Profile

Vincent A Cicirello

Vincent A. Cicirello

Sites where you can find me or my work
Web and social media Personal Website LinkedIn DEV Profile Stack Overflow profile StackExchange profile
Software development Github Maven Central PyPI Docker Hub
Publications Google Scholar ORCID DBLP ACM Digital Library IEEE Xplore ResearchGate arXiv
View Bibliometrics for My Research Publications My bibliometrics
View My Detailed GitHub Activity My GitHub Activity

If you want to generate the equivalent to the above for your own GitHub profile, check out the cicirello/user-statistician GitHub Action.




Or visit my website:

Vincent A. Cicirello - Professor of Computer Science

Vincent A. Cicirello - Professor of Computer Science at Stockton University - is a researcher in artificial intelligence, evolutionary computation, swarm intelligence, and computational intelligence, with a Ph.D. in Robotics from Carnegie Mellon University. He is an ACM Senior Member, IEEE Senior Member, AAAI Life Member, EAI Distinguished Member, and SIAM Member.

favicon cicirello.org

Top comments (0)