Apache Maven

Cheatsheet

Search for a specific dependency

Download all dependencies and plugins

  • mvn dependency:go-offline / mvndg

Project specific Maven config

Lifecycle Reference

Specify dependency version range

<dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>maven-core</artifactId>
    <version>[3.0,)</version>   <!-- 3.0 (inclusive) and above -->
</dependency

Download dependenc(ies) adhoc from remote repo to local repo

mvn dependency:get -DremoteRepositories=http://repo1.maven.org/maven2/ \
                   -DgroupId=junit \
                   -DartifactId=junit \
                   -Dversion=4.8.2 \
                   -Dtransitive=false

Copy dependencies to target folder

mvn dependency:copy-dependencies

or

Config in pom.xml

<plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>${maven-dependency-plugin.version}</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/dependency</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

List all classes in an artifact

Can be used to determine if a Java class is in an artifact.

mvn dependency:list-classes -Dartifact=$groupId:$artifactId:$version

Example

> mvn dependency:list-classes -Dartifact=org.slf4j:slf4j-api:2.0.0
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------< cq.playground:playground.spring-kafka >----------------
[INFO] Building playground.spring-kafka 0.1-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- dependency:3.6.1:list-classes (default-cli) @ playground.spring-kafka ---
[INFO] org.slf4j.ILoggerFactory
[INFO] org.slf4j.IMarkerFactory
[INFO] org.slf4j.Logger
[INFO] org.slf4j.LoggerFactory
[INFO] org.slf4j.LoggerFactoryFriend
[INFO] org.slf4j.MDC$1
[INFO] org.slf4j.MDC$MDCCloseable
[INFO] org.slf4j.MDC
[INFO] org.slf4j.Marker
[INFO] org.slf4j.MarkerFactory
[INFO] org.slf4j.event.DefaultLoggingEvent
[INFO] org.slf4j.event.EventConstants
[INFO] org.slf4j.event.EventRecordingLogger
[INFO] org.slf4j.event.KeyValuePair
[INFO] org.slf4j.event.Level
[INFO] org.slf4j.event.LoggingEvent
[INFO] org.slf4j.event.SubstituteLoggingEvent
[INFO] org.slf4j.helpers.AbstractLogger
[INFO] org.slf4j.helpers.BasicMDCAdapter$1
[INFO] org.slf4j.helpers.BasicMDCAdapter
[INFO] org.slf4j.helpers.BasicMarker
[INFO] org.slf4j.helpers.BasicMarkerFactory
[INFO] org.slf4j.helpers.CheckReturnValue
[INFO] org.slf4j.helpers.FormattingTuple
[INFO] org.slf4j.helpers.LegacyAbstractLogger
[INFO] org.slf4j.helpers.MarkerIgnoringBase
[INFO] org.slf4j.helpers.MessageFormatter
[INFO] org.slf4j.helpers.NOPLogger
[INFO] org.slf4j.helpers.NOPLoggerFactory
[INFO] org.slf4j.helpers.NOPMDCAdapter
[INFO] org.slf4j.helpers.NOP_FallbackServiceProvider
[INFO] org.slf4j.helpers.NamedLoggerBase
[INFO] org.slf4j.helpers.NormalizedParameters
[INFO] org.slf4j.helpers.SubstituteLogger
[INFO] org.slf4j.helpers.SubstituteLoggerFactory
[INFO] org.slf4j.helpers.SubstituteServiceProvider
[INFO] org.slf4j.helpers.ThreadLocalMapOfStacks
[INFO] org.slf4j.helpers.Util$1
[INFO] org.slf4j.helpers.Util$ClassContextSecurityManager
[INFO] org.slf4j.helpers.Util
[INFO] org.slf4j.spi.CallerBoundaryAware
[INFO] org.slf4j.spi.DefaultLoggingEventBuilder$1
[INFO] org.slf4j.spi.DefaultLoggingEventBuilder
[INFO] org.slf4j.spi.LocationAwareLogger
[INFO] org.slf4j.spi.LoggerFactoryBinder
[INFO] org.slf4j.spi.LoggingEventAware
[INFO] org.slf4j.spi.LoggingEventBuilder
[INFO] org.slf4j.spi.MDCAdapter
[INFO] org.slf4j.spi.MarkerFactoryBinder
[INFO] org.slf4j.spi.NOPLoggingEventBuilder
[INFO] org.slf4j.spi.SLF4JServiceProvider
[INFO] META-INF.versions.9.module-info
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  53.555 s
[INFO] Finished at: 2025-01-14T16:33:52+11:00
[INFO] ------------------------------------------------------------------------

Modules

Multi module build

  • A child module can omit groupId and version as they are implicitly the same as the parent's.
  • Use ${project.version} reference sibling dependencies in a multi module build.
  • Use property revision to define and reference version will not trigger Maven warning (Maven 3.5+).
<!-- Parent POM -->
<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.apache</groupId>
        <artifactId>apache</artifactId>
        <version>18</version>
    </parent>
 
    <groupId>org.apache.maven.ci</groupId>
    <artifactId>ci-parent</artifactId>
    <version>${revision}</version>
 
    <name>First CI Friendly</name>
 
    <properties>
        <revision>1.0.0-SNAPSHOT</revision>
    </properties>
 
    <modules>
        <module>child1</module>
        <module>child2</module>
    </modules>
</project>
 
