Once you've adopted Maven at your super complex enterprise
and you have two hundred and twenty inter-related Maven projects, you
are going to start wondering if there is a better way to get a handle on
dependency versions. If every single project that uses a dependency like
the MySQL Java connector needs to independently list the version number
of the dependency, you are going to run into problems when you need to
upgrade to a new version. Because the version numbers are distributed
throughout your project tree, you are going to have to manually edit
each of the pom.xml files that reference a
dependency to make sure that you are changing the version number
everywhere. Even with find, xargs,
and awk, you are still running the risk of missing a
single POM.
Luckily, Maven provides a way for you to consolidate dependency
version numbers in the dependencyManagement element.
You'll usually see the dependencyManagement element
in a top-level parent POM for an organization or
project. Using the dependencyManagement element in a
pom.xml allows you to reference a dependency in a
child project without having to explicitly list the version. Maven will
walk up the parent-child hierarchy until it finds a project with a
dependencyManagement element, it will then use the
version specified in this dependencyManagement
element.
For example, if you have a large set of projects which make use of
the MySQL Java connector version 5.1.2, you could define the following
dependencyManagement element in your multi-module
project's top-level POM.
Example 3.9. Defining Dependency Versions in a Top-level POM
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>a-parent</artifactId>
<version>1.0.0</version>
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.2</version>
</dependency>
...
<dependencies>
</dependencyManagement>
Then, in a child project, you can add a dependency to the MySQL Java Connector using the following dependency XML:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonatype.mavenbook</groupId>
<artifactId>a-parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>project-a</artifactId>
...
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
</project>
You should notice that the child project did not have to
explicitly list the version of the
mysql-connector-java dependency. Because this
dependency was defined in the top-level POM's
dependencyManagement element, the version number
is going to propagate to the child project's dependency on
mysql-connector-java. Note that if this child
project did define a version, it would override the version listed
in the top-level POM's
dependencyManagement section. That is, the
dependencyManagement version is only used when
the child does not declare a version directly.
Dependency management in a top-level POM is
different from just defining a dependency on a widely shared parent
POM. For starters, all dependencies are
inherited. If mysql-connector-java were listed as
a dependency of the top-level parent project, every single project
in the hierarchy would have a reference to this dependency. Instead
of adding in unnecessary dependencies, using
dependencyManagement allows you to consolidate
and centralize the management of dependency versions without adding
dependencies which are inherited by all children. In other words,
the dependencyManagement element is equivalent to
an environment variable which allows you to declare a dependency
anywhere below a project without specifying a version number.
