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
code
1. validate - Validate project structure 2. initialize - Initialize build state 3. generate-sources 4. process-sources 5. generate-resources 6. process-resources - Copy resources to output 7. compile - Compile source code 8. process-classes 9. generate-test-sources 10. process-test-sources 11. generate-test-resources 12. process-test-resources 13. test-compile - Compile test sources 14. process-test-classes 15. test - Run unit tests 16. prepare-package 17. package - Create JAR/WAR 18. pre-integration-test 19. integration-test - Run integration tests 20. post-integration-test 21. verify - Run verification checks 22. install - Install to local repo 23. deploy - Deploy to remote repo
Common Phase Commands
bash
# 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
code
1. pre-clean 2. clean - Delete target directory 3. post-clean
bash
# Clean build artifacts mvn clean # Clean specific directory mvn clean -DbuildDirectory=out
Site Lifecycle
code
1. pre-site 2. site - Generate documentation 3. post-site 4. site-deploy - Deploy documentation
bash
# Generate site mvn site # Generate and deploy site mvn site-deploy
Goals vs Phases
Executing Phases
bash
# Execute phase (runs all previous phases) mvn package
Executing Goals
bash
# Execute specific goal mvn compiler:compile mvn surefire:test mvn jar:jar # Multiple goals mvn dependency:tree compiler:compile
Phase-to-Goal Bindings
xml
<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
xml
<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
bash
# Activate by name mvn install -Pproduction # Multiple profiles mvn install -Pproduction,ci # Deactivate profile mvn install -P!development
Activation Triggers
xml
<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
xml
<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
properties
# application.properties
app.name=${project.name}
app.version=${project.version}
app.environment=${env}
build.timestamp=${maven.build.timestamp}
Build Customization
Source and Target Configuration
xml
<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
xml
<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
xml
<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
bash
# 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
xml
<!-- parent/pom.xml -->
<modules>
<module>common</module>
<module>api</module>
<module>service</module>
<module>web</module>
</modules>
Test Configuration
Surefire Plugin (Unit Tests)
xml
<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)
xml
<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
bash
# Skip unchanged modules mvn install -amd # Use build cache (requires Maven Daemon) mvnd install
Parallel Builds
xml
<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
bash
# Enable build cache (Maven 4+) mvn install -Dmaven.build.cache.enabled=true
Debugging Builds
Verbose Output
bash
# Debug mode mvn install -X # Error stacktrace mvn install -e # Quiet mode mvn install -q
Effective POM
bash
# View resolved POM mvn help:effective-pom # View effective settings mvn help:effective-settings # Active profiles mvn help:active-profiles
Dependency Analysis
bash
# Check plugin versions mvn versions:display-plugin-updates # Check dependency versions mvn versions:display-dependency-updates
Best Practices
- •Use Clean Builds - Run
mvn cleanbefore releases - •Consistent Versions - Lock plugin versions
- •Profile Isolation - Keep profiles focused
- •Fail Fast - Use
-ffin CI for quick feedback - •Parallel Builds - Use
-Tfor 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
yaml
- name: Build with Maven run: mvn -B clean verify -Pci - name: Release run: mvn -B deploy -Prelease -DskipTests
Jenkins Pipeline
groovy
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