16

Apache Maven: POM & BOM

Modern software projects often consist of dozens (or hundreds) of dependencies. Managing versions, transitive dependencies, consistency, and build logic manually…

Modern software projects often consist of dozens (or hundreds) of dependencies. Managing versions, transitive dependencies, consistency, and build logic manually quickly becomes chaotic. Apache Maven addresses this complexity using two foundational concepts:

  • POM (Project Object Model)
  • BOM (Bill of Materials)

Though related, they serve distinct purposes in dependency and build management.


What is POM (Project Object Model)?

A POM is the core configuration file of a Maven project. It defines:

  • Project metadata
  • Dependencies
  • Plugins
  • Build lifecycle configurations
  • Inheritance and modules
  • Repository definitions

Every Maven project must have one POM file, named: pom.xml

┌──────────────────────────┐
│ pom.xml │
│ (Project Object Model) │
└──────────┬───────────────┘

│ Defines

┌──────────────────────────┐
│ Dependencies │
│ Plugins │
│ Build Lifecycle │
│ Packaging (jar/war) │
│ Repositories │
│ Project metadata │
└──────────────────────────┘

Core Idea Behind POM

The POM acts as the single source of truth for how a project is built, tested, packaged, and deployed.


Basic Structure & Syntax of a POM

Minimal POM Example

<project xmlns="http://maven.apache.org/POM/4.0.0"
     	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
     	https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.example</groupId>
	<artifactId>demo-app</artifactId>
	<version>1.0.0</version>
	<packaging>jar</packaging>
</project>

Key Elements of a POM

a. Dependencies

<dependencies>
	<dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-context</artifactId>
    	<version>6.1.5</version>
	</dependency>
</dependencies>

b. Plugins

<build>
	<plugins>
    	<plugin>
        	<groupId>org.apache.maven.plugins</groupId>
        	<artifactId>maven-compiler-plugin</artifactId>
        	<version>3.11.0</version>
        	<configuration>
            	<source>17</source>
            	<target>17</target>
        	</configuration>
    	</plugin>
	</plugins>
</build>

c. Inheritance (Parent POM)

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>3.2.3</version>
</parent>

What is BOM (Bill of Materials)?

A BOM is a special type of POM whose sole purpose is to centralize dependency versions.

A BOM does not build an application.
It only manages versions.

Technically, a BOM is still a POM, but with:

<packaging>pom</packaging>

Core Idea Behind BOM

Imagine a project with:

  • 20 Spring dependencies
  • 15 Kafka-related dependencies
  • 10 internal libraries

If versions are declared individually:

  • Inconsistencies arise
  • Version conflicts appear
  • Upgrading becomes risky

BOM solves this by declaring versions exactly once.


BOM Syntax & Structure

BOM Definition Example

┌──────────────────────────────┐
│ BOM (POM) │
│ packaging = pom │
│ │
│ Dependency Versions Only │
│ │
│ spring-core → 6.1.5 │
│ spring-web → 6.1.5 │
│ spring-context → 6.1.5 │
│ jackson-* → 2.15.3 │
└──────────────────────────────┘
<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</groupId>
            	<artifactId>spring-context</artifactId>
            	<version>6.1.5</version>
        	</dependency>
        	<dependency>
            	<groupId>org.springframework</groupId>
            	<artifactId>spring-web</artifactId>
            	<version>6.1.5</version>
        	</dependency>
    	</dependencies>
	</dependencyManagement>
</project>

How to Use a BOM in a POM

Application POM

├── dependencyManagement
│ └── import example-bom

├── dependencies
│ ├── spring-core
│ ├── spring-web
│ └── jackson-databind


Maven Resolves Versions From BOM

Importing a BOM

<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>

Using Dependencies Without Versions

<dependencies>
	<dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-context</artifactId>
	</dependency>

	<dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-web</artifactId>
	</dependency>
</dependencies>

Versions are automatically resolved from the BOM.


Differences Between POM and BOM

AspectPOMBOM
PurposeBuild & manage a projectManage dependency versions
Packagingjar / war / pompom only
Contains dependencies✅ Yes✅ Yes (in dependencyManagement)
Builds an artifact✅ Yes❌ No
Declares plugin config✅ Yes❌ Typically no
Used via inheritance✅ Yes✅ Yes
Used via import❌ No✅ Yes
                    ┌────────────────────┐
│ Parent POM │
│────────────────────│
│ Plugins │
│ Build Config │
│ Java Version │
│ Repositories │
└─────────┬──────────┘
│ inherits

┌─────────────────────────────────────────────────────┐
│ Application POM │
│─────────────────────────────────────────────────────│
│ Uses Plugins & Build from Parent │
│ │
│ dependencyManagement │
│ └── import → BOM │
│ │
│ dependencies │
│ ├── spring-context │
│ ├── spring-web │
│ └── jackson-databind │
└─────────────────────────────────────────────────────┘

│ imports
┌─────────┴──────────┐
│ BOM │
│────────────────────│
│ Dependency Versions│
│ Only │
└────────────────────┘
ComponentControls
Parent POMHow you build
BOMWhich versions you use
App POMWhat you actually need

Typical Use Cases

POM Use Cases

  • Define application dependencies
  • Configure build plugins
  • Package applications
  • Create parent POMs
  • Multi-module project management

BOM Use Cases

  • Enforce consistent dependency versions
  • Share version catalogs across teams
  • Avoid “dependency hell”
  • Simplify upgrades
  • Manage large microservice ecosystems

Handling Multi-module project with BOM

                    Company BOM
(Versions for All)


┌────────────┴───────────┐
│ Parent POM │
│ (Plugins & Build Rules)│
└────────────┬───────────┘

┌─────────────────────┼─────────────────────┐
│ │ │
┌───────────┐ ┌───────────┐ ┌───────────┐
│ service-a │ │ service-b │ │ service-c │
│ pom.xml │ │ pom.xml │ │ pom.xml │
│ deps w/o │ │ deps w/o │ │ deps w/o │
│ versions │ │ versions │ │ versions │
└───────────┘ └───────────┘ └───────────┘

What we achieved:

  • Upgrade Spring → 1 BOM change
  • Enforce security versions → 1 BOM change
  • Zero duplication across services

Real‑World Examples

Spring Boot BOM

Spring Boot Starter Parent

└── imports
└── spring-boot-dependencies (BOM)

├── spring-framework
├── tomcat
├── jackson
├── logback
└── hundreds more
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-dependencies</artifactId>
	<version>3.2.3</version>
	<type>pom</type>
	<scope>import</scope>
</dependency>

Spring Boot internally manages hundreds of compatible versions.


Best Practices

✅ Use a BOM when:

  • You manage multiple services
  • You want version consistency
  • You maintain internal libraries

✅ Use a Parent POM for:

  • Plugin configuration
  • Build logic
  • Common repositories

✅ Combine both:

  • Parent POM → build logic
  • Imported BOM → dependency versions

Ashish Sharma

I’ve always believed that collaboration is the engine of progress. While many say knowledge is power, I believe the true power lies in its distribution. To that end, I am building a curated knowledge base of my professional journey—refined by AI for maximum clarity and depth. Whether you’re here to master a new skill or sharpen an existing one, my goal is to provide a roadmap for your success. This collection will evolve as I do, and I welcome your insights and dialogue as we grow together.

Leave a Reply

Your email address will not be published. Required fields are marked *