Maven Project Object Model
So far in the handbook, we used bit and pieces of Maven POM (pom.xml) without going to deep into the subject. In this section, we formally introduce Maven Project Object Model (POM), one of the central concept of Maven. Having gone through other concepts such as lifecycle phase, plugins and goals, we can now put many aspects of POM into perspective than before.
In POM, we declare project’s identity and structure, configure builds, and relate projects to one another. The presence of a pom.xml file defines a Maven project.
Overview of POM Elements and Structure
The next listing shows the sections or blocks of Maven POM and the top level elements within the project element.
pom.xml
<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>
<!-- The Basics -->
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<packaging>...</packaging>
<dependencies>...</dependencies>
<parent>...</parent>
<dependencyManagement>...</dependencyManagement>
<modules>...</modules>
<properties>...</properties>
<!-- Build Settings -->
<build>...</build>
<reporting>...</reporting>
<!-- More Project Information -->
<name>...</name>
<description>...</description>
<url>...</url>
<inceptionYear>...</inceptionYear>
<licenses>...</licenses>
<organization>...</organization>
<developers>...</developers>
<contributors>...</contributors>
<!-- Environment Settings -->
<issueManagement>...</issueManagement>
<ciManagement>...</ciManagement>
<mailingLists>...</mailingLists>
<scm>...</scm>
<prerequisites>...</prerequisites>
<repositories>...</repositories>
<pluginRepositories>...</pluginRepositories>
<distributionManagement>...</distributionManagement>
<profiles>...</profiles>
</project>
For now, it’s suffice to know the overall structure and once you through with the guide you may refer official POM Reference to know more about it.
Super POM
Maven installation comes with a pom.xml which is known as Super POM. As in Java, where every other class extends java.lang.Object, all Maven projects extends Super POM. The pom.xml we create in our project is child or decedent of the Super POM.
The Super POM declares location of Maven central repository, Plugins repository, build element which sets the standard locations of the directories, plugin configuration and execution etc.,
Effective POM
At the start of every build, Maven internally merges project pomx.ml with Super POM and constructs a new POM which is known as Effective POM.
Earlier in Maven Lifecycle and Plugin Goals, we learned that Maven binds plugins goals to lifecycle phases. Actually, this magic happens in effective POM and it is highly instructive to go through the effective POM to know the what goes on under the hood.
Let’s generate the effective POM and analyze it. To get a clear picture, replace the simple-app pom.xml with a basic POM - just project coordinates and project dependencies.
simple-app/pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- project coordinates -->
<groupId>com.xyz</groupId>
<artifactId>simple-app</artifactId>
<version>1.0</version>
<!-- project dependencies -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
</project>
Next, use Maven Help Plugin to dump the effective POM to a file for investigation.
$ cd simple-app
$ mvn help:effective-pom -Doutput=target/effective-pom.xml
It creates a file effective-pom.xml
in target directory. If -Doutput
is omitted then command outputs the effective POM to console.
We explained that Maven merges project pom.xml with Super POM and internally creates an effective POM which it uses to build the project. In the example pom.xml, we defined project coordinates, a property related to resource encoding and project dependencies. The effective POM contains these items from pom.xml and also, many more items from Super POM.
The effective POM starts with coordinates of our project and then goes on to define Maven central and plugin repositories. Next, in build section, it defines project and build directories.
<build>
<sourceDirectory>/home/m/work/simple-app/src/main/java</sourceDirectory>
<scriptSourceDirectory>/home/m/work/simple-app/src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>/home/m/work/simple-app/src/test/java</testSourceDirectory>
<outputDirectory>/home/m/work/simple-app/target/classes</outputDirectory>
<testOutputDirectory>/home/m/work/simple-app/target/test-classes</testOutputDirectory>
....
<directory>/home/m/work/simple-app/target</directory>
<finalName>simple-app-1.0</finalName>
In the plugins section, Maven binds default goals for lifecycle phases. Though we have not defined build section in the project pom.xml, Maven constructs the effective POM with all sections which are essential to build the project.
As sample, the next screenshot shows the plugin definition for Maven Jar Plugin. It defines plugin execution with id default-jar (default-<goal-name>) which binds jar:jar goal to the package phase. If we go through the effective POM, we can find other default goals which binds to various lifecycle phases.
Project POM and Effective POM
Let’s add some plugin configuration to pom.xml and see how they get merged into effective POM.
So far, we saw many examples where single goal is executed in a lifecycle phase. However, it is also possible to execute multiple goals a single phase. For example, the package phase, by default, creates a Jar of application class and resource files using jar:jar goal. Suppose, we also require a separate Jar that contains only the test classes and resources. The Maven Jar Plugin has another goal jar:test-jar which creates the Jar of test files and to bind it to package phase, add following snippet to the pom.xml.
simple-app/pom.xml
...
<!-- project build -->
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>test-jar</id>
<phase>package</phase>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
Run mvn package
and build, in package phase, executes two goals -
jar:jar and jar:test-jar - and creates two jars - simple-app-1.0.jar and
simple-app-1.0-tests.jar - in target directory.
Generate effective POM with mvn help:effective-pom
and in it, for
Maven Jar Plugin we can find two executions - default one defined by
Super POM and another one defined by us in pom.xml.
In the next chapter, we describe project resources and the Maven Resources Plugin.