Inheritance Behavior
When managing a large number of libraries in a Maven multi-module architecture, a parent POM (packaged as pom) is typically utilized to centralize version control. The behavior differs significantly between the <dependencies> and <dependencyManagement> configurations.
Artifacts declared within the <dependencies> block of a parent POM are unconditionally inherited by all child modules. Conversely, declarations placed inside <dependencyManagement> merely define version preferences and default versions; they do not automatically add the libraries to the child modules. Sub-modules must explicitly declare the artifact in their own <dependencies> section, but they are permitted to omit the <version> tag, inheriting it from the parent.
Configuration Examples
Parent POM structure:
<project>
<dependencyManagement>
<dependencies>
<!-- Requires explicit declaration in child modules -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Unconditionally inherited by all child modules -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.10.0</version>
</dependency>
</dependencies>
</project>
If a child module possesses an empty <dependencies> block, it will still resolve commons-text from the parent's direct dependencies, but gson will remain absent.
To include the managed dependency, the child module must declare it without specifying the version number:
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
</dependencies>
Importing External Dependency Management
The <dependencyManagement> section supports combining <scope>import</scope> with <type>pom</type>. This mechanism allows a project to incorporate the version management rules defined in an entirely separate POM file.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>external.vendor.group</groupId>
<artifactId>vendor-bom</artifactId>
<version>1.0.0</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
By setting the scope to import and type to pom, all constraints defined within the <dependencyManagement> block of vendor-bom are merged into the current project's configuration. Consequently, any module inheriting from the current project can reference those imported libraries without declaring versions.
It is crucial to distinguish this from simply adding vendor-bom as a standard dependency. A regular dependency inclusion would pull in the transient dependencies of vendor-bom but would completely ignore its <dependencyManagement> declarations. Using import effectively extends the current project's version control strategy with external definitions.