Mastering Maven Build Lifecycles: A Comprehensive Guide

Anil GulatiAnil Gulati
9 min read

Note: This article is a continuation of the previous article, Maven Dependency Resolution: The BF and Skipper Algorithm

In the realm of software development, efficient project management is the key to delivering exceptional results. Maven, the versatile project management tool, simplifies this process through its well-structured build lifecycles. In this article, we will embark on a journey through Maven’s build lifecycles, dissecting their phases and uncovering their potential to enhance your project management prowess.

Navigating the Build Lifecycles

A Build Lifecycle is a predefined sequence of phases that orchestrates the execution of specific goals. Each phase represents a crucial stage in the project’s lifecycle, and the associated goals are executed in a meticulously defined order. Let’s dive deeper into the fundamental phases of the Maven Build Lifecycle:

1. validate

In the validation phase, Maven ensures the correctness of your project’s configuration and structure. It checks that all the necessary information is available for the subsequent phases.

<!-- Example: Validating the Project -->
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.1</version>
            <executions>
                <execution>
                    <id>validate-phase</id>
                    <phase>validate</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                    <configuration>
                        <tasks>
                            <echo>Validating the project...</echo>
                        </tasks>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

2. compile

During the compile phase, Maven transforms your source code into compiled code, preparing it for subsequent stages.

<!-- Example: Compiling the Source Code -->
<build>
    <!-- ... -->
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <executions>
                <execution>
                    <id>compile-phase</id>
                    <phase>compile</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

3. test

In the test phase, Maven runs your unit tests on the compiled source code to ensure its quality. These tests shouldn’t rely on packaging or deployment.

<!-- Example: Running Unit Tests -->
<build>
    <!-- ... -->
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.0.0-M5</version>
            <executions>
                <execution>
                    <id>test-phase</id>
                    <phase>test</phase>
                    <goals>
                        <goal>test</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

4. package

The packaging phase involves taking the compiled code and packaging it into a distributable format, such as a JAR file.

<!-- Example: Packaging the Application -->
<build>
    <!-- ... -->
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.2.0</version>
            <executions>
                <execution>
                    <id>package-phase</id>
                    <phase>package</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

5. verify

In the verification phase, Maven runs checks on the results of integration tests to ensure they meet quality standards.

<!-- Example: Verifying Integration Tests -->
<build>
    <!-- ... -->
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-failsafe-plugin</artifactId>
            <version>3.0.0-M5</version>
            <executions>
                <execution>
                    <id>verify-phase</id>
                    <phase>verify</phase>
                    <goals>
                        <goal>verify</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

6. install

During the “install” phase, Maven installs the packaged artifacts into the local or remote Maven repository. These artifacts become accessible for use as dependencies in other projects.

<!-- Example: Installing the Artifacts -->
<build>
    <!-- ... -->
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-install-plugin</artifactId>
            <version>3.0.0-M1</version>
            <executions>
                <execution>
                    <id>install-phase</id>
                    <phase>install</phase>
                    <goals>
                        <goal>install</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

7. deploy

In the “deploy” phase, Maven copies the final package to a remote repository, making it available for sharing with other developers and projects.

xmlCopy code
<!-- Example: Deploying the Artifacts -->
<build>
    <!-- ... -->
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-deploy-plugin</artifactId>
            <version>3.0.0-M1</version>
            <executions>
                <execution>
                    <id>deploy-phase</id>
                    <phase>deploy</phase>
                    <goals>
                        <goal>deploy</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Maven Build Lifecycles in Action

Maven defines three standard lifecycles:

1. Clean Lifecycle

The Clean Lifecycle focuses on preparing your project by cleaning it before the build process. It consists of the following phases:

  • pre-clean: Executes processes needed before the actual project cleaning.

  • clean: Removes all files generated by the previous build.

  • post-clean: Executes processes needed to finalize the project cleaning.

You can trigger the Clean Lifecycle by running mvn clean. Maven will meticulously execute each of these phases, ensuring your project is pristine and ready for a fresh build.

2. Default (Build) Lifecycle

The Default Lifecycle is Maven’s workhorse, handling the complete build process. It comprises 21 phases, from validate to deploy. These phases are executed sequentially, and you can customize them to suit your project's specific requirements.

By attaching goals to these phases, you can extend and tailor the Default Lifecycle to your project’s unique needs. For instance, you can run unit tests, package your application, and perform various checks during the build.

3. Site Lifecycle

The Site Lifecycle is instrumental in generating documentation, reports, and deploying project websites. It includes phases like pre-site, site, post-site, and site-deploy, catering to your documentation and reporting needs.

Harnessing the Site Lifecycle allows you to create informative project websites, making your project’s documentation easily accessible to your team and stakeholders.

Unveiling the Role of Goals

While build phases define the high-level stages of a build lifecycle, the actual tasks within these phases are carried out by goals. A plugin goal represents a specific task that contributes to the project’s build and management. Each goal is bound to one or more build phases, dictating when it is executed.

Goal-Bound Build Phases

A goal can be bound to zero or more build phases. When a goal is not bound to any phase, it can be executed directly outside of the build lifecycle. The order of execution depends on the sequence of goals and phases specified.

Consider the following command:

mvn clean dependency:copy-dependencies package

In this command, clean and package are build phases, while dependency:copy-dependencies is a goal associated with the dependency plugin. When executed, Maven will execute the clean phase first, followed by the dependency:copy-dependencies goal, and finally, the package phase.

