Maven is a powerful build tool for Java software projects. Actually, you can build software projects using other languages too, but Maven is developed in Java, and is thus historically used more for Java projects.
What is a Build Tool?
A build tool is a tool that automates everything related to building the software project. Building a software project typically includes one or more of these activities:
- Generating source code (if auto-generated code is used in the project).
- Generating documentation from the source code.
- Compiling source code.
- Packaging compiled code into JAR files or ZIP files.
- Installing the packaged code on a server, in a repository or somewhere else.
Installing Maven
To install Maven on your own system (computer), go to the Maven download page and follow the instructions there. In summary, what you need to do is:
- Set the
JAVA_HOME
environment variable to point to a valid Java SDK (e.g. Java 8). - Download and unzip Maven.
- Set the
M2_HOME
environment variable to point to the directory you unzipped Maven to. - Set the
M2
environment variable to point toM2_HOME/bin
(%M2_HOME%\bin
on Windows,$M2_HOME/bin
on unix). - Add
M2
to thePATH
environment variable (%M2%
on Windows,$M2
on unix). - Open a command prompt and type '
mvn -version
' (without quotes) and press enter.
After typing in the
mvn -version
command you should be able to see Maven execute, and the version number of Maven written out to the command prompt.Maven Overview - Core Concepts
Maven is centered around the concept of POM files (Project Object Model). A POM file is an XML representation of project resources like source code, test code, dependencies (external JARs used) etc. The POM contains references to all of these resources. The POM file should be located in the root directory of the project it belongs to.
Here is a diagram illustrating how Maven uses the POM file, and what the POM file primarily contains:
Overview of Maven core concepts. |
These concepts are explained briefly below to give you an overview, and then in more detail in their own sections later in this tutorial.
POM Files
When you execute a Maven command you give Maven a POM file to execute the commands on. Maven will then execute the command on the resources described in the POM.
When you execute a Maven command you give Maven a POM file to execute the commands on. Maven will then execute the command on the resources described in the POM.
Build Life Cycles, Phases and Goals
The build process in Maven is split up into build life cycles, phases and goals. A build life cycle consists of a sequence of build phases, and each build phase consists of a sequence of goals. When you run Maven you pass a command to Maven. This command is the name of a build life cycle, phase or goal. If a life cycle is requested executed, all build phases in that life cycle are executed. If a build phase is requested executed, all build phases before it in the pre-defined sequence of build phases are executed too.
The build process in Maven is split up into build life cycles, phases and goals. A build life cycle consists of a sequence of build phases, and each build phase consists of a sequence of goals. When you run Maven you pass a command to Maven. This command is the name of a build life cycle, phase or goal. If a life cycle is requested executed, all build phases in that life cycle are executed. If a build phase is requested executed, all build phases before it in the pre-defined sequence of build phases are executed too.
Dependencies and Repositories
One of the first goals Maven executes is to check the dependencies needed by your project. Dependencies are external JAR files (Java libraries) that your project uses. If the dependencies are not found in the local Maven repository, Maven downloads them from a central Maven repository and puts them in your local repository. The local repository is just a directory on your computer's hard disk. You can specify where the local repository should be located if you want to (I do). You can also specify which remote repository to use for downloading dependencies. All this will be explained in more detail later in this tutorial.
One of the first goals Maven executes is to check the dependencies needed by your project. Dependencies are external JAR files (Java libraries) that your project uses. If the dependencies are not found in the local Maven repository, Maven downloads them from a central Maven repository and puts them in your local repository. The local repository is just a directory on your computer's hard disk. You can specify where the local repository should be located if you want to (I do). You can also specify which remote repository to use for downloading dependencies. All this will be explained in more detail later in this tutorial.
Build Plugins
Build plugins are used to insert extra goals into a build phase. If you need to perform a set of actions for your project which are not covered by the standard Maven build phases and goals, you can add a plugin to the POM file. Maven has some standard plugins you can use, and you can also implement your own in Java if you need to.
Build plugins are used to insert extra goals into a build phase. If you need to perform a set of actions for your project which are not covered by the standard Maven build phases and goals, you can add a plugin to the POM file. Maven has some standard plugins you can use, and you can also implement your own in Java if you need to.
Build Profiles
Build profiles are used if you need to build your project in different ways. For instance, you may need to build your project for your local computer, for development and test. And you may need to build it for deployment on your production environment. These two builds may be different. To enable different builds you can add different build profiles to your POM files. When executing Maven you can tell which build profile to use.
Build profiles are used if you need to build your project in different ways. For instance, you may need to build your project for your local computer, for development and test. And you may need to build it for deployment on your production environment. These two builds may be different. To enable different builds you can add different build profiles to your POM files. When executing Maven you can tell which build profile to use.
Maven POM Files
A Maven POM file (Project Object Model) is an XML file that describe the resources of the project. This includes the directories where the source code, test source etc. is located in, what external dependencies (JAR files) your projects has etc.
Here is a minimal POM file:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jenkov</groupId> <artifactId>java-web-crawler</artifactId> <version>1.0.0</version> </project>
The above
groupId
, artifactId
and version
elements would result in a JAR file being built and put into the local Maven repository at the following path (directory and file name):MAVEN_REPO/com/jenkov/java-web-crawler/1.0.0/java-web-crawler-1.0.0.jar
Effective POM
With all this POM inheritance it may be hard to know what the total POM file looks like when Maven executes. The total POM file (result of all inheritance) is called the effective POM. You can get Maven to show you the effective POM using this command:
mvn help:effective-pom
Maven Settings File
Maven has two settings files. In the settings files you can configure settings for Maven across all Maven POM files. For instance, you can configure:
- Location of local repository
- Active build profile
- Etc.
The settings files are called
settings.xml
. The two settings files are located at:- The Maven installation directory:
$M2_HOME/conf/settings.xml
- The user's home directory:
${user.home}/.m2/settings.xml
Both files are optional. If both files are present, the values in the user home settings file overrides the values in the Maven installation settings file.
Running Maven
When you have installed Maven and have created a POM file and put the POM file in the root directory of your project, you can run Maven on your project.
Running Maven is done by executing the
mvn
command from a command prompt. When executing the mvn
command you pass the name of a build life cycle, phase or goal to it, which Maven then executes. Here is an example:mvn install
This command executes the build phase called
install
(part of the default
build life cycle), which builds the project and copies the packaged JAR file into the local Maven repository. Actually, this command executes all build phases before install
in the build phase sequence, before executing the install
build phase.
You can execute multiple build life cycles or phases by passing more than one argument to the
mvn
command. Here is an example:mvn clean install
This command first executes the
clean
build life cycle, which removes compiled classes from the Maven output directory, and then it executes the install
build phase.
You can also execute a Maven goal (a subpart of a build phase) by passing the build phase and goal name concatenated with a : in between, as parameter to the Maven command. Here is an example:
mvn dependency:copy-dependencies
This command executes the
copy-dependencies
goal of the dependency
build phase.Maven Directory Structure
Maven has a standard directory structure. If you follow that directory structure for your project, you do not need to specify the directories of your source code, test code etc. in your POM file.
Here are the most important directories:
- src - main - java - resources - webapp - test - java - resources - target
Project Dependencies
You specify your project dependencies inside the
dependencies
element in the POM file. Here is an example:<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jenkov.crawler</groupId> <artifactId>java-web-crawler</artifactId> <version>1.0.0</version> <dependencies> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.7.1</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> </build> </project>
Snapshot Dependencies
Snapshot dependencies are dependencies (JAR files) which are under development. Instead of constantly updating the version numbers to get the latest version, you can depend on a snapshot version of the project. Snapshot versions are always downloaded into your local repository for every build, even if a matching snapshot version is already located in your local repository. Always downloading the snapshot dependencies assures that you always have the latest version in your local repository, for every build.
You can tell Maven that your project is a snapshot version simply by appending
-SNAPSHOT
to the version number in the beginning of the POM (where you also set the groupId
and artifactId
). Here is a version
element example:<version>1.0-SNAPSHOT</version>
Maven Repositories
Maven repositories are directories of packaged JAR files with extra meta data. The meta data are POM files describing the projects each packaged JAR file belongs to, including what external dependencies each packaged JAR has. It is this meta data that enables Maven to download dependencies of your dependencies recursively, until the whole tree of dependencies is download and put into your local repository.
Maven repositories are covered in more detail in the Maven Introduction to Repositories, but here is a quick overview.
Maven has three types of repository:
- Local repository
- Central repository
- Remote repository
Maven searches these repositories for dependencies in the above sequence. First in the local repository, then in the central repository, and third in remote repositories if specified in the POM.
Here is a diagram illustrating the three repository types and their location:
Maven Repository Types and Location. |
Maven Build Life Cycles, Phases and Goals
When Maven builds a software project it follows a build life cycle. The build life cycle is divided into build phases, and the build phases are divided into build goals. Maven build life cycles, build phases and goals are described in more detail in the Maven Introduction to Build Phases, but here I will give you a quick overview.
Build Life Cycles
Maven has 3 built-in build life cycles. These are:
Maven has 3 built-in build life cycles. These are:
- default
- clean
- site
Build Phases
Each build life cycle is divided into a sequence of build phases, and the build phases are again subdivided into goals. Thus, the total build process is a sequence of build life cycle(s), build phases and goals.
Each build life cycle is divided into a sequence of build phases, and the build phases are again subdivided into goals. Thus, the total build process is a sequence of build life cycle(s), build phases and goals.
Build Phase | Description |
validate | Validates that the project is correct and all necessary information is available. This also makes sure the dependencies are downloaded. |
compile | Compiles the source code of the project. |
test | Runs the tests against the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployed. |
package | Packs the compiled code in its distributable format, such as a JAR. |
install | Install the package into the local repository, for use as a dependency in other projects locally. |
deploy | Copies the final package to the remote repository for sharing with other developers and projects. |
Build Goals
Build goals are the finest steps in the Maven build process. A goal can be bound to one or more build phases, or to none at all. If a goal is not bound to any build phase, you can only execute it by passing the goals name to the
Build goals are the finest steps in the Maven build process. A goal can be bound to one or more build phases, or to none at all. If a goal is not bound to any build phase, you can only execute it by passing the goals name to the
mvn
command. If a goal is bound to multiple build phases, that goal will get executed during each of the build phases it is bound to.Maven Build Profiles
Maven build profiles enable you to build your project using different configurations. Instead of creating two separate POM files, you can just specify a profile with the different build configuration, and build your project with this build profile when needed.
You can read the full story about build profiles in the Maven POM reference under Profiles. Here I will give you a quick overview though.
Maven build profiles are specified inside the POM file, inside the
profiles
element. Each build profile is nested inside a profile
element. Here is an example:<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jenkov.crawler</groupId> <artifactId>java-web-crawler</artifactId> <version>1.0.0</version> <profiles> <profile> <id>test</id> <activation>...</activation> <build>...</build> <modules>...</modules> <repositories>...</repositories> <pluginRepositories>...</pluginRepositories> <dependencies>...</dependencies> <reporting>...</reporting> <dependencyManagement>...</dependencyManagement> <distributionManagement>...</distributionManagement> </profile> </profiles> </project>
A build profile describes what changes should be made to the POM file when executing under that build profile. This could be changing the applications configuration file to use etc. The elements inside the
profile
element will override the values of the elements with the same name further up in the POM.
Inside the
profile
element you can see a activation
element. This element describes the condition that triggers this build profile to be used. One way to choose what profile is being executed is in the settings.xml
file. There you can set the active profile. Another way is to add -P profile-name
to the Maven command line.Maven Plugins
Maven plugins enable you to add your own actions to the build process. You do so by creating a simple Java class that extends a special Maven class, and then create a POM for the project. The plugin should be located in its own project.
Maven" is really just a core framework for a collection of Maven Plugins. In other words, plugins are where much of the real action is performed, plugins are used to: create jar files, create war files, compile code, unit test code, create project documentation, and on and on. Almost any action that you can think of performing on a project is implemented as a Maven plugin.
Plugins are the central feature of Maven that allow for the reuse of common build logic across multiple projects. They do this by executing an "action" (i.e. creating a WAR file or compiling unit tests) in the context of a project's description - the Project Object Model (POM). Plugin behavior can be customized through a set of unique parameters which are exposed by a description of each plugin goal (or Mojo).
One of the simplest plugins in Maven is the Clean Plugin. The Maven Clean plugin (maven-clean-plugin) is responsible for removing the target directory of a Maven project. When you run "mvn clean", Maven executes the "clean" goal as defined in the Clean plug-in, and the target directory is removed. The Clean plugin defines a parameter which can be used to customize plugin behavior, this parameter is called outputDirectory and it defaults to ${project.build.directory}.
What is a Mojo ?
A Mojo is really just a goal in Maven, and plug-ins consist of any number of goals (Mojos). Mojos can be defined as annotated Java classes or Beanshell script. A Mojo specifies metadata about a goal: a goal name, which phase of the lifecycle it fits into, and the parameters it is expecting.
Mojo term was introduced in Maven 2 as a complete rework on how to write plugins (see below for more details on Maven 1.x plugins comparison).
MOJO is a play on POJO (Plain-old-Java-object), substituting "Maven" for "Plain".
Custom Plugin can be created with the help of MOJO.