Java Maven Cheat Sheet
Covers a minimal pom.xml, the most common Maven CLI commands, dependency scopes, the default build lifecycle, and multi-module projects.
Minimal pom.xml
The essential elements every Maven project's POM needs.
<project xmlns="http://maven.apache.org/POM/4.0.0"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>my-app</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.10.0</version> <scope>test</scope> </dependency> </dependencies></project>
Common Maven CLI Commands
The commands used day-to-day for building and inspecting a project.
mvn compile # Compile source codemvn test # Run unit testsmvn package # Build a jar/war into target/mvn install # Install the artifact into the local ~/.m2 repomvn clean # Delete the target/ directorymvn clean install # Full clean rebuild + installmvn dependency:tree # Print the resolved dependency graphmvn -DskipTests package # Package without running testsmvn versions:display-dependency-updates # Check for newer dependency versions
Dependency Scopes
Control when and where a dependency is available on the classpath.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!-- default scope: compile - available everywhere --></dependency><dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <scope>test</scope> <!-- only on the test classpath --></dependency><dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <scope>provided</scope> <!-- supplied by the runtime container, not bundled --></dependency>
Build Lifecycle & Key Concepts
The phases and vocabulary behind every Maven build.
- validate to deploy- The default lifecycle runs validate, compile, test, package, verify, install, deploy in order; invoking one runs all prior phases too
- groupId:artifactId:version (GAV)- Uniquely identifies an artifact in a Maven repository
- Local repository (~/.m2)- Cache of downloaded/installed artifacts on the local machine
- Plugins- Goals like compiler:compile or surefire:test that phases bind to; configured under <build><plugins>
- Parent POM / <parent>- Lets a module inherit shared configuration and dependency versions
- <dependencyManagement>- Centralizes version numbers without adding the dependency itself, so child modules just declare groupId/artifactId
- Multi-module project- A parent pom.xml with <modules> lists sub-projects built together
Multi-Module Project Setup
A parent POM that aggregates and builds several sub-modules together.
<!-- parent pom.xml --><project> <groupId>com.example</groupId> <artifactId>parent-project</artifactId> <version>1.0.0</version> <packaging>pom</packaging> <modules> <module>api</module> <module>core</module> </modules></project>
Maven Wrapper (mvnw)
Pin the exact Maven version per project so builds are reproducible without a global install.
# Generate the wrapper (creates mvnw, mvnw.cmd, .mvn/wrapper/)mvn -N wrapper:wrapper -Dmaven=3.9.6# Commit mvnw, mvnw.cmd and .mvn/ to version control, then build with:./mvnw clean verify# CI pipelines should always call ./mvnw, never a globally installed mvn,# to guarantee every developer and CI runner uses the same Maven version.
Build Profiles
Activate different configuration per environment without separate POMs.
<profiles> <profile> <id>prod</id> <properties> <db.url>jdbc:postgresql://prod-host:5432/app</db.url> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skipTests>true</skipTests> </configuration> </plugin> </plugins> </build> </profile></profiles><!-- Activate with: mvn package -Pprod -->
Binding Plugin Goals to Lifecycle Phases
Attach a custom plugin execution to a specific build phase, e.g. shading a fat jar at package time.
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.5.1</version> <executions> <execution> <phase>package</phase> <goals><goal>shade</goal></goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>com.example.Main</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins></build>
Excluding Transitive Dependencies
Drop an unwanted transitive dependency, e.g. swapping Spring Boot's default logging backend.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId></dependency>
Advanced Maven Concepts
Vocabulary and mechanics that show up once projects grow beyond a single module.
- Reactor build order- In a multi-module build, Maven computes a dependency graph between modules and builds them in topological order, not declaration order
- -pl / -am / -amd flags- mvn -pl module-a -am builds module-a plus its upstream dependencies; -amd builds it plus downstream consumers
- BOM (Bill of Materials)- A POM with packaging=pom imported via <dependencyManagement><scope>import</scope> to pin a consistent set of versions (e.g. spring-boot-dependencies)
- Settings.xml- ~/.m2/settings.xml holds mirrors, server credentials, and proxy config kept out of the POM (and out of source control)
- Snapshot vs. release versions- A -SNAPSHOT version is re-resolved from the repo on every build; release versions are immutable once deployed
- mvn -X / -e- Run with debug output (-X) or full stack traces (-e) when diagnosing a failing build
- Effective POM- mvn help:effective-pom prints the fully resolved POM after inheritance, profiles, and interpolation are applied
Run mvn dependency:tree before adding a new library to spot version conflicts early - Maven silently resolves conflicting transitive dependency versions using 'nearest wins', which can pull in an unexpected (and sometimes broken) version without any warning.