skip to content

In a Maven multi-module project, what is the difference between aggregation and inheritance, and which POM elements express each?

level: middleimportance: must knowfreq 70%

answer

  1. aggregation = <modules>, builds together
  2. inheritance = <parent>, shares config
  3. orthogonal — often same POM
  4. aggregator points down, child points up
  5. packaging=pom for aggregator

basics

~20 s

Aggregation means a parent POM lists child <modules> so one build command builds them all. Inheritance means a child declares a <parent> and reuses its config (versions, plugins, dependencies). They are independent concerns that often live in the same POM.

solid answer

~50 s

Aggregation and inheritance solve different problems. **Aggregation** is about *building together*: an aggregator POM has `<packaging>pom</packaging>` and a `<modules>` section listing relative directories; running `mvn install` on it builds every listed module in computed dependency order (a reactor build). **Inheritance** is about *sharing configuration*: a child POM declares `<parent>` and inherits groupId/version, properties, `<dependencyManagement>`, `<pluginManagement>`, and more. The two are orthogonal — a POM can be only an aggregator, only a parent, both, or neither. In practice teams combine them: one root `pom.xml` is both the aggregator (lists modules) and the parent (children point `<parent>` back at it). But the relationship is directional: aggregator points *down* to children via `<modules>`; children point *up* to the parent via `<parent>`. Misunderstanding this leads to thinking adding a module automatically gives it the parent's config — it does not.

code

xml · 24 lines
xml
<!-- root pom.xml: BOTH aggregator and parent -->
<project>
  <groupId>com.acme</groupId>
  <artifactId>acme-parent</artifactId>
  <version>1.0.0</version>
  <packaging>pom</packaging>

  <!-- aggregation -->
  <modules>
    <module>core</module>
    <module>service</module>
  </modules>

  <!-- inheritance config shared by children -->
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.10.2</version>
      </dependency>
    </dependencies>
  </dependencyManagement>
</project>

go deeper

for a junior

Knows <modules> builds several projects at once and <parent> shares settings; may blur the two.

for a middle

Clearly separates aggregation (<modules>) from inheritance (<parent>) and knows packaging=pom.

for a senior

Explains orthogonality, when to split parent from aggregator, and the reactor ordering nuance.

for a principal

Designs repo/parent strategy across many teams: shared corporate parent vs per-repo aggregator, governance of versions via dependencyManagement.

## The two mechanisms Maven multi-module builds rest on two separate ideas that are easy to conflate because they usually share one file. ### Aggregation (the reactor) An **aggregator** (or *aggregate*) POM declares `<packaging>pom</packaging>` — it produces no jar itself — and contains a `<modules>` list. Each `<module>` is a **relative path to a directory** containing another POM: ```xml <modules> <module>core</module> <module>service</module> <module>web</module> </modules> ``` When you run a goal (e.g. `mvn install`) on the aggregator, Maven collects all listed modules into the **reactor**, computes the build order from their inter-dependencies (topological sort, not list order), and builds them in one pass. This is what lets a *monorepo* build with a single command. Aggregation points **downward**: parent knows its children. ### Inheritance (configuration reuse) A child POM declares a `<parent>`: ```xml <parent> <groupId>com.acme</groupId> <artifactId>acme-parent</artifactId> <version>1.0.0</version> </parent> ``` The child then **inherits** groupId, version, properties, `<dependencyManagement>`, `<pluginManagement>`, `<dependencies>`, `<build>` config, distribution settings, and more. Inheritance points **upward**: child knows its parent. The parent does NOT need to list the child for inheritance to work, and a child does NOT need to be a module of its parent to inherit from it. ## Orthogonality The combinations: - **Aggregator only:** lists modules but children have a different (or no) parent. - **Parent only:** a shared `acme-parent` published to a repo, no `<modules>`. - **Both (most common):** the root POM lists modules AND is the parent each child points to. - **Neither:** an ordinary leaf jar module. ## Why combine them The typical monorepo layout uses one root POM that is both: it aggregates so `mvn install` at the root builds everything, and it is the parent so every module shares plugin versions, Java version property, dependency versions via `<dependencyManagement>`, etc. This gives single-command builds plus consistent configuration. ## Common mistake Adding `<module>newthing</module>` makes the module build in the reactor, but does NOT give `newthing` the parent's managed versions unless `newthing/pom.xml` also declares the `<parent>`. They are separate wirings.

  • Can a POM be a parent without being an aggregator?
    Yes. A standalone parent POM (e.g. acme-parent published to a repository) provides shared config via inheritance and has no <modules>. Children reference it by coordinates regardless of directory location.
  • Does adding a <module> automatically apply the parent's dependencyManagement to it?
    No. The module must also declare <parent> pointing at the root for inheritance. Aggregation and inheritance are wired separately.

Aggregation is a tour bus that knows which stops to visit; inheritance is a family resemblance a child gets from a parent. A bus driver picking up a kid does not make them related, and being related does not put you on the bus.

saying these in an interview costs you the question

  • Saying aggregation and inheritance are the same thing.
  • Claiming the reactor builds modules in <modules> declaration order (it uses dependency order).
  • Believing listing a module gives it the parent's managed versions.

context