skip to content

Version Management & BOM Import

Centralizing versions with <dependencyManagement> and importing a BOM to inherit a curated, tested set. Interviewers ask this to see whether you can keep versions consistent across a large build without repeating them in every module.

on this pageshow

questions

5

What does the <dependencyManagement> section in a pom.xml do, and how is it different from a plain <dependencies> section?

level: juniorimportance: must knowfreq 75%

answer

  1. policy table, not classpath
  2. child omits version, inherits
  3. centralize versions in parent
  4. overrides transitive versions too
  5. scope/exclusions/version all managed

basics

~20 s

<dependencyManagement> declares versions (and other settings) centrally but does NOT add the dependency to the build. Child modules that list the same dependency without a version inherit the managed version. Plain <dependencies> actually pulls the jar onto the classpath.

solid answer

~40 s

<dependencyManagement> is a place to centralize dependency metadata — versions, scopes, exclusions — WITHOUT actually adding anything to the classpath. It only takes effect when a real <dependencies> entry (in this POM or a child) references the same groupId:artifactId; then it can omit the version and inherit the managed one. The big win is consistency: in a multi-module reactor you set a library's version once in the parent's <dependencyManagement>, and every module that uses it stays aligned. A plain <dependencies> entry, by contrast, is a concrete request that puts the artifact on the classpath. dependencyManagement also governs versions of transitive dependencies (forcing a specific version regardless of mediation), which a top-level <dependencies> entry does too but more bluntly.

code

xml · 9 lines
xml
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.14.0</version>
    </dependency>
  </dependencies>
</dependencyManagement>

go deeper

for a junior

Knows it centralizes versions and child modules can omit the version.

for a middle

Understands it doesn't add to classpath, manages scope/exclusions, and governs transitive versions.

for a senior

Uses it to enforce org-wide consistency and to remediate vulnerable transitive deps without explicit dependencies.

for a principal

Designs a parent-POM / BOM strategy across teams, balancing central control vs module autonomy and avoiding hidden version coupling.

## What problem this solves In a project with many modules (a Maven 'reactor'), the same third-party library is often used in several modules. If each module hardcodes its own version, they drift apart and you get subtle classpath conflicts. Maven gives you a central place to declare versions once. ## <dependencyManagement> vs <dependencies> - **<dependencies>**: a list of artifacts that are ACTUALLY added to the build's classpath. Each needs a groupId, artifactId, and (unless managed) a version. - **<dependencyManagement>**: a list of *managed* declarations. Nothing is added to the classpath by this block alone. It only says "IF something references this artifact, use these settings (version/scope/exclusions) as the default." Think of it as a policy table. A child module then declares the dependency for real but can leave out the version: ```xml <!-- parent pom --> <dependencyManagement> <dependencies> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>33.2.1-jre</version> </dependency> </dependencies> </dependencyManagement> <!-- child module pom --> <dependencies> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <!-- no version: inherited from parent's dependencyManagement --> </dependency> </dependencies> ``` ## What it manages Beyond version, dependencyManagement can pin `scope`, `exclusions`, `optional`, `type`, and `classifier`. It is also the mechanism behind **BOM import** (`<type>pom</type>` + `<scope>import</scope>`). ## Effect on transitive dependencies dependencyManagement also overrides versions of *transitive* dependencies. If library A pulls in commons-lang3:3.10 transitively, but you put commons-lang3:3.14 in <dependencyManagement>, Maven forces 3.14 — dependencyManagement wins over normal mediation. This is a common, safe way to bump a vulnerable transitive jar. ## Key takeaway Declare versions in <dependencyManagement> (often in a parent or BOM); declare *usage* in <dependencies>, omitting versions so they stay centralized.

  • Does <dependencyManagement> add a jar to your classpath?
    No. It only sets defaults. You still need a <dependencies> entry (here or in a child) to actually use the artifact.
  • Can dependencyManagement change the version of a transitive dependency?
    Yes — it overrides Maven's normal mediation for transitive deps, so it's a clean way to force-bump a vulnerable transitive jar.

Like a company price list: <dependencyManagement> is the catalog of approved versions; <dependencies> is the actual order. The catalog alone buys nothing.

saying these in an interview costs you the question

  • Saying <dependencyManagement> adds the dependency to the build (it doesn't).
  • Claiming child modules automatically get every managed dependency without declaring them.
  • Confusing it with <pluginManagement>.

context

open as a page

How do you import a BOM in Maven, and what does it accomplish?

level: middleimportance: must knowfreq 70%

basics

~20 s

A BOM (Bill of Materials) is a POM that only declares versions in its <dependencyManagement>. You import it by adding it inside your own <dependencyManagement> with <type>pom</type> and <scope>import</scope>. Then you use its libraries without specifying versions.

open as a page

What does a -SNAPSHOT version mean in Maven, and how are SNAPSHOTs resolved and updated?

level: middleimportance: must knowfreq 65%

basics

~20 s

A -SNAPSHOT version (e.g. 1.2.0-SNAPSHOT) marks an in-development, mutable version. On a remote repo each deploy is stored with a unique timestamp, and Maven re-checks for newer SNAPSHOTs periodically (by default daily). Release versions are immutable.

open as a page

When centralizing versions, what is the difference between using Maven <properties> for versions versus <dependencyManagement>, and how do they interact in a multi-module project?

level: seniorimportance: should knowfreq 40%

basics

~20 s

A <properties> entry like <guava.version>33.2.1</guava.version> is just a reusable string you reference with ${guava.version}; you still write the version everywhere. <dependencyManagement> sets a managed default so child modules can omit the version entirely. Teams often combine both.

open as a page

How do Maven version ranges work (e.g. [1.0,2.0)), and why are pinned versions usually preferred?

level: seniorimportance: should knowfreq 45%

basics

~20 s

A version range like [1.0,2.0) lets Maven pick any matching version: square brackets are inclusive, parentheses exclusive. So that means >=1.0 and <2.0. Most teams instead pin an exact version (e.g. 1.4.2) for reproducible, predictable builds.

open as a page