Introduction to the Build Lifecycle
Build Lifecycle Basics
Maven is based around the central concept of a build lifecycle. What this means is that the process for building and distributing a particular artifact (project) is clearly defined.
There are three built-in build lifecycles: default, clean and site. The default lifecycle handles your project deployment, the clean lifecycle handles project cleaning, while the site lifecycle handles the creation of your project’s site documentation.
A Build Lifecycle is Made Up of Phases
Each of these build lifecycles is defined by a different list of build phases, wherein a build phase represents a stage in the lifecycle.
The clean lifecycle comprises of the following phases:
pre-clean- execute processes needed prior to the actual project cleaningclean- remove all files generated by the previous buildpost-clean- execute processes needed to finalize the project cleaning
Here are some of the most important phases in the default lifecycle:
validate- validate the project is correct and all necessary information is availablecompile- compile the source code of the projecttest- test the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployedpackage- take the compiled code and package it in its distributable format, such as a JAR.verify- run any checks on results of integration tests to ensure quality criteria are metinstall- install the package into the local repository, for use as a dependency in other projects locallydeploy- done in the build environment, copies the final package to the remote repository for sharing with other developers and projects.
These lifecycle phases (plus the other lifecycle phases not shown here) are executed sequentially to complete the default lifecycle.
The Site lifecycle comprises of the following phases:
pre-siteexecute processes needed prior to the actual project site generationsitegenerate the project’s site documentationpost-siteexecute processes needed to finalize the site generation, and to prepare for site deploymentsite-deploydeploy the generated site documentation to the specified web server
Usual Command Line Calls
Phases are executed in a specific order. This means that if we run a specific phase using the command:
|
|
This won’t only execute the specified phase but all the preceding phases as well. When a phase is given, Maven will execute every phase in the sequence up to and including the one defined.
In a build environment, use the following call to cleanly build and deploy artifacts into the shared repository.
|
|
Maven executes clean, then executes deploy (including all of the prior build phase steps).
A Build Phase is Made Up of Plugin Goals
A plugin goal represents a specific task (finer than a build phase) which contributes to the building and managing of a project. It may be bound to zero or more build phases. A goal not bound to any build phase could be executed outside of the build lifecycle by direct invocation. The order of execution depends on the order in which the goal(s) and the build phase(s) are invoked.
|
|
Some Phases Are Not Usually Called From the Command Line
The phases named with hyphenated-words (pre-*, post-*, or process-*) are not usually directly called from the command line.
Setting Up Your Project to Use the Build Lifecycle
Packaging
The first, and most common way, is to set the packaging for your project via the equally named POM element <packaging>. Some of the valid packaging values are jar, war, ear and pom. If no packaging value has been specified, it will default to jar.
Each packaging contains a list of goals to bind to a particular phase.
Note that for some packaging types to be available, you may also need to include a particular plugin in the <build> section of your POM and specify <extensions>true</extensions> for that plugin.
Plugins
The second way to add goals to phases is to configure plugins in your project. Plugins are artifacts that provide goals to Maven. Furthermore, a plugin may have one or more goals wherein each goal represents a capability of that plugin, plugins can contain information that indicates which lifecycle phase to bind a goal to.
The goals that are configured will be added to the goals already bound to the lifecycle from the packaging selected. If more than one goal is bound to a particular phase, the order used is that those from the packaging are executed first, followed by those configured in the POM. Note that you can use the <executions> element to gain more control over the order of particular goals.
For example, let’s say you have a goal display:time that echos the current time to the commandline, and you want it to run in the process-test-resources phase to indicate when the tests were started. This would be configured like so:
|
|
We can use the following command to list all goals in a specific plugin:
|
|
For example, to list all goals in the Failsafe plugin:
|
|
To run a specific goal, without executing its entire phase (and the preceding phases) we can use the command:
|
|
Building a Maven Project
To build a Maven project, we need to execute one of the life cycles by running one of their phases:
|
|
This will execute the entire default lifecycle. Alternatively, we can stop at the install phase:
|
|
But usually we’ll use the command:
|
|
To clean the project first – by running the clean lifecycle – before the new build.
We can also run only a specific goal of the plugin:
|
|
Introduction to the POM
What is a POM?
A Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project and configuration details used by Maven to build the project. It contains default values for most projects.
Super POM
The Super POM is Maven’s default POM. All POMs extend the Super POM unless explicitly set, meaning the configuration specified in the Super POM is inherited by the POMs you created for your projects.
Minimal POM
The minimum requirement for a POM are the following:
projectrootmodelVersion- should be set to 4.0.0groupId- the id of the project’s group.artifactId- the id of the artifact (project)version- the version of the artifact under the specified group
Project Inheritance
Elements in the POM that are merged are the following:
- dependencies
- developers and contributors
- plugin lists (including reports)
- plugin executions with matching ids
- plugin configuration
- resources
The Scenario 1
And let us specify their directory structure as the following:
|
|
com.mycompany.app:my-module:1’s POM
|
|
With this setup, our module can now inherit some of the properties of our parent POM.
The Scenario 2
|
|
To address this directory structure (or any other directory structure), we would have to add the <relativePath> element to our parent section.
|
|
Project Aggregation
Project Aggregation is similar to Project Inheritance. But instead of specifying the parent POM from the module, it specifies the modules from the parent POM. By doing so, the parent project now knows its modules, and if a Maven command is invoked against the parent project, that Maven command will then be executed to the parent’s modules as well. To do Project Aggregation, you must do the following:
- Change the parent POMs packaging to the value “pom”.
- Specify in the parent POM the directories of its modules (children POMs).
The Scenario 1
directory structure
|
|
If we are to aggregate my-module into my-app, we would only have to modify my-app.
|
|
Now, whenever a Maven command processes com.mycompany.app:my-app:1, that same Maven command would be ran against com.mycompany.app:my-module:1 as well.
The Scenario 2
directory structure:
|
|
|
|
Project Inheritance vs Project Aggregation
If you have several Maven projects, and they all have similar configurations, you can refactor your projects by pulling out those similar configurations and making a parent project. Thus, all you have to do is to let your Maven projects inherit that parent project, and those configurations would then be applied to all of them.
And if you have a group of projects that are built or processed together, you can create a parent project and have that parent project declare those projects as its modules. By doing so, you’d only have to build the parent and the rest will follow.
But of course, you can have both Project Inheritance and Project Aggregation.
Project Interpolation and Variables
One of the practices that Maven encourages is don’t repeat yourself. However, there are circumstances where you will need to use the same value in several different locations. To assist in ensuring the value is only specified once, Maven allows you to use both your own and pre-defined variables in the POM.
For example, to access the project.version variable, you would reference it like so:
|
|
Available Variables
Project Model Variables
Any field of the model that is a single value element can be referenced as a variable. For example, ${project.groupId}, ${project.version}, ${project.build.sourceDirectory} and so on.
Special Variables
${project.basedir}, ${project.baseUri}, ${maven.build.timestamp} and so on.
Properties
You are also able to reference any properties defined in the project as a variable.
|
|