Maven – POM Reference (original) (raw)

Introduction

What is the POM?

POM stands for "Project Object Model". It is an XML representation of a Maven project held in a file named pom.xml. When in the presence of Maven folks, speaking of a project is speaking in the philosophical sense, beyond a mere collection of files containing code. A project contains configuration files, as well as the developers involved and the roles they play, the defect tracking system, the organization and licenses, the URL of where the project lives, the project's dependencies, and all of the other little pieces that come into play to give code life. It is a one-stop-shop for all things concerning the project. In fact, in the Maven world, a project does not need to contain any code at all, merely a pom.xml.

Quick Overview

This is a listing of the elements directly under the POM's project element. Notice that modelVersion contains 4.0.0. That is currently the only supported POM version, and is always required.

4.0.0

... ... ... ... ... ... ... ... ...

... ...

... ... ... ... ... ... ... ...

... ... ... ... ... ... ... ... ...

The Basics

The POM contains all necessary information about a project, as well as configurations of plugins to be used during the build process. It is the declarative manifestation of the "who", "what", and "where", while the build lifecycle is the "when" and "how". That is not to say that the POM cannot affect the flow of the lifecycle - it can. For example, by configuring the maven-antrun-plugin, one can embed Apache Ant tasks inside of the POM. It is ultimately a declaration, however. Whereas a build.xml tells Ant precisely what to do when it is run (procedural), a POM states its configuration (declarative). If some external force causes the lifecycle to skip the Ant plugin execution, it does not stop the plugins that are executed from doing their magic. This is unlike a build.xml file, where tasks are almost always dependant on the lines executed before it.

4.0.0

org.codehaus.mojo my-project 1.0

Maven Coordinates

The POM defined above is the bare minimum that Maven allows. groupId:artifactId:version are all required fields (although, groupId and version do not need to be explicitly defined if they are inherited from a parent - more on inheritance later). The three fields act much like an address and timestamp in one. This marks a specific place in a repository, acting like a coordinate system for Maven projects:

The three elements given above point to a specific version of a project, letting Maven know who we are dealing with, and when in its software lifecycle we want them.

Packaging

Now that we have our address structure of groupId:artifactId:version, there is one more standard label to give us a really complete what: that is the project's packaging. In our case, the example POM for org.codehaus.mojo:my-project:1.0 defined above will be packaged as a jar. We could make it into a war by declaring a different packaging:

... war ...

When no packaging is declared, Maven assumes the packaging is the default: jar. The valid types are Plexus role-hints (read more on Plexus for a explanation of roles and role-hints) of the component role org.apache.maven.lifecycle.mapping.LifecycleMapping. The current core packaging values are: pom, jar, maven-plugin, ejb, war, ear, rar. These define the default list of goals which execute on each corresponding build lifecycle stage for a particular package structure: see Plugin Bindings for default Lifecycle Reference for details.

POM Relationships

One powerful aspect of Maven is its handling of project relationships: this includes dependencies (and transitive dependencies), inheritance, and aggregation (multi-module projects).

Dependency management has a long tradition of being a complicated mess for anything but the most trivial of projects. "Jarmageddon" quickly ensues as the dependency tree becomes large and complicated. "Jar Hell" follows, where versions of dependencies on one system are not equivalent to the versions developed with, either by the wrong version given, or conflicting versions between similarly named jars.

Maven solves both problems through a common local repository from which to link projects correctly, versions and all.

Dependencies

The cornerstone of the POM is its dependency list. Most projects depend on others to build and run correctly. If all Maven does for you is manage this list, you have gained a lot. Maven downloads and links the dependencies on compilation, as well as on other goals that require them. As an added bonus, Maven brings in the dependencies of those dependencies (transitive dependencies), allowing your list to focus solely on the dependencies your project requires.

... junit junit 4.12 jar test true ... ...

Dependency Management

Dependencies can be managed in the dependencyManagement section to affect the resolution of dependencies which are not fully qualified or to enforce the usage of a specific transitive dependency version. Further information in Introduction to the Dependency Mechanism.

Dependency Version Requirement Specification

