Maven projects, dependencies, builds, artifacts: all of
these are objects to be modeled and described. These objects are described
by an XML file called a Project Object Model. The
POM tells Maven what sort of project it is dealing with
and how to modify default behavior to generate output from source. In the
same way a Java web application has a web.xml that describes, configures, and
customizes the application, a Maven project is defined by the presence
of a pom.xml. It is a
descriptive declaration of a project for Maven; it is the figurative “map”
that Maven needs to understand what it is looking at when it builds your
project.
You could also think of the pom.xml as analogous to a Makefile or an Ant build.xml. When you are using
GNU make to build something like
MySQL, you’ll usually have a file named Makefile that contains explicit instructions
for building a binary from source. When you are using Apache Ant, you
likely have a file named build.xml
that contains explicit instructions for cleaning, compiling, packaging,
and deploying an application. make, Ant, and Maven
are similar in that they rely on the presence of a commonly named file
such as Makefile, build.xml, or pom.xml, but that is where the similarities
end. If you look at a Maven pom.xml,
the majority of the POM is going to deal with
descriptions: Where is the source code? Where are the resources? What is
the packaging? If you look at an Ant build.xml file, you’ll see something entirely
different. You’ll see explicit instructions for tasks such as compiling a
set of Java classes. The Maven POM is declarative, and
although you can certainly choose to include some procedural
customizations via the Maven Ant plugin, for the most part you will not
need to get into the gritty procedural details of your project’s
build.
The POM is also not specific to building Java projects. While most of the examples in this book are geared towards Java applications, there is nothing Java-specific in the definition of a Maven Project Object Model. While Maven's default plugins are targeted at building JAR artifacts from a set of source, tests, and resources, there is nothing preventing you from defining a POM for a project that contains C# sources and produces some proprietary Microsoft binary using Microsoft tools. Similarly, there is nothing stopping you from defining a POM for a technical book. In fact, the source for this book and this book's examples is captured in a multi-module Maven project which uses one of the many Maven Docbook plugins to apply the standard Docbook XSL to a series of chapter XML files. Others have created Maven plugins to build Adobe Flex code into SWCs and SWFs, and yet others have used Maven to build projects written in C.
We've established that the POM describes and declares, it is unlike Ant or Make in that it doesn't provide explicit instructions, and we've noted that POM concepts are not specific to Java. Diving into more specifics, take a look at Figure 3.1, “The Project Object Model” for a survey of the contents of a POM.
The POM contains four categories of description and configuration:
- General project information
-
This includes a project’s name, the URL for a project, the sponsoring organization, and a list of developers and contributors along with the license for a project.
- Build settings
-
In this section, we customize the behavior of the default Maven build. We can change the location of source and tests, we can add new plugins, we can attach plugin goals to the lifecycle, and we can customize the site generation parameters.
- Build environment
-
The build environment consists of profiles that can be activated for use in different environments. For example, during development you may want to deploy to a development server, whereas in production you want to deploy to a production server. The build environment customizes the build settings for specific environments and is often supplemented by a custom
settings.xmlin~/.m2. This settings file is discussed in Chapter 5, Build Profiles and in the section Section A.2, “Settings Details”. - POM relationships
-
A project rarely stands alone; it depends on other projects, inherits POM settings from parent projects, defines its own coordinates, and may include submodules.
Before we dive into some examples of
POMs, let's take a quick look at the Super
POM. All Maven project POMs extend
the Super POM, which defines a set of defaults shared
by all projects. This Super POM is a part of the
Maven installation and can be found in the
maven-2.2.1-uber.jar file in
${M2_HOME}/lib. If you look in this
JAR file, you will find a file named
pom-4.0.0.xml under the
org.apache.maven.project package. The Super
POM for Maven is shown in Example 3.1, “The Super POM”.
Example 3.1. The Super POM
<project>
<modelVersion>4.0.0</modelVersion>
<name>Maven Default Project</name>
<repositories>
<repository>
<id>central</id>
<name>Maven Repository Switchboard</name>
<layout>default</layout>
<url>http://repo1.maven.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Maven Plugin Repository</name>
<url>http://repo1.maven.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</pluginRepository>
</pluginRepositories>
<build>
<directory>${project.basedir}/target</directory>
<outputDirectory>
${project.build.directory}/classes
</outputDirectory>
<finalName>${project.artifactId}-${project.version}</finalName>
<testOutputDirectory>
${project.build.directory}/test-classes
</testOutputDirectory>
<sourceDirectory>
${project.basedir}/src/main/java
</sourceDirectory>
<scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>
${project.basedir}/src/test/java
</testSourceDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/resources</directory>
</testResource>
</testResources>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-2</version>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.4</version>
</plugin>
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<version>2.3.1</version>
</plugin>
<plugin>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.1</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.5</version>
</plugin>
<plugin>
<artifactId>maven-plugin-plugin</artifactId>
<version>2.4.3</version>
</plugin>
<plugin>
<artifactId>maven-rar-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.0-beta-8</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.3</version>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>2.0-beta-7</version>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.0.4</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.3</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1-alpha-2</version>
</plugin>
</plugins>
</pluginManagement>
<reporting>
<outputDirectory>target/site</outputDirectory>
</reporting>
</project>
The Super POM defines some standard configuration variables that are inherited by all projects. Those values are captured in the annotated sections:
|
The default Super POM defines a single
remote Maven repository with an ID of |
|
|
The central Maven repository also contains Maven plugins. The default plugin repository is the central Maven repository. Snapshots are disabled, and the update policy is set to “never,” which means that Maven will never automatically update a plugin if a new version is released. |
|
|
The |
|
|
Starting in Maven 2.0.9, default versions of core plugins have been provided in the Super POM. This was done to provide some stability for users that are not specifying versions in their POMs. |
All Maven POMs inherit defaults from the Super
POM (introduced earlier in the section Section 3.2., “The Super POM”). If you are just writing
a simple project that produces a JAR from some source
in src/main/java, want to run your
JUnit tests in src/test/java, and
want to build a project site using mvn
site, you don’t have to customize anything. All you would
need, in this case, is the simplest possible POM
shown in Example 3.2, “The Simplest POM”. This POM
defines a groupId, artifactId, and
version: the three required coordinates for every
project.
Example 3.2. The Simplest POM
<project> <modelVersion>4.0.0</modelVersion> <groupId>org.sonatype.mavenbook.ch08</groupId> <artifactId>simplest-project</artifactId> <version>1</version> </project>
Such a simple POM would be more than adequate
for a simple project—e.g., a Java library that produces a
JAR file. It isn’t related to any other projects, it
has no dependencies, and it lacks basic information such as a name and a
URL. If you were to create this file and then create
the subdirectory src/main/java with
some source code, running mvn package
would produce a JAR in target/simple-project-1.jar.
This simplest POM brings us to the
concept of the “effective POM.” Since
POMs can inherit configuration from other
POMs, you must always think of a Maven
POM in terms of the combination of the Super
POM, plus any parent POMs, and
finally the current project’s POM. Maven starts with
the Super POM and then overrides default
configuration with one or more parent POMs. Then it
overrides the resulting configuration with the current project’s
POM. You end up with an effective
POM that is a mixture of various
POMs. If you want to see a project’s effective
POM, you’ll need to run the
effective-pom goal in the Maven Help plugin, which
was introduced earlier in the section Section 6.3, “Using the Maven Help Plugin”. To run the
effective-pom goal, execute the following in a
directory with a pom.xml
file:
$ mvn help:effective-pom
Executing the effective-pom goal should print
out an XML document capturing the merge between the
Super POM and the POM from Example 3.2, “The Simplest POM”.
Maven is something of a chameleon; you can pick and choose the features you want to take advantage of. Some open source projects may value the ability to list developers and contributors, generate clean project documentation, and manage releases automatically using the Maven Release plugin. On the other hand, someone working in a corporate environment on a small team might not be interested in the distribution management capabilities of Maven nor the ability to list developers. The remainder of this chapter is going to discuss features of the POM in isolation. Instead of bombarding you with a 10-page listing of a set of related POMs, we’re going to focus on creating a good reference for specific sections of the POM. In this chapter, we discuss relationships between POMs, but we don’t illustrate such a project here.