Moreover, if a goal is bound to multiple build phases, it will execute in all those phases.

Phase-Bound Goals

Conversely, a build phase can have zero or more goals bound to it. If a build phase lacks bound goals, it won’t execute. However, if one or more goals are bound to a phase, all those goals will execute when the phase is triggered.

It’s crucial to note that in Maven 2.0.5 and above, multiple goals bound to a phase are executed in the order specified in the POM. This allows fine-grained control over the build process.

Beyond the Command Line

While many phases are directly invoked from the command line, some phases with hyphenated names (e.g., pre-, post-, or process-*) are not typically called directly. These phases are responsible for sequencing the build and producing intermediate results that aren’t useful outside the build context.

For instance, phases like pre-integration-test and post-integration-test are vital for setting up and cleaning up the environment for integration tests. These phases facilitate tasks such as environment configuration, code coverage analysis, and integration test container management.

Configuring Your Project for the Build Lifecycle

Now that you understand the essentials of build phases, goals, and lifecycles, you may wonder how to assign tasks to each build phase effectively. Two primary methods enable you to do this:

1. Packaging

The first method involves setting the packaging for your project. The <packaging> element in your project's POM file determines the default goals bound to each phase. Depending on the packaging type (e.g., JAR, WAR, EAR), Maven associates a specific set of goals with the build phases.

For example, a project with packaging set to jar will have a default set of goals bound to the build phases, including compiling, testing, packaging, and more.

2. Plugins

The second method relies on configuring plugins within your project. Plugins are artifacts that provide Maven with additional goals to execute during the build. Each plugin may offer one or more goals, each representing a specific capability of that plugin.

To customize the build process, configure plugins in your project’s POM file. Specify the goals you want to execute and bind them to specific build phases. This approach provides fine-grained control over your project’s build lifecycle.

<!-- Example: Configuring a Plugin and Binding Goals -->
<build>
    <!-- ... -->
    <plugins>
        <plugin>
            <groupId>org.example.myplugin</groupId>
            <artifactId>my-maven-plugin</artifactId>
            <version>1.0.0</version>
            <executions>
                <execution>
                    <id>my-goal-execution</id>
                    <phase>compile</phase>
                    <goals>
                        <goal>my-custom-goal</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

In this example, the my-custom-goal from the my-maven-plugin is bound to the compile phase, allowing you to introduce custom logic during compilation.

Navigating Maven Build Lifecycles

To help you navigate Maven’s build lifecycles, we’ve compiled a quick reference to the phases and their descriptions:

Clean Lifecycle

  • pre-clean: Execute processes needed before actual project cleaning.

  • clean: Remove all files generated by the previous build.

  • post-clean: Execute processes needed to finalize the project cleaning.

Default (Build) Lifecycle

  • validate: Validate the project’s correctness and information availability.

  • initialize: Initialize the build state, e.g., set properties or create directories.

  • generate-sources: Generate source code for inclusion in compilation.

  • process-sources: Process source code, e.g., filter values.

  • generate-resources: Generate resources for packaging.

  • process-resources: Copy and process resources into the destination directory.

  • compile: Compile the project’s source code.

  • process-classes: Post-process generated files from compilation.

  • generate-test-sources: Generate test source code for compilation.

  • process-test-sources: Process test source code, e.g., filter values.

  • generate-test-resources: Create resources for testing.

  • process-test-resources: Copy and process test resources into the test destination directory.

  • test-compile: Compile test source code into the test destination directory.

  • process-test-classes: Post-process generated files from test compilation.

  • test: Run tests using a suitable unit testing framework.

  • prepare-package: Perform operations necessary to prepare a package before packaging.

  • package: Package the compiled code into a distributable format (e.g., JAR).

  • pre-integration-test: Perform actions required before executing integration tests, such as setting up the environment.

  • integration-test: Process and deploy the package for integration testing.

  • post-integration-test: Perform actions required after integration tests, including cleanup.

  • verify: Run checks to verify the package’s validity and quality criteria.

  • install: Install the package into the local repository for local dependency use.

  • deploy: In an integration or release environment, copy the final package to a remote repository for sharing.

Site Lifecycle

  • pre-site: Execute processes needed before actual project site generation.

  • site: Generate the project’s site documentation.

  • post-site: Execute processes needed to finalize site generation and prepare for site deployment.

  • site-deploy: Deploy the generated site documentation to the specified web server.

Your Maven Journey Awaits

Mastering Maven’s Build Lifecycles is your gateway to effective project management in software development. By understanding and customizing these lifecycles, you gain unparalleled control over your projects, resulting in streamlined and organized development processes.

Throughout your Maven journey, remember that goals, bound to phases, empower you to perform specific tasks. By harnessing the full potential of Maven’s lifecycles and goals, you elevate your project management to new heights, delivering successful software projects with ease.

So, embark on your Maven adventure, explore its build lifecycles, and unlock the true potential of your software projects!

Enjoyed This Article?

If you enjoy reading this post, got help, knowledge through it, and want to support my efforts please clap this article and follow.
To explore more of my work, visit my portfolio at
anilgulati.com

10
Subscribe to my newsletter

Read articles from Anil Gulati directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Anil Gulati
Anil Gulati

Associate Software Engineer @YMSLI | Ex-SDE@Onelab Ventures | Full Stack Developer| Freelancer | Bibliophile | Technical Head @DITU ACM SC |