Dependencies' version elements define version requirements, which are used to compute dependency versions. Soft requirements can be replaced by different versions of the same artifact found elsewhere in the dependency graph. Hard requirements mandate a particular version or versions and override soft requirements. If there are no versions of a dependency that satisfy all the hard requirements for that artifact, the build fails.

Version requirements have the following syntax:

Version Order Specification:

If version strings are syntactically correct Semantic Versioning 1.0.0 version numbers, then in almost all cases version comparison follows the precedence rules outlined in that specification. These versions are the commonly encountered alphanumeric ASCII strings such as 2.15.2-alpha. More precisely, this is true if both version numbers to be compared match the "valid semver" production in the BNF grammar in the semantic versioning specification. Maven does not consider any semantics implied by that specification.

Important: This is only true for Semantic Versioning 1.0.0. The Maven version order algorithm is not compatible with Semantic Versioning 2.0.0. In particular, Maven does not special case the plus sign or consider build identifiers.

When version strings do not follow semantic versioning, a more complex set of rules is required. The Maven coordinate is split in tokens between dots ('.'), hyphens ('-'), underscore ('_') and transitions between digits and characters. The separator is recorded and will have effect on the order. A transition between digits and characters is equivalent to a hyphen. Empty tokens are replaced with "0". This gives a sequence of version numbers (numeric tokens) and version qualifiers (non-numeric tokens) with "." or "-" prefixes. Versions are expected to start with numbers.

Splitting and Replacing Examples:

Then, starting from the end of the version, the trailing "null" values (0, "", "final", "ga") are trimmed. This process is repeated at each remaining hyphen from end to start.

Trimming Examples:

The version order is the lexicographical order on this sequence of prefixed tokens, the shorter one padded with enough "null" values with matching prefix to have the same length as the longer one. Padded "null" values depend on the prefix of the other version: 0 for '.', "" for '-'. The prefixed token order is:

Following semver rules is encouraged, and some qualifiers are discouraged:

End Result Examples:

Version Order Testing:

The maven distribution includes a tool to check version order. It was used to produce the examples in the previous paragraphs. Feel free to run it yourself when in doubt. You can run it like this:

java -jar ${MAVEN_HOME}/lib/maven-artifact-3.9.9.jar [versions...]

example:

$ java -jar ./lib/maven-artifact-3.9.9.jar 1 2 1.1 Display parameters as parsed by Maven (in canonical form and as a list of tokens) and comparison result:

  1. 1 -> 1; tokens: [1] 1 < 2
  2. 2 -> 2; tokens: [2] 2 > 1.1
  3. 1.1 -> 1.1; tokens: [1, 1]

Exclusions

It is sometimes useful to limit a dependency's transitive dependencies. A dependency may have incorrectly specified scopes, or dependencies that conflict with other dependencies in your project. Exclusions tell Maven not to include a specified artifact in the classpath even if it is a dependency of one or more of this project's dependencies (a transitive dependency). For example, maven-embedder depends on maven-core. Suppose you want to depend on maven-embedder but do not want to include maven-core or its dependencies in the classpath. Then add maven-core as an exclusion in the element that declares the dependency on maven-embedder:

... org.apache.maven maven-embedder 3.9.9 org.apache.maven maven-core ... ...

This only removes the path to maven-core from this one dependency. If maven-core appears as a direct or transitive dependency elsewhere in the POM, it can still be added to the classpath.

Wildcard excludes make it easy to exclude all of a dependency's transitive dependencies. In the case below, you may be working with the maven-embedder and you want to manage the dependencies you use, so you exclude all the transitive dependencies:

... org.apache.maven maven-embedder 3.8.6 ... ...

Inheritance

One powerful addition that Maven brings to build management is the concept of project inheritance. Although in build systems such as Ant inheritance can be simulated, Maven makes project inheritance explicit in the project object model.

4.0.0

org.codehaus.mojo my-parent 2.0 pom

The packaging type is required to be pom for parent and aggregation (multi-module) projects. These types define the goals bound to a set of lifecycle stages. For example, if packaging is jar, then the package phase will execute the jar:jar goal. Now we may add values to the parent POM, which will be inherited by its children. Most elements from the parent POM are inherited by its children, including:

