Centralizing Maven Versions: Parent POM vs. Bill of Materials (BOM)
Learn when to use a Parent POM versus a Bill of Materials (BOM) in Maven to prevent version drift and manage dependencies across multi-module projects.
18 Jul 2025, 12:26 UTC

The Version Drift Problem
In multi-module projects or microservice architectures, declaring dependency versions in every individual pom.xml leads to "version drift." This occurs when different modules use slightly different versions of the same library, causing unpredictable runtime behavior, NoSuchMethodError exceptions, and classpath conflicts during deployment.
The goal is to define a version once and have all modules inherit that constraint. In Apache Maven, this is achieved via the <dependencyManagement> section, but the method of delivery—via a Parent POM or a Bill of Materials (BOM)—changes how your projects are coupled.
Comparing Inheritance and Import
The primary decision is whether you want a strict hierarchical relationship (Parent POM) or a flexible, composition-based relationship (BOM).
| Feature | Parent POM Inheritance | BOM Import (Composition) |
|---|---|---|
| Relationship | Strict Parent-Child (Is-a) | Imported Constraint (Uses-a) |
| Limit | Only one parent allowed | Multiple BOMs can be imported |
| Scope | Shares plugins, properties, and versions | Shares version constraints only |
| Coupling | High (Tight coupling) | Low (Loose coupling) |
Trade-offs and Decision Criteria
When to use a Parent POM
Use a Parent POM when your modules are part of a single logical application that shares the same build lifecycle, compiler versions, and plugin configurations. It is the most efficient way to ensure that every module in a monolithic repository uses the same maven-compiler-plugin settings and Java version.
When to use a BOM
Use a BOM when you need to share a set of compatible library versions across independent projects that do not share a common parent. This is critical for microservices where Project A and Project B are separate repositories but must both use the same version of a shared internal library or a third-party framework (like Spring Boot or the AWS SDK).
Risk: BOM Conflict Resolution
If you import multiple BOMs that define the same dependency with different versions, Maven resolves the conflict based on declaration order. The first BOM listed in the <dependencyManagement> block wins. This makes the order of imports a critical configuration detail.
Implementation Example: Creating and Using a BOM
To implement a BOM, you create a standalone project with <packaging>pom</packaging>. This project does not contain code; it only contains the version constraints.
1. Define the BOM (The "Platform" POM)
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.platform</groupId>
<artifactId>company-bom</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies<
</dependencyManagement>
</project>
2. Consume the BOM in a Service POM
In the consuming project, use the import scope. This allows the project to maintain its own parent while still inheriting the version constraints from the BOM.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example.platform</groupId>
<artifactId>company-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies<
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<!-- No version tag needed here; it is managed by the BOM --<
</dependency>
</dependencies>
Validating the Result
To verify that the version is being correctly managed and not overridden by a transitive dependency, run the following command in your terminal from the project root:
mvn dependency:tree
Check: Search the output for commons-lang3. It should explicitly show version 3.12.0. If the version differs, check for other imported BOMs or explicit version declarations in the local pom.xml that are overriding the management block.
Practical Test: Temporarily remove the <dependencyManagement> block and attempt to build. If the build fails with a "version missing" error for the dependency, you have successfully confirmed that the BOM was providing the version constraint.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.