ZetCode

Maven BOM

last modified June 12, 2025

In this tutorial, we will explore how to use Maven BOM (Bill of Materials) to efficiently manage dependency versions across multiple projects. By leveraging BOMs, developers can ensure consistency, avoid version conflicts, and simplify dependency management in complex applications.

A Maven BOM (Bill of Materials) is a specialized POM (Project Object Model) file that acts as a central reference for dependency versions. Instead of manually specifying versions for each dependency across different modules or projects, a BOM allows you to define them once and reuse them wherever needed.

This approach is especially beneficial for large-scale applications with numerous modules that share common dependencies. Without a BOM, version mismatches can lead to compatibility issues, making upgrades and maintenance challenging.

A BOM simplifies dependency management by providing a single source of truth for dependency versions. It allows developers to import a predefined set of dependencies and their versions into their projects, ensuring that all modules and projects use the same versions of shared dependencies. This reduces the risk of version conflicts and makes it easier to manage updates across multiple projects.

BOM has several advantages, including:

Creating a BOM Project

To create a BOM project, you need to define a POM file with the packaging type set to pom. This POM will contain the dependency management section where you can specify the versions of the dependencies you want to manage.

bom/pom.xml
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>example-bom</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>3.2.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            
            <dependency>
                <groupId>com.fasterxml.jackson</groupId>
                <artifactId>jackson-bom</artifactId>
                <version>2.16.1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            
            <dependency>
                <groupId>com.example</groupId>
                <artifactId>common-lib</artifactId>
                <version>2.5.0</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

In this example, we define a BOM project with the following elements:

The <dependencyManagement> section contains a list of dependencies with their versions. These dependencies can be imported into other projects that use this BOM. The import scope is used for dependencies that are meant to be used as a BOM, allowing other projects to inherit the versions defined in this BOM without needing to specify them explicitly.

You can add any dependencies you want to manage in the BOM. In this example, we include the Spring Boot BOM, the Jackson BOM, and a custom library called common-lib. The versions of these dependencies are defined in the BOM, allowing other projects to use them without specifying the versions explicitly.

Using the BOM in Other Projects

To use the BOM in other Maven projects, you need to import it in the dependencyManagement section of the project's POM file. This allows you to inherit the versions defined in the BOM without specifying them explicitly in each project's POM. Here is an example of how to do this:

project/pom.xml
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>example-bom</artifactId>
            <version>1.0.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <!-- Version inherited from BOM -->
    </dependency>
    
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>common-lib</artifactId>
        <!-- Version inherited from BOM -->
    </dependency>
</dependencies>

The dependencyManagement section allows you to import the BOM, which defines versions for all dependencies listed within it. When you declare dependencies in your project, you do not need to specify their versions, as they are inherited from the BOM.

This approach simplifies version management, as you can update the BOM in one place, and all projects using it will automatically use the updated versions. It also helps avoid version conflicts and ensures that all projects use the same versions of shared dependencies.

Inheriting from Parent BOM

You can also create a BOM that inherits from another BOM, allowing you to extend or override versions as needed. This is useful for creating a custom BOM that builds upon an existing BOM, such as the Spring Boot BOM.

project/pom.xml
<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>example-bom</artifactId>
        <version>1.0.0</version>
    </parent>
    
    <artifactId>my-project</artifactId>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

In this example, the project inherits from the example-bom, which contains the Spring Boot BOM. This allows you to use the versions defined in the BOM without explicitly declaring them in your project POM.

Multi-Module Project with BOM

In a multi-module Maven project, you can create a parent POM that includes the BOM and manages dependencies for all child modules. This allows you to maintain consistent dependency versions across all modules in the project.

parent/pom.xml
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>parent-project</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    
    <modules>
        <module>bom</module>
        <module>service</module>
        <module>web</module>
    </modules>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.example</groupId>
                <artifactId>example-bom</artifactId>
                <version>${project.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

In this parent POM, we define a dependencyManagement section that imports the BOM. Each child module can then declare its dependencies without specifying versions, as they will inherit the versions defined in the BOM.

Overriding BOM Versions

You can override specific versions from the BOM when needed. This is useful when you want to use a different version of a dependency than the one defined in the BOM, while still benefiting from the BOM's version management for other dependencies.

project/pom.xml
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>example-bom</artifactId>
            <version>1.0.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        
        <!-- Override specific version -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.15.2</version>
        </dependency>
    </dependencies>
</dependencyManagement>

In this example, we import the example-bom but override the version of jackson-databind to 2.15.2. This allows us to use a different version of this dependency while still benefiting from the other versions defined in the BOM.

Popular Public BOMs

Many popular libraries and frameworks provide their own BOMs to simplify dependency management. These BOMs define a set of recommended versions for dependencies commonly used together, making it easier to manage versions in your projects.

Using Spring Boot BOM
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>3.2.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

The Spring Boot BOM provides a set of managed dependencies for Spring Boot applications, ensuring that all dependencies are compatible with each other.

Using Jackson BOM
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson</groupId>
            <artifactId>jackson-bom</artifactId>
            <version>2.16.1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

The Jackson BOM provides a set of managed dependencies for the Jackson JSON processing library, ensuring that all Jackson components are compatible with each other.

BOM Best Practices

Source

Maven Dependency Mechanism

In this article we have explored how to use Maven BOMs to manage dependency versions across multiple projects.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Java tutorials.