2.3. Maven Essentials
Overview
This section provides a quick introduction to some essential Maven concepts, enabling you to understand the fundamental ideas of the Maven build system.
Build lifecycle phases
Maven defines a standard set of phases in the build lifecycle, where the precise sequence of phases depends on what type of package you are building. For example, a JAR package includes the phases (amongst others):
compile
, test
, package
, and install
.
When running Maven, you normally specify the phase as an argument to the
mvn
command, in order to indicate how far you want the build to proceed. To get started, the following are the most commonly used Maven commands:
- Build the project, run the unit tests, and install the resulting package in the local Maven repository:
mvn install
- Clean the project (deleting temporary and intermediate files):
mvn clean
- Build the project and run the unit tests:
mvn test
- Build and install the project, skipping the unit tests:
mvn install -Dmaven.test.skip=true
- Build the project in offline mode:
mvn -o install
Offline mode (selected by the-o
option) is useful in cases where you know that you already have all of the required dependencies in your local repository. It prevents Maven from (unnecessarily) checking for updates to SNAPSHOT dependencies, enabling the build to proceed more quickly.
Maven directory structure
Example 2.1, “Standard Maven Directory Layout” shows the standard Maven directory layout. Most important is the Maven POM file,
pom.xml
, which configures the build for this Maven project.
Example 2.1. Standard Maven Directory Layout
ProjectDir/ pom.xml src/ main/ java/ ... resources/ META-INF/ spring/ *.xml OSGI-INF/ blueprint/ *.xml test/ java/ resources/ target/ ...
The project's Java source files must be stored under
ProjectDir/src/main/java/
and any resource files should be stored under ProjectDir/src/main/resources/
. In particular, Spring XML files (matching the pattern *.xml
) should be stored under the following directory:
ProjectDir/src/main/resources/META-INF/spring/
Blueprint XML files (matching the pattern
*.xml
) should be stored under the following directory:
ProjectDir/src/main/resources/OSGI-INF/blueprint/
Convention over configuration
An important principle of Maven is that of convention over configuration. What this means is that Maven's features and plug-ins are initialized with sensible default conventions, so that the basic functionality of Maven requires little or no configuration.
In particular, the location of the files within Maven's standard directory layout effectively determines how they are processed. For example, if you have a Maven project for building a JAR, all of the Java files under the
src/main/java
directory are automatically compiled and added to the JAR. All of the resource files under the src/main/resources
directory are also added to the JAR.
Note
Although it is possible to alter the default Maven conventions, this practice is strongly discouraged. Using non-standard Maven conventions makes your projects more difficult to configure and more difficult to understand.
Maven packaging type
Maven defines a variety of packaging types, which determine the basic build behavior. The most common packaging types are as follows:
jar
- (Default) This packaging type is used for JAR files and is the default packaging type in Maven.
bundle
- This packaging type is used for OSGi bundles. To use this packaging type, you must also configure the
maven-bundle-plugin
in the POM file. war
- This packaging type is used for WAR files. To use this packaging type, you must also configure the
maven-war-plugin
in the POM file. pom
- When you build with this packaging type, the POM file itself gets installed into the local Maven repository. This packaging type is typically used for parent POM files.
Maven artifacts
The end product of a Maven build is a Maven artifact (for example, a JAR file). Maven artifacts are normally installed into a Maven repository, from where they can be accessed and used as building blocks for other Maven projects (by declaring them as dependencies).
Maven coordinates
Artifacts are uniquely identified by a tuple of Maven coordinates, usually consisting of
groupId:artifactId:version
. For example, when deploying a Maven artifact into the Red Hat JBoss Fuse container, you can reference it using a Maven URI of the form, mvn:groupId/artifactId/version
.
For more details about Maven coordinates, see chapter "Building with Maven" in "Deploying into Apache Karaf".
Maven dependencies
The most common modification you will need to make to your project's POM file is adding or removing Maven dependencies. A dependency is simply a reference to a Maven artifact (typically a JAR file) that is needed to build and run your project. In fact, in the context of a Maven build, managing the collection of dependencies in the POM effectively takes the place of managing the collection of JAR files in a Classpath.
The following snippet from a POM file shows how to specify a dependency on the
camel-blueprint
artifact:
<project ...> ... <dependencies> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-blueprint</artifactId> <version>2.17.0.redhat-630xxx</version> <scope>provided</scope> </dependency> </dependencies> ... </project>
dependency element
The
dependency
element declares a dependency on the Maven artifact with coordinates org.apache.camel:camel-blueprint:6.3.0.redhat-xxx
. You can add as many dependency
elements as you like inside the dependencies
element.
dependency/scope element
The
scope
element is optional and provides some additional information about when this dependency is needed. By default (with the scope
element omitted), it is assumed that the dependency is needed at build time, at unit test time, and at run time. With scope
set to the value, provided
, the effect depends on what kind of artifact you are building:
- OSGi bundle—(when the POM's
packaging
element is specified asbundle
) theprovided
scope setting has no effect.
Transitive dependencies
To simplify the list of dependencies in your POM and to avoid having to list every single dependency explicitly, Maven employs a recursive algorithm to figure out the dependencies needed for your project.
For example, if your project, A, depends on B1 and B2; B1 depends on C1, C2, and C3; and B2 depends on D1 and D2; Maven will automatically pull in all of the explicitly and implicitly required dependencies at build time, constructing a classpath that includes the dependencies, B1, B2, C1, C2, C3, D1, and D2. Of these dependencies, only B1 and B2 appear explicitly in A's POM file. The rest of the dependencies—which are figured out by Maven—are known as transitive dependencies.
Maven repositories
A Maven repository is a place where Maven can go to search for artifacts. Because Maven repositories can be anywhere—and that includes anywhere on the Internet—the Maven build system is inherently distributed. The following are the main categories of Maven repository:
- Local repository—the local repository (by default, located at
~/.m2/repository
on *NIX orC:\Documents and Settings\UserName\.m2\repository
on Windows) is used by Maven as follows:- First search location—the local repository is the first place that Maven looks when searching for a dependency.
- Cache of downloaded dependencies—any artifacts that have ever been downloaded from a remote repository are stored permanently in the local repository, so that they can be retrieved quickly next time they are needed.
- Store of locally-built artifacts—any time that you build a local project (using
mvn install
), the resulting artifact gets stored in your local repository.
- Remote repository—Maven can also search for and download artifacts from remote repositories. By default, Maven automatically tries to download an artifact from remote repositories, if it cannot find the artifact in the local repository (you can suppress this behavior by specifying the
-o
flag—for example,mvn -o install
). - System repository—(Red Hat JBoss Fuse container only; not used by the
mvn
command-line tool) at run time, the Red Hat JBoss Fuse container can access artifacts from the JBoss Fuse system repository, which is located atInstallDir/system/
.
For more details about Maven repositories, see chapter "Building with Maven" in "Deploying into Apache Karaf".
Specifying remote repositories
If you need to customise the remote repositories accessible to Maven, you must separately configure the build-time and runtime repository locations, as follows:
- Build time—to customize the remote repositories accessible at build time (when running the
mvn
command), edit the Mavensettings.xml
file, at the following location:- *Nix: default location is
~/.m2/settings.xml
. - Windows: default location is
C:\Documents and Settings\UserName\.m2\settings.xml
.
- Run time—to customize the remote repositories accessible at run time (from within Red Hat JBoss Fuse container), edit the relevant property settings in the
InstallDir/etc/org.ops4j.pax.url.mvn.cfg
.