skip to content

Why does an aggregator/parent POM use <packaging>pom</packaging>, and what does it produce?

level: juniorimportance: must knowfreq 55%

answer

  1. pom packaging = no jar, POM is the artifact
  2. required when <modules> present
  3. parent/BOM are pom-packaged
  4. installs only the .pom file
  5. minimal lifecycle, no compile

basics

~20 s

Because it isn't a real artifact like a jar — it only organizes other modules and/or shares config. packaging=pom makes Maven install just the POM file itself (no jar/war), and it is required for any POM with a <modules> section.

solid answer

~40 s

`<packaging>pom</packaging>` tells Maven this project produces **no compiled artifact** — no jar, war, or class output. Its deliverable is the POM file itself, which gets installed/deployed so other projects can reference it (as a parent via inheritance, or as a BOM via import). It is **mandatory** for an aggregator: a POM that lists `<modules>` must be packaging `pom`. It is also the natural packaging for a pure parent POM that only carries shared `<dependencyManagement>`, `<pluginManagement>`, and properties. Because there is nothing to compile, the default lifecycle for pom packaging is minimal — mostly `install`/`deploy` of the POM and processing of any modules. Trying to aggregate with `jar` packaging is a configuration error.

code

xml · 10 lines
xml
<project>
  <groupId>com.acme</groupId>
  <artifactId>acme-parent</artifactId>
  <version>1.0.0</version>
  <packaging>pom</packaging>
  <modules>
    <module>core</module>
    <module>service</module>
  </modules>
</project>

go deeper

for a junior

Knows the root/parent uses packaging=pom and makes no jar.

for a middle

Knows it is required for <modules> and used for parents/BOMs.

for a senior

Explains lifecycle differences and BOM import vs inheritance use of pom packaging.

for a principal

Decides parent-vs-BOM strategy and what gets published as pom artifacts across the org.

## What packaging means The `<packaging>` element selects which artifact a project produces and which lifecycle bindings run. `jar` (the default) compiles classes and builds a jar; `war` builds a web archive; `pom` builds *nothing executable* — its artifact **is the POM file**. ```xml <project> <groupId>com.acme</groupId> <artifactId>acme-parent</artifactId> <version>1.0.0</version> <packaging>pom</packaging> <modules> <module>core</module> </modules> </project> ``` ## Why aggregators/parents need it Two roles both require `pom` packaging: - **Aggregator:** any POM with a `<modules>` list must be `packaging=pom`. There is no source code to compile at that level; its job is to drive the reactor. - **Parent / BOM:** a POM that exists only to be inherited (or imported via `<scope>import</scope>` for a BOM) ships only its configuration, so it is `pom` packaged. ## What gets produced and stored On `install`/`deploy`, Maven places the POM into the local/remote repository under its coordinates (e.g. `com/acme/acme-parent/1.0.0/acme-parent-1.0.0.pom`). No `.jar` accompanies it. Children resolving `<parent>` or importing the BOM download just this POM. ## Lifecycle differences With `pom` packaging, the default phase bindings are sparse — there is no `compile`/`test-compile`/`package` jar step. Running `mvn install` on a pom-packaged aggregator mainly: builds the modules (reactor) and installs the POM(s). This is why an aggregator build feels like it 'just' iterates over children. ## Common errors - Forgetting `packaging=pom` on a POM that has `<modules>` → build error. - Expecting a jar from the parent directory → there isn't one by design.

  • Can a pom-packaged project also be a BOM?
    Yes. A BOM is a pom-packaged project that defines <dependencyManagement> only; consumers import it with <scope>import</scope> and <type>pom</type> to share managed versions without inheritance.
  • What artifact ends up in ~/.m2 for a pom-packaged module?
    Only the POM file itself (e.g. acme-parent-1.0.0.pom). No jar is produced or installed.

saying these in an interview costs you the question

  • Saying an aggregator can use packaging=jar.
  • Expecting the parent module to produce a runnable/compiled jar.
  • Confusing packaging=pom with producing an empty jar.

context