skip to content

What is the difference between inheriting <dependencyManagement> and inheriting <dependencies> from a parent POM?

level: seniorimportance: must knowfreq 65%

answer

  1. deps = added everywhere
  2. depMgmt = recommend only
  3. child omits version to use managed
  4. pluginManagement mirrors it
  5. manages transitive versions too

basics

~10 s

<dependencies> in the parent are actually added to every child. <dependencyManagement> only sets default versions/scopes; a child still has to declare the dependency (without a version) to use it.

solid answer

~30 s

A parent's `<dependencies>` are *concrete*: they become part of every child's classpath whether or not the child wants them. A parent's `<dependencyManagement>` is *advisory*: it pins versions, scopes, and exclusions but adds nothing. A child uses a managed dependency by declaring it in its own `<dependencies>` and omitting the version, which Maven fills from management. The same distinction applies to plugins: `<pluginManagement>` configures without binding, while `<plugins>` actually binds. Best practice for a parent/BOM is to put almost everything in `<dependencyManagement>` so each module pulls only what it needs, keeping version control centralized without forcing unwanted jars onto the classpath.

code

xml · 18 lines
xml
<!-- parent -->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.17.1</version>
    </dependency>
  </dependencies>
</dependencyManagement>

<!-- child uses it without a version -->
<dependencies>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
  </dependency>
</dependencies>

go deeper

for a junior

Know parent <dependencies> are added; management is just versions.

for a middle

Show using a managed dependency by omitting the version in the child.

for a senior

Decide what belongs in management vs concrete, and explain transitive override.

for a principal

Design parent/BOM split, govern version policy across many teams, avoid classpath bloat.

## Two sections, very different meaning Both live under the project, both are inherited, but they behave oppositely. ### `<dependencies>` — concrete, added everywhere Whatever the parent lists here is **on the classpath of every child**. Use sparingly — only for things truly every module needs (e.g. a logging API, a test framework). ### `<dependencyManagement>` — advisory, adds nothing This only declares *recommended* `version`, `scope`, `exclusions`, etc. for a given `groupId:artifactId`. It does **not** put the dependency on any classpath. A child opts in by declaring the dependency and **omitting the version**: ```xml <!-- parent --> <dependencyManagement> <dependencies> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.17.1</version> </dependency> </dependencies> </dependencyManagement> <!-- child: no version, taken from management --> <dependencies> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> </dependencies> ``` ## Why prefer management - **Single source of truth for versions** across many modules. - Modules stay lean — each declares only what it uses. - It also governs **transitive** versions: dependencyManagement overrides what transitive resolution would otherwise pick. ## The plugin parallel - `<pluginManagement>` = version/config recommendations, no execution binding. - `<plugins>` (in `<build>`) = actually applied/bound to the lifecycle. Same mental model: *Management = recommend, plain = apply.* ## BOM import A related pattern is importing a Bill of Materials with `<scope>import</scope>` and `<type>pom</type>` inside `<dependencyManagement>`, which merges another project's managed versions — different from parent inheritance but solving the same versioning problem.

  • Does dependencyManagement affect transitive dependency versions?
    Yes. A version pinned in dependencyManagement overrides the version transitive resolution would otherwise choose for that artifact, which is a key reason to use it.
  • How does this relate to a BOM?
    A BOM is a POM whose dependencyManagement you import with <scope>import</scope> and <type>pom</type>, merging its managed versions into yours without parent inheritance.
  • What is the plugin equivalent of dependencyManagement?
    pluginManagement: it configures plugin versions and settings without binding executions; <plugins> under <build> actually applies them.

dependencyManagement is a price list on the wall; dependencies is what's actually in your cart. The list sets prices, but only items you put in the cart get charged.

saying these in an interview costs you the question

  • Saying dependencyManagement adds jars to the classpath
  • Forgetting the child must redeclare the dependency to use a managed version
  • Claiming pluginManagement runs plugins by itself

context