Maven Build Lifecycle
Master Maven's build lifecycle including phases, goals, profiles, and build customization for efficient Java project builds.
Overview
Maven's build lifecycle is a well-defined sequence of phases that execute in order. Understanding the lifecycle is essential for effective build configuration and optimization.
Default Lifecycle Phases
Complete Phase Order
- validate - Validate project structure
- initialize - Initialize build state
- generate-sources
- process-sources
- generate-resources
- process-resources - Copy resources to output
- compile - Compile source code
- process-classes
- generate-test-sources
- process-test-sources
- generate-test-resources
- process-test-resources
- test-compile - Compile test sources
- process-test-classes
- test - Run unit tests
- prepare-package
- package - Create JAR/WAR
- pre-integration-test
- integration-test - Run integration tests
- post-integration-test
- verify - Run verification checks
- install - Install to local repo
- deploy - Deploy to remote repo
Common Phase Commands
Compile only
mvn compile
Compile and run tests
mvn test
Create package
mvn package
Install to local repository
mvn install
Deploy to remote repository
mvn deploy
Clean and build
mvn clean install
Skip tests
mvn install -DskipTests
Skip test compilation and execution
mvn install -Dmaven.test.skip=true
Clean Lifecycle
- pre-clean
- clean - Delete target directory
- post-clean
Clean build artifacts
mvn clean
Clean specific directory
mvn clean -DbuildDirectory=out
Site Lifecycle
- pre-site
- site - Generate documentation
- post-site
- site-deploy - Deploy documentation
Generate site
mvn site
Generate and deploy site
mvn site-deploy
Goals vs Phases
Executing Phases
Execute phase (runs all previous phases)
mvn package
Executing Goals
Execute specific goal
mvn compiler:compile mvn surefire:test mvn jar:jar
Multiple goals
mvn dependency:tree compiler:compile
Phase-to-Goal Bindings
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.12.1</version> <executions> <execution> <id>compile-sources</id> <phase>compile</phase> <goals> <goal>compile</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
Build Profiles
Profile Definition
<profiles> <profile> <id>development</id> <activation> <activeByDefault>true</activeByDefault> </activation> <properties> <env>dev</env> <skip.integration.tests>true</skip.integration.tests> </properties> </profile>
<profile>
<id>production</id>
<properties>
<env>prod</env>
<skip.integration.tests>false</skip.integration.tests>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<debug>false</debug>
<optimize>true</optimize>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Profile Activation
Activate by name
mvn install -Pproduction
Multiple profiles
mvn install -Pproduction,ci
Deactivate profile
mvn install -P!development
Activation Triggers
<profile> <id>jdk17</id> <activation> <!-- Activate by JDK version --> <jdk>17</jdk> </activation> </profile>
<profile> <id>windows</id> <activation> <!-- Activate by OS --> <os> <family>windows</family> </os> </activation> </profile>
<profile> <id>ci</id> <activation> <!-- Activate by environment variable --> <property> <name>env.CI</name> <value>true</value> </property> </activation> </profile>
<profile> <id>with-config</id> <activation> <!-- Activate by file existence --> <file> <exists>src/main/config/app.properties</exists> </file> </activation> </profile>
Resource Filtering
Enable Filtering
<build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> <includes> <include>/*.properties</include> <include>/.xml</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <filtering>false</filtering> <excludes> <exclude>**/.properties</exclude> <exclude>**/*.xml</exclude> </excludes> </resource> </resources> </build>
Property Substitution
application.properties
app.name=${project.name} app.version=${project.version} app.environment=${env} build.timestamp=${maven.build.timestamp}
Build Customization
Source and Target Configuration
<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <maven.compiler.release>17</maven.compiler.release> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>
Custom Source Directories
<build> <sourceDirectory>src/main/java</sourceDirectory> <testSourceDirectory>src/test/java</testSourceDirectory> <resources> <resource> <directory>src/main/resources</directory> </resource> </resources> <testResources> <testResource> <directory>src/test/resources</directory> </testResource> </testResources> </build>
Final Name and Output
<build> <finalName>${project.artifactId}-${project.version}</finalName> <directory>target</directory> <outputDirectory>target/classes</outputDirectory> <testOutputDirectory>target/test-classes</testOutputDirectory> </build>
Multi-Module Builds
Reactor Options
Build all modules
mvn install
Build specific module and dependencies
mvn install -pl module-name -am
Build dependents of a module
mvn install -pl module-name -amd
Resume from specific module
mvn install -rf :module-name
Build in parallel
mvn install -T 4 mvn install -T 1C # 1 thread per CPU core
Module Order Control
<!-- parent/pom.xml --> <modules> <module>common</module> <module>api</module> <module>service</module> <module>web</module> </modules>
Test Configuration
Surefire Plugin (Unit Tests)
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.2.3</version> <configuration> <includes> <include>/*Test.java</include> <include>/*Tests.java</include> </includes> <excludes> <exclude>**/*IntegrationTest.java</exclude> </excludes> <parallel>methods</parallel> <threadCount>4</threadCount> <forkCount>1</forkCount> <reuseForks>true</reuseForks> </configuration> </plugin>
Failsafe Plugin (Integration Tests)
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <version>3.2.3</version> <executions> <execution> <goals> <goal>integration-test</goal> <goal>verify</goal> </goals> </execution> </executions> <configuration> <includes> <include>/*IT.java</include> <include>/*IntegrationTest.java</include> </includes> </configuration> </plugin>
Build Optimization
Incremental Builds
Skip unchanged modules
mvn install -amd
Use build cache (requires Maven Daemon)
mvnd install
Parallel Builds
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <fork>true</fork> <compilerArgs> <arg>-J-Xmx512m</arg> </compilerArgs> </configuration> </plugin> </plugins> </build>
Build Cache
Enable build cache (Maven 4+)
mvn install -Dmaven.build.cache.enabled=true
Debugging Builds
Verbose Output
Debug mode
mvn install -X
Error stacktrace
mvn install -e
Quiet mode
mvn install -q
Effective POM
View resolved POM
mvn help:effective-pom
View effective settings
mvn help:effective-settings
Active profiles
mvn help:active-profiles
Dependency Analysis
Check plugin versions
mvn versions:display-plugin-updates
Check dependency versions
mvn versions:display-dependency-updates
Best Practices
-
Use Clean Builds - Run mvn clean before releases
-
Consistent Versions - Lock plugin versions
-
Profile Isolation - Keep profiles focused
-
Fail Fast - Use -ff in CI for quick feedback
-
Parallel Builds - Use -T for multi-module projects
-
Skip Wisely - Know the difference between skip options
-
Resource Filtering - Enable only where needed
-
Test Separation - Unit tests in Surefire, integration in Failsafe
-
Reproducible Builds - Pin all plugin versions
-
Document Profiles - Comment profile purposes
Common Pitfalls
-
Skipping Tests - Don't skip tests in CI
-
SNAPSHOT in Release - Remove snapshots before release
-
Missing Clean - Stale files causing issues
-
Profile Conflicts - Overlapping profile configurations
-
Resource Filtering - Accidentally filtering binaries
-
Phase Confusion - Running wrong phase
-
Memory Issues - Insufficient heap for large builds
-
Reactor Order - Module dependency issues
CI/CD Integration
GitHub Actions
-
name: Build with Maven run: mvn -B clean verify -Pci
-
name: Release run: mvn -B deploy -Prelease -DskipTests
Jenkins Pipeline
stage('Build') { steps { sh 'mvn -B clean package -DskipTests' } } stage('Test') { steps { sh 'mvn -B test' } } stage('Integration Test') { steps { sh 'mvn -B verify -DskipUnitTests' } }
When to Use This Skill
-
Setting up new Maven projects
-
Customizing build phases
-
Creating build profiles for environments
-
Configuring test execution
-
Optimizing build performance
-
Debugging build failures
-
Setting up CI/CD pipelines
-
Multi-module project configuration