In a Maven multi-module project, what is the difference between aggregation and inheritance, and which POM elements express each?
answer
- aggregation = <modules>, builds together
- inheritance = <parent>, shares config
- orthogonal — often same POM
- aggregator points down, child points up
- packaging=pom for aggregator
basics
~20 sAggregation 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 sAggregation 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<!-- 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
Knows <modules> builds several projects at once and <parent> shares settings; may blur the two.
Clearly separates aggregation (<modules>) from inheritance (<parent>) and knows packaging=pom.
Explains orthogonality, when to split parent from aggregator, and the reactor ordering nuance.
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.