skip to content

What is the Maven reactor, and how do you build only a single module out of a large multi-module project from the command line?

level: juniorimportance: must knowfreq 70%

answer

  1. reactor = order + selection
  2. -pl / --projects selector list
  3. path OR :artifactId
  4. subset != upstream included
  5. needs -am for deps

basics

~10 s

The reactor is Maven's engine that figures out which modules to build and in what order based on dependencies. To build one module, run from the root: mvn install -pl :artifactId (or -pl module-path).

solid answer

~40 s

In a multi-module project the root (aggregator) pom lists `<modules>`. When you run Maven there, the **reactor** collects all listed modules, sorts them topologically by their inter-module dependencies, and builds them in that order. To restrict the build to specific modules you pass `-pl`/`--projects` with a comma-separated list of project selectors. A selector is either a relative directory path (e.g. `-pl core,web`) or a `groupId:artifactId` / `:artifactId` coordinate. Running `mvn install -pl :payments` builds just that one module. The catch: if `payments` depends on `core` and `core` isn't already in your local repository, the build fails because the reactor only includes what you selected. That's why `-pl` is usually combined with `-am` (also-make) to pull in upstream dependencies.

code

bash · 4 lines
bash
# from the aggregator root
mvn install -pl :payments          # one module by artifactId
mvn install -pl core,web           # two modules by path
mvn install -pl !legacy             # all modules except legacy

go deeper

for a junior

Know that -pl/--projects limits the build to named modules and selectors can be a path or :artifactId.

for a middle

Understand the reactor computes build order from inter-module dependencies and that -pl excludes upstream modules unless -am is added.

for a senior

Combine selectors with -am/-amd/-rf to design fast incremental builds and reason about resolution from local repo vs reactor.

for a principal

Define CI strategy: which modules to build per change, when to rely on installed artifacts vs reactor inclusion, and the failure modes of partial builds across teams.

## What is a multi-module project A Maven **multi-module** (a.k.a. aggregator) project has a parent/root `pom.xml` with `<packaging>pom</packaging>` and a `<modules>` section listing child directories. Each child is itself a Maven project. Building the root builds all the children together. ## What is the reactor The **reactor** is the part of Maven that, given a set of modules, (1) reads each module's dependencies, (2) computes a dependency graph, and (3) sorts the modules into a valid build order (topological sort) so that a module is always built after the modules it depends on. It then runs the requested lifecycle (e.g. `install`) on each in turn. Inter-module dependencies are recognized when one module declares another as a `<dependency>` using the same `groupId:artifactId:version`. ## Building a subset with -pl / --projects `-pl` (long form `--projects`) takes a comma-separated list of **project selectors**: - a relative path to the module directory: `-pl core,services/payments` - a coordinate `groupId:artifactId`: `-pl com.acme:payments` - a short coordinate `:artifactId`: `-pl :payments` - (Maven 3.2.1+) prefix `!` or `-` to *exclude* a module: `-pl !legacy` Maven then runs the goals only on the selected modules (still in correct reactor order among themselves). ## The dependency gotcha `-pl` does **not** automatically include upstream modules. If `payments` depends on sibling `core`, and `core` is not present in your local repo (`~/.m2/repository`), the build of `payments` cannot resolve it and fails. Solutions: install `core` first, or add `-am` (also-make) so the reactor includes `core` automatically. ```bash # build only payments (may fail if core isn't installed) mvn install -pl :payments # build payments AND everything it depends on mvn install -pl :payments -am ``` ## Why it matters On big repos, full builds are slow. Reactor selectors let you build just what you touched, dramatically shortening the feedback loop in local dev and CI.

  • Why might `mvn install -pl :payments` fail even though the module compiles fine in a full build?
    Because -pl excludes its sibling dependencies; if an upstream module like core isn't already in the local repo, dependency resolution fails. Add -am to include upstream modules.
  • What forms can a -pl selector take?
    A relative directory path, a full groupId:artifactId, a short :artifactId, and (Maven 3.2.1+) a leading ! or - to exclude a module.

The reactor is like a chef reading a recipe tree: it figures out you must chop onions before the sauce, sauce before the dish — and -pl says 'only make these dishes', not their prep.

saying these in an interview costs you the question

  • Thinking -pl automatically builds dependency modules too
  • Believing the reactor ignores build order when a subset is selected
  • Confusing -pl (projects) with -P (profiles)

context