Maven: The Complete Reference

3.3. POM Syntax

The POM is always in a file named pom.xml in the base directory of a Maven project. This XML document can start with the XML declaration, or you can choose to omit it. All values in a POM are captured as XML elements.

3.3.1. Project Versions

A project’s version number is used to group and order releases. Maven versions contain the following parts: major version, minor version, incremental version, and qualifier. In a version, these parts correspond to the following format:

<major version>.<minor version>.<incremental version>-<qualifier>

For example, the version "1.3.5" has a major version of 1, a minor version of 3, and an incremental version of 5. The version "5" has a major version of 5 and no minor or incremental version. The qualifier exists to capture milestone builds: alpha and beta releases, and the qualifier is separated from the major, minor, and incremental versions by a hyphen. For example, the version "1.3-beta-01" has a major version of 1, a minor version of 3, and a qualifier of "beta-01".

Keeping your version numbers aligned with this standard will become very important when you want to start using version ranges in your POMs. Version ranges, introduced in Section 3.4.3, “Dependency Version Ranges”, allow you to specify a dependency on a range of versions, and they are only supported because Maven has the ability to sort versions based on the version release number format introduced in this section.

If your version release number matches the format <major>.<minor>.<incremental>-<qualifier> then your versions will be compared properly; "1.2.3" will be evaluated as a more recent build than "1.0.2", and the comparison will be made using the numeric values of the major, minor, and incremental versions. If your version release number does not fit the standard introduced in this section, then your versions will be compared as strings; "1.0.1b" will be compared to "1.2.0b" using a String comparison.

Version Build Numbers

One gotcha for release version numbers is the ordering of the qualifiers. Take the version release numbers “1.2.3-alpha-2” and “1.2.3-alpha-10,” where the “alpha-2” build corresponds to the 2nd alpha build, and the “alpha-10” build corresponds to the 10th alpha build. Even though “alpha-10” should be considered more recent than “alpha-2,” Maven is going to sort “alpha-10” before “alpha-2” due to a known issue in the way Maven handles version numbers.

Maven is supposed to treat the number after the qualifier as a build number. In other words, the qualifier should be "alpha", and the build number should be 2. Even though Maven has been designed to separate the build number from the qualifier, this parsing is currently broken. As a result, "alpha-2" and "alpha-10" are compared using a String comparison, and "alpha-10" comes before "alpha-2" alphabetically. To get around this limitation, you will need to left-pad your qualified build numbers. If you use "alpha-02" and "alpha-10" this problem will go away, and it will continue to work once Maven properly parses the version build number.

SNAPSHOT Versions

Maven versions can contain a string literal to signify that a project is currently under active development. If a version contains the string “-SNAPSHOT,” then Maven will expand this token to a date and time value converted to UTC (Coordinated Universal Time) when you install or release this component. For example, if your project has a version of “1.0-SNAPSHOT” and you deploy this project’s artifacts to a Maven repository, Maven would expand this version to “1.0-20080207-230803-1” if you were to deploy a release at 11:08 PM on February 7th, 2008 UTC. In other words, when you deploy a snapshot, you are not making a release of a software component; you are releasing a snapshot of a component at a specific time.

Why would you use this? SNAPSHOT versions are used for projects under active development. If your project depends on a software component that is under active development, you can depend on a SNAPSHOT release, and Maven will periodically attempt to download the latest snapshot from a repository when you run a build. Similarly, if the next release of your system is going to have a version "1.4", your project would have a version "1.4-SNAPSHOT" until it was formally released.

As a default setting, Maven will not check for SNAPSHOT releases on remote repositories. To depend on SNAPSHOT releases, users must explicitly enable the ability to download snapshots using a repository or pluginRepository element in the POM.

When releasing a project, you should resolve all dependencies on SNAPSHOT versions to dependencies on released versions. If a project depends on a SNAPSHOT, it is not stable as the dependencies may change over time. Artifacts published to non-snapshot Maven repositories such as http://repo1.maven.org/maven2 cannot depend on SNAPSHOT versions, as Maven’s Super POM has snapshot’s disabled from the Central repository. SNAPSHOT versions are for development only.

3.3.2. Property References

preceded by a dollar sign and surrounded by two curly braces. For example, consider the following POM:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.sonatype.mavenbook</groupId>
    <artifactId>project-a</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <build>
        <finalName>${project.groupId}-${project.artifactId}</finalName>
    </build>
</project>

If you put this XML in a pom.xml and run mvn help:effective-pom, you will see that the output contains the line:

...
<finalName>org.sonatype.mavenbook-project-a</finalName>
...

When Maven reads a POM, it replaces references to properties when it loads the POM XML. Maven properties occur frequently in advanced Maven usage, and are similar to properties in other systems such as Ant or Velocity. They are simply variables delimited by ${...}. Maven provides three implicit variables which can be used to access environment variables, POM information, and Maven Settings:

env
The env variable exposes environment variables exposed by your operating system or shell. For example, a reference to ${env.PATH} in a Maven POM would be replaced by the ${PATH} environment variable (or %PATH% in Windows).
project
The project variable exposes the POM. You can use a dot-notated (.) path to reference the value of a POM element. For example, in this section we used the groupId and artifactId to set the finalName element in the build configuration. The syntax for this property reference was: ${project.groupId}-${project.artifactId}.
settings
The settings variable exposes Maven settings information. You can use a dot-notated (.) path to reference the value of an element in a settings.xml file. For example, ${settings.offline} would reference the value of the offline element in ~/.m2/settings.xml.

Note

You may see older builds that use ${pom.xxx} or just ${xxx} to reference POM properties. These methods have been deprecated and only ${project.xxx} should be used.

In addition to the three implicit variables, you can reference system properties and any custom properties set in the Maven POM or in a build profile:

Java System Properties
All properties accessible via getProperties() on java.lang.System are exposed as POM properties. Some examples of system properties are: ${user.name}, ${user.home}, ${java.home}, and ${os.name}. A full list of system properties can be found in the Javadoc for the System class.
x
Arbitrary properties can be set with a properties element in a pom.xml or settings.xml, or properties can be loaded from external files. If you set a property named fooBar in your pom.xml, that same property is referenced with ${fooBar}. Custom properties come in handy when you are building a system that filters resources and targets different deployment platforms. Here is the syntax for setting ${foo}=bar in a POM:
<properties>
    <foo>bar</foo>
</properties>

For a more comprehensive list of available properties, see Chapter 9, Properties and Resource Filtering.