<!-- Child POM -->
<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.apache.maven.ci</groupId>
        <artifactId>ci-parent</artifactId>
        <version>${revision}</version>
    </parent>
 
    <!-- A child module can omit `groupId` and `version` as they are implicitly the same as the parent's. -->
    <artifactId>child1</artifactId>
 
    <dependencies>
        <dependency>
            <groupId>org.apache.maven.ci</groupId>
            <artifactId>child2</artifactId>
            <!-- Use ${project.version} reference sibling dependencies in a multi module build -->
            <version>${project.version}</version>
        </dependency>
    </dependencies>
</project>

Plugins

Finding the latest plugin or dependency versions for your modules

  • mvn versions:display-dependency-updates

  • mvn versions:display-plugin-updates

  • mvn versions:display-property-updates

Show help information for plugin goals

  • mvn <plugin_alias>:help [-Ddetail]

or

  • mvn help:describe -Dplugin=<GROUP_ID>:<ARTIFACT_ID> [-Ddetail]

Enforce minimum Maven version to ensure plugin compatibility

Surefire

Run a single test case

mvn test -Dtest=${TEST_CLASS_NAME}

Surefire - Run a single test method

mvn test -Dtest="${TEST_CLASS_NAME}#${TEST_METHOD_NAME}"

Surefire - JVM options to apply when running tests

<!-- pom.xml -->
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
    <argLine>
        --add-exports java.base/sun.security.x509=ALL-UNNAMED
        --add-exports java.base/sun.security.util=ALL-UNNAMED
    </argLine>
</configuration>

Adjust order of plugin goal execution bound to the same phase

Plugin goal execution in the same phase are executed in the declared order.

Use plugins without specifying Group ID

  • Add plugin's Group ID to settings.xml
<!-- settings.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <pluginGroups>
    <pluginGroup>PLUGIN_GROUP_ID</plugingroup>
  </pluginGroups>
</settings>

Environment

Override properties from command line

# Example
mvn -Drevision=2.0.0-SNAPSHOT clean package

Determine and specify JRE used to run Maven build

  • Maven uses JAVA_HOME as the JRE to run build.

  • Use mvn -v to determine the JRE that Maven uses.

  • Set JAVA_HOME before running a Maven build to use a specific JRE.

    e.g. JAVA_HOME=<JRE_path> mvn compile

    JRE used to run Maven

Parallel artifact download

export MAVEN_OPTS=-Dmaven.artifact.threads=3

Repo management

Artifact remote repo deployment

  • Maven Deploy plugin

    • Repo

      • Snapshot artifacts are deployed to snapshot repo specified by <snapshotRepository>

        Snapshot: <version>0.1-SNAPSHOT</version>

      • Non-snapshot artifacts are deployed to release repo specified by <repository>

        Non-snapshot: <version>0.1</version>

    • deploy:deploy Mojo (opens in a new tab)

      In most cases, this mojo is invoked when you call the deploy phase of the default build lifecycle: mvn deploy. It works even without adding the plugin to POM.

      To enable this mojo to function, you must include a valid <distributionManagement/> section POM, which at the minimum provides a <repository/> defining the remote repository location for your artifact. To separate snapshot artifacts from release artifacts, you can also specify a <snapshotRepository/> location.

Dependency resolution

  • Repo order (opens in a new tab)

    • Effective settings and local build POM, with profile taken into account, can easily be reviewed to see their repositories order with mvn help:effective-settings and mvn help:effective-pom -Dverbose.
  • Properties inheritance

    • Use mvn help:effective-pom -Dverbose to trace where the property is defined.

Repo configuration

<!-- Repo config in POM -->
<!-- Repos for artifact distribution -->
<distributionManagement>
    <!--
      Non-snapshot artifacts are deployed to release repo
      such as <version>0.1</version>
    -->
    <repository>
        <id>central</id>
        <name>maven-libs-release</name>
        <url>https://chrisqiu.jfrog.io/artifactory/maven-libs-release</url>
    </repository>
    <!--
      Snapshot artifacts are deployed to snapshot repo
      such as <version>0.1-SNAPSHOT</version>
    -->
    <snapshotRepository>
        <id>snapshots</id>
        <name>maven-libs-snapshot</name>
        <url>https://chrisqiu.jfrog.io/artifactory/maven-libs-snapshot</url>
    </snapshotRepository>
</distributionManagement>
 
<!-- Repos for dependency resolution -->
<repositories>
    <repository>
        <id>central</id>
        <name>maven-libs-release</name>
        <url>https://chrisqiu.jfrog.io/artifactory/maven-libs-release</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
    <repository>
        <id>snapshots</id>
        <name>maven-libs-snapshot</name>
        <url>https://chrisqiu.jfrog.io/artifactory/maven-libs-snapshot</url>
        <snapshots/>
    </repository>
</repositories>
<pluginRepositories>
    <pluginRepository>
        <id>central</id>
        <name>maven-libs-release</name>
        <url>https://chrisqiu.jfrog.io/artifactory/maven-libs-release</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </pluginRepository>
    <pluginRepository>
        <snapshots/>
        <id>snapshots</id>
        <name>maven-libs-snapshot</name>
        <url>https://chrisqiu.jfrog.io/artifactory/maven-libs-snapshot</url>
    </pluginRepository>
</pluginRepositories>

Repo authentication

<!--
  In Maven settings.xml, use id to associate with repo specified under distributionManagement, repositories, and pluginRepositories element
-->
<servers>
    <server>
        <id>central</id>
        <username>${env.ARTIFACTORY_USERNAME}</username>
        <password>${env.ARTIFACTORY_PASSWORD}</password>
    </server>
    <server>
        <id>snapshots</id>
        <username>${env.ARTIFACTORY_USERNAME}</username>
        <password>${env.ARTIFACTORY_PASSWORD}</password>
    </server>
</servers>

Flatten Maven Plugin