Notable elements which are not inherited include:

4.0.0

org.codehaus.mojo my-parent 2.0 ../my-parent

my-project

Notice the relativePath element. It is not required, but may be used as a signifier to Maven to first search the path given for this project's parent, before searching the local and then remote repositories.

To see inheritance in action, just have a look at the ASF or Maven parent POM's.

Detailed inheritance rules are outlined in Maven Model Builder. All URLs are transformed when being inherited by default. The other ones are just inherited as is. For plugin configuration you can overwrite the inheritance behaviour with the attributes combine.children or combine.self outlined in Plugins.

The Super POM

Similar to the inheritance of objects in object oriented programming, POMs that extend a parent POM inherit certain values from that parent. Moreover, just as Java objects ultimately inherit from java.lang.Object, all Project Object Models inherit from a base Super POM. The snippet below is the Super POM for Maven 3.5.4.

4.0.0 central Central Repository https://repo.maven.apache.org/maven2 default false central Central Repository https://repo.maven.apache.org/maven2 default false never ${project.basedir}/target ${project.build.directory}/classes ${project.artifactId}-${project.version} ${project.build.directory}/test-classes ${project.basedir}/src/main/java ${project.basedir}/src/main/scripts ${project.basedir}/src/test/java ${project.basedir}/src/main/resources ${project.basedir}/src/test/resources maven-antrun-plugin 1.3 maven-assembly-plugin 2.2-beta-5 maven-dependency-plugin 2.8 maven-release-plugin 2.5.3 ${project.build.directory}/site release-profile
  <activation>
    <property>
      <name>performRelease</name>
      <value>true</value>
    </property>
  </activation>

  <build>
    <plugins>
      <plugin>
        <inherited>true</inherited>
        <artifactId>maven-source-plugin</artifactId>
        <executions>
          <execution>
            <id>attach-sources</id>
            <goals>
              <goal>jar-no-fork</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <inherited>true</inherited>
        <artifactId>maven-javadoc-plugin</artifactId>
        <executions>
          <execution>
            <id>attach-javadocs</id>
            <goals>
              <goal>jar</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <inherited>true</inherited>
        <artifactId>maven-deploy-plugin</artifactId>
        <configuration>
          <updateReleaseInfo>true</updateReleaseInfo>
        </configuration>
      </plugin>
    </plugins>
  </build>
</profile>

You can take a look at how the Super POM affects your Project Object Model by creating a minimal pom.xml and executing on the command line: mvn help:effective-pom

Dependency Management

Besides inheriting certain top-level elements, parents have elements to configure values for child POMs and transitive dependencies. One of those elements is dependencyManagement.

Aggregation (or Multi-Module)

A project with modules is known as a multi-module, or aggregator project. Modules are projects that this POM lists, and are executed as a group. A pom packaged project may aggregate the build of a set of projects by listing them as modules, which are relative paths to the directories or the POM files of those projects.

4.0.0

org.codehaus.mojo my-parent 2.0 pom

my-project another-project third-project/pom-example.xml

You do not need to consider the inter-module dependencies yourself when listing the modules; i.e. the ordering of the modules given by the POM is not important. Maven will topologically sort the modules such that dependencies are always build before dependent modules.

To see aggregation in action, have a look at the Maven base POM.

A final note on Inheritance v. Aggregation

Inheritance and aggregation create a nice dynamic to control builds through a single, high-level POM. You often see projects that are both parents and aggregators. For example, the entire Maven core runs through a single base POM org.apache.maven:maven, so building the Maven project can be executed by a single command: mvn compile. However, an aggregator project and a parent project are both POM projects, they are not one and the same and should not be confused. A POM project may be inherited from - but does not necessarily have - any modules that it aggregates. Conversely, a POM project may aggregate projects that do not inherit from it.

Properties

Properties are the last required piece to understand POM basics. Maven properties are value placeholders, like properties in Ant. Their values are accessible anywhere within a POM by using the notation ${X}, where X is the property. Or they can be used by plugins as default values, for example:

... 1.7 1.7 UTF-8 UTF-8 ...

They come in five different styles:

  1. env.X: Prefixing a variable with "env." will return the shell's environment variable. For example, ${env.PATH} contains the PATH environment variable.
    Note: While environment variables themselves are case-insensitive on Windows, lookup of properties is case-sensitive. In other words, while the Windows shell returns the same value for %PATH% and %Path%, Maven distinguishes between ${env.PATH} and ${env.Path}. The names of environment variables are normalized to all upper-case for the sake of reliability.
  2. project.x: A dot (.) notated path in the POM will contain the corresponding element's value. For example: <project><version>1.0</version></project> is accessible via ${project.version}.
  3. settings.x: A dot (.) notated path in the settings.xml will contain the corresponding element's value. For example: <settings><offline>false</offline></settings> is accessible via ${settings.offline}.
  4. Java System Properties: All properties accessible via java.lang.System.getProperties() are available as POM properties, such as ${java.home}.
  5. x: Set within a <properties /> element in the POM. The value of <properties><someVar>value</someVar></properties> may be used as ${someVar}.

Build Settings

Beyond the basics of the POM given above, there are two more elements that must be understood before claiming basic competency of the POM. They are the build element, that handles things like declaring your project's directory structure and managing plugins; and the reporting element, that largely mirrors the build element for reporting purposes.

Build

According to the POM 4.0.0 XSD, the build element is conceptually divided into two parts: there is a BaseBuild type which contains the set of elements common to both build elements (the top-level build element under project and the build element under profiles, covered below); and there is the Build type, which contains the BaseBuild set as well as more elements for the top level definition. Let us begin with an analysis of the common elements between the two.

Note: These different build elements may be denoted "project build" and "profile build".

... ...

...

The BaseBuild Element Set

BaseBuild is exactly as it sounds: the base set of elements between the two build elements in the POM.

install ${project.basedir}/target ${artifactId}-${version} filters/filter1.properties ...

Resources

Another feature of build elements is specifying where resources exist within your project. Resources are not (usually) code. They are not compiled, but are items meant to be bundled within your project or used for various other reasons, such as code generation.

For example, a Plexus project requires a configuration.xml file (which specifies component configurations to the container) to live within the META-INF/plexus directory. Although we could just as easily place this file within src/main/resources/META-INF/plexus, we want instead to give Plexus its own directory of src/main/plexus. In order for the JAR plugin to bundle the resource correctly, you would specify resources similar to the following:

... META-INF/plexus false ${project.basedir}/src/main/plexus configuration.xml **/*.properties ... ...

Plugins

... org.apache.maven.plugins maven-jar-plugin 2.6 false true test ... ...

Beyond the standard coordinate of groupId:artifactId:version, there are elements which configure the plugin or this builds interaction with it.

Plugin Management

... ... org.apache.maven.plugins maven-jar-plugin 2.6 pre-process-classes compile jar pre-process ...

If we added these specifications to the plugins element, they would apply only to a single POM. However, if we apply them under the pluginManagement element, then this POM and all inheriting POMs that add the maven-jar-plugin to the build will get the pre-process-classes execution as well. So rather than the above mess included in every child pom.xml, only the following is required:

... ... org.apache.maven.plugins maven-jar-plugin ...

The Build Element Set

The Build type in the XSD denotes those elements that are available only for the "project build". Despite the number of extra elements (six), there are really only two groups of elements that project build contains that are missing from the profile build: directories and extensions.

Directories

The set of directory elements live in the parent build element, which set various directory structures for the POM as a whole. Since they do not exist in profile builds, these cannot be altered by profiles.

... ${project.basedir}/src/main/java ${project.basedir}/src/main/scripts ${project.basedir}/src/test/java ${project.basedir}/target/classes ${project.basedir}/target/test-classes ...

If the values of a *Directory element above is set as an absolute path (when their properties are expanded) then that directory is used. Otherwise, it is relative to the base build directory: ${project.basedir}. Please note that the scriptSourceDirectory is nowhere used in Maven and is obsolete.

Extensions

Extensions are a list of artifacts that are to be used in this build. They will be included in the running build's classpath. They can enable extensions to the build process (such as add an ftp provider for the Wagon transport mechanism), as well as make plugins active which make changes to the build lifecycle. In short, extensions are artifacts that are activated during build. The extensions do not have to actually do anything nor contain a Mojo. For this reason, extensions are excellent for specifying one out of multiple implementations of a common plugin interface.

... ... org.apache.maven.wagon wagon-ftp 1.0-alpha-3 ...

Reporting

Reporting contains the elements that correspond specifically for the site generation phase. Certain Maven plugins can generate reports defined and configured under the reporting element, for example: generating Javadoc reports. Much like the build element's ability to configure plugins, reporting commands the same ability. The glaring difference is that rather than fine-grained control of plug-in goals within the executions block, reporting configures goals within reportSet elements. And the subtler difference is that a plugin configuration under the reporting element works as build plugin configuration, although the opposite is not true (a build plugin configuration does not affect a reporting plugin).

Possibly the only item under the reporting element that would not be familiar to someone who understood the build element is the Boolean excludeDefaults element. This element signifies to the site generator to exclude reports normally generated by default. When a site is generated via the site build cycle, a Project Info section is placed in the left-hand menu, chock full of reports, such as the Project Team report or Dependencies list report. These report goals are generated by maven-project-info-reports-plugin. Being a plugin like any other, it may also be suppressed in the following, more verbose, way, which effectively turns off project-info reports.

... /home/jenkins/82467a7c/workspace/aven_maven-box_maven-site_master/target/site maven-project-info-reports-plugin 2.0.1 ...

The other difference is the outputDirectory element under plugin. In the case of reporting, the output directory is ${project.basedir}/target/site by default.

Report Sets

It is important to keep in mind that an individual plugin may have multiple goals. Each goal may have a separate configuration. Report sets configure execution of a report plugin's goals. Does this sound familiar - deja-vu? The same thing was said about build's execution element with one difference: you cannot bind a report to another phase. Sorry.

For example, suppose you wanted to configure the javadoc:javadoc goal to link to "http://java.sun.com/j2se/1.5.0/docs/api/", but only the javadoc goal (not the goal maven-javadoc-plugin:jar). We would also like this configuration passed to its children, and set inherited to true. The reportSet would resemble the following:

... ... sunlink javadoc true http://java.sun.com/j2se/1.5.0/docs/api/ ...

Between build executions and reporting reportSets, it should be clear now as to why they exist. In the simplest sense, they drill down in configuration. The POM must have a way not only to configure plugins, but must also configure the goals of those plugins. That is where these elements come in, giving the POM ultimate granularity in control of its build destiny.

More Project Information

Several elements do not affect the build, but rather document the project for the convenience of developers. Many of these elements are used to fill in project details when generating the project's web site. However, like all POM declarations, plugins can use them for anything. The following are the simplest elements:

Licenses

Apache-2.0 https://www.apache.org/licenses/LICENSE-2.0.txt repo A business-friendly OSS license

Licenses are legal documents defining how and when a project (or parts of a project) may be used. A project should list licenses that apply directly to this project, and not list licenses that apply to the project's dependencies.

Organization

Most projects are run by some sort of organization (business, private group, etc.). Here is where the most basic information is set.

... Codehaus Mojo http://mojo.codehaus.org

Developers

All projects consist of files that were created, at some time, by a person. Like the other systems that surround a project, so to do the people involved with a project have a stake in the project. Developers are presumably members of the project's core development. Note that, although an organization may have many developers (programmers) as members, it is not good form to list them all as developers, but only those who are immediately responsible for the code. A good rule of thumb is, if the person should not be contacted about the project, they do not need to be listed here.

... jdoe John Doe jdoe@example.com http://www.example.com/jdoe ACME http://www.example.com architect developer America/New_York http://www.example.com/jdoe/pic ...

Contributors

Contributors are like developers yet play an ancillary role in a project's lifecycle. Perhaps the contributor sent in a bug fix, or added some important documentation. A healthy open source project will likely have more contributors than developers.

... Noelle some.name@gmail.com http://noellemarie.com Noelle Marie http://noellemarie.com tester America/Vancouver some.name@gmail.com ...

Contributors contain the same set of elements than developers sans the id element.

Environment Settings

Issue Management

This defines the defect tracking system (Bugzilla, TestTrack, ClearQuest, etc) used. Although there is nothing stopping a plugin from using this information for something, it's primarily used for generating project documentation.

... Bugzilla http://127.0.0.1/bugzilla/ ...

Continuous Integration Management

Continuous integration build systems based upon triggers or timings (such as, hourly or daily) have grown in favor over manual builds in the past few years. As build systems have become more standardized, so have the systems that run the trigger those builds. Although the majority of the configuration is up to the specific program used (Continuum, Cruise Control, etc.), there are a few configurations which may take place within the POM. Maven has captured a few of the recurring settings within the set of notifier elements. A notifier is the manner in which people are notified of certain build statuses. In the following example, this POM is setting a notifier of type mail (meaning email), and configuring the email address to use on the specified triggers sendOnError, sendOnFailure, and not sendOnSuccess or sendOnWarning.

... continuum http://127.0.0.1:8080/continuum mail true true false false

continuum@127.0.0.1
...

Mailing Lists

Mailing lists are a great tool for keeping in touch with people about a project. Most mailing lists are for developers and users.

... User List user-subscribe@127.0.0.1 user-unsubscribe@127.0.0.1 user@127.0.0.1 http://127.0.0.1/user/ http://base.google.com/base/1/127.0.0.1 ...

SCM

SCM (Software Configuration Management, also called Source Code/Control Management or, succinctly, version control) is an integral part of any healthy project. If your Maven project uses an SCM system (it does, doesn't it?) then here is where you would place that information into the POM.

... scm:svn:http://127.0.0.1/svn/my-project scm:svn:https://127.0.0.1/svn/my-project HEAD http://127.0.0.1/websvn/my-project ...

Prerequisites

The POM may have certain prerequisites in order to execute correctly. The only element that exists as a prerequisite in POM 4.0.0 is the maven element, which takes a minimum version number.

Use Maven Enforcer Plugin's requireMavenVersion rule, or other rules for build-time prerequisites. For packaging maven-plugin this is still used at run-time to make sure that the minimum Maven version for the plugin is met (but only in the pom.xml of the referenced plugin).

... 2.0.6 ...

Repositories

Repositories are collections of artifacts which adhere to the Maven repository directory layout. In order to be a Maven repository artifact, a POM file must live within the structure $BASE_REPO/groupId/artifactId/version/artifactId-version.pom. $BASE_REPO can be local (file structure) or remote (base URL); the remaining layout will be the same. Repositories exist as a place to collect and store artifacts. Whenever a project has a dependency upon an artifact, Maven will first attempt to use a local copy of the specified artifact. If that artifact does not exist in the local repository, it will then attempt to download from a remote repository. The repository elements within a POM specify those alternate repositories to search.

The repository is one of the most powerful features of the Maven community. By default Maven searches the central repository at https://repo.maven.apache.org/maven2/. Additional repositories can be configured in the pom.xml `repositories` element.

... false true always fail Nexus Snapshots snapshots-repo https://oss.sonatype.org/content/repositories/snapshots default ... ...

Plugin Repositories

Repositories are home to two major types of artifacts. The first are artifacts that are used as dependencies of other artifacts. These are the majority of artifacts that reside within central. The other type of artifact is plugins. Maven plugins are themselves a special type of artifact. Because of this, plugin repositories may be separated from other repositories (although, I have yet to hear a convincing argument for doing so). In any case, the structure of the pluginRepositories element block is similar to the repositories element. The pluginRepository elements each specify a remote location of where Maven can find new plugins.

Distribution Management

Distribution management acts precisely as it sounds: it manages the distribution of the artifact and supporting files generated throughout the build process.

... ... ... ... ... ... ... ...

Repository

Whereas the repositories element specifies in the POM the location and manner in which Maven may download remote artifacts for use by the current project, distributionManagement specifies where (and how) this project will get to a remote repository when it is deployed. The repository elements will be used for snapshot distribution if the snapshotRepository is not defined.

... false corp1 Corporate Repository scp://repo/maven2 default true propSnap Propellors Snapshots sftp://propellers.net/maven legacy ... ...

Site Distribution

More than distribution to the repositories, distributionManagement is responsible for defining how to deploy the project's site and documentation.

... ... mojo.website Mojo Website scp://beaver.codehaus.org/home/projects/mojo/public_html/ ... ...

Relocation

<project xmlns="http://maven.apache.org/POM/4.0.0"1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 " title="undefined" rel="noopener noreferrer">https://maven.apache.org/xsd/maven-4.0.0.xsd"> ... ... org.apache my-project 1.0 We have moved the Project under Apache ... ...

Projects are not static; they are living things (or dying things, as the case may be). A common thing that happens as projects grow, is that they are forced to move to more suitable quarters. For example, when your next wildly successful open source project moves under the Apache umbrella, it would be good to give users a heads-up that the project is being renamed to org.apache:my-project:1.0. Besides specifying the new address, it is also good form to provide a message explaining why.

downloadUrl

... ... http://mojo.codehaus.org/my-project/download.html ...

downloadUrl is the URL of the project's download page. If not given users will be referred to the homepage given by url. This is given to assist in locating artifacts that are not in the repository due to licensing restrictions. See for example MNG-2083 for a typical workflow.

status

... ... deployed ...

Warning! Like a baby bird in a nest, the status should never be touched by human hands! The reason for this is that Maven will set the status of the project when it is transported out to the repository. It is described here just for understanding, but should never be configured in your pom.xml.

Status valid values are as follows:

Profiles

A new feature of the POM 4.0 is the ability of a project to change settings depending on the environment where it is being built. A profile element contains both an optional activation (a profile trigger) and the set of changes to be made to the POM if that profile has been activated. For example, a project built for a test environment may point to a different database than that of the final deployment. Or dependencies may be pulled from different repositories based upon the JDK version used. The elements of profiles are as follows:

... test ... ... ... ... ... ... ... ... ...

Activation

Activations are the key of a profile. The power of a profile comes from its ability to modify the basic POM only under certain circumstances. Those circumstances are specified via an activation element.

... test false 1.5 Windows XP Windows x86 5.1.2600 sparrow-type African ${basedir}/file2.properties ${basedir}/file1.properties ...

Before Maven 3.2.2 activation occurs when one or more of the specified criteria have been met. When the first positive result is encountered, processing stops and the profile is marked as active. Since Maven 3.2.2 activation occurs when all of the specified criteria have been met.

The POM based profile activation only refers to the container profile (not all profiles with the same id).

The activation element is not the only way that a profile may be activated. The settings.xml file's activeProfile element may contain the profile's id. They may also be activated explicitly through the command line via a comma separated list after the -P flag (e.g. -P codecoverage).

To see which profile will activate in a certain build, use the maven-help-plugin.

Further information about profiles is available in Introduction to Build Profiles.

The BaseBuild Element Set (revisited)

As mentioned above, the reason for the two types of build elements reside in the fact that it does not make sense for a profile to configure build directories or extensions as it does in the top level of the POM. Reguardless of in which environment the project is built, some values will remain constant, such as the directory structure of the source code. If you find your project needing to keep two sets of code for different environments, it may be prudent to investigate refactoring the project into two or more separate projects.

Final

The Maven POM is big. However, its size is also a testament to its versatility. The ability to abstract all of the aspects of a project into a single artifact is powerful, to say the least. Gone are the days of dozens of disparate build scripts and scattered documentation concerning each individual project. Along with Maven's other stars that make up the Maven galaxy - a well defined build lifecycle, easy to write and maintain plugins, centralized repositories, system-wide and user-based configurations, as well as the increasing number of tools to make developers' jobs easier to maintain complex projects - the POM is the large, but bright, center.


Aspects of this guide were originally published in the Maven 2 Pom Demystified.