skip to content

What does it mean for a Maven plugin goal to be 'bound' to a lifecycle phase, and why does running a phase execute plugin goals?

level: juniorimportance: must knowfreq 70%

answer

  1. phase = empty stage
  2. goal = real work
  3. binding = glue
  4. packaging picks defaults
  5. mvn package runs all prior phases

basics

~20 s

A lifecycle phase (like compile) is just a named step that does nothing by itself. Plugin goals are 'bound' to phases, so running 'mvn compile' actually runs the goals attached to that phase, like compiler:compile.

solid answer

~40 s

Maven's build lifecycle is an ordered sequence of named phases (validate, compile, test, package, install, deploy, etc.), but the phases themselves contain no logic. The real work is done by plugin goals (e.g., compiler:compile, surefire:test, jar:jar). Binding is the association between a goal and a phase. When you run `mvn package`, Maven walks every phase up to and including `package` in order, and for each phase executes whatever goals are bound to it. Most bindings come 'for free' from the packaging type (jar, war, etc.), which selects a default set of goal-to-phase bindings. You can add more bindings via an `<execution>` block under a plugin, choosing the goal and the `<phase>`. So phases give ordering; goals give behavior; bindings glue them together.

code

bash · 3 lines
bash
# Runs every phase up to package, executing each phase's bound goals:
mvn package
# => resources:resources, compiler:compile, surefire:test, jar:jar

go deeper

for a junior

Know that phases are empty steps and goals do the work; running a phase runs the goals bound to it.

for a middle

Name the default jar bindings (compiler:compile, surefire:test, jar:jar, install:install) and that prior phases run too.

for a senior

Explain that packaging selects the binding set and how custom executions extend it without losing defaults.

for a principal

Reason about lifecycle design: why Maven separates ordering (phases) from behavior (goals), and the governance implications for standardized builds across many modules.

## The problem: phases are empty Maven defines a **build lifecycle**: an ordered list of **phases** such as `validate` -> `compile` -> `test` -> `package` -> `verify` -> `install` -> `deploy`. A phase is only a *name marking a stage* of the build. By itself a phase does nothing. ## Goals do the work Actual behavior lives in **plugin goals**. A goal is one task implemented by a Maven plugin (a Mojo). Examples written as `plugin:goal`: - `maven-compiler-plugin:compile` (short: `compiler:compile`) — compiles `src/main/java`. - `maven-surefire-plugin:test` (`surefire:test`) — runs unit tests. - `maven-jar-plugin:jar` (`jar:jar`) — packages classes into a JAR. - `maven-install-plugin:install` — copies the artifact into your local `~/.m2` repository. - `maven-deploy-plugin:deploy` — uploads to a remote repository. ## Binding = goal attached to a phase A **binding** says "run goal X during phase Y". When you invoke `mvn package`, Maven executes **every phase in order up to and including `package`**, and for each phase runs the goals bound to it. That is why one command runs many goals. ## Where do default bindings come from? They are chosen by the project's `<packaging>` element. For `jar` packaging, Maven binds (among others): - `process-resources` -> `resources:resources` - `compile` -> `compiler:compile` - `test` -> `surefire:test` - `package` -> `jar:jar` - `install` -> `install:install` - `deploy` -> `deploy:deploy` Other packagings (`war`, `pom`, `maven-plugin`) get different default bindings. ## Adding your own binding You bind extra goals with an `<execution>` under a plugin in `<build><plugins>`, naming the `<phase>` and the `<goal>`: ```xml <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <id>print-version</id> <phase>validate</phase> <goals><goal>echo</goal></goals> </execution> </executions> </plugin> ``` ## Mental model Phases = the *when* and the *order*. Goals = the *what*. Bindings = the wiring. The packaging type ships a sensible default wiring so a plain `mvn install` already compiles, tests, packages, and installs without you configuring anything.

  • If you run `mvn install`, does it also run `compile` and `test`?
    Yes. Maven executes all phases before `install` in order, so resources, compile, test, and package goals all run first.
  • Can a single phase have more than one goal bound to it?
    Yes. Multiple goals can bind to the same phase; they execute in declaration order (plugins in pom order, then their executions).

Phases are numbered slots on an assembly line; goals are the machines you bolt into a slot. An empty slot still exists in the line order but does nothing until a machine (goal) is bound to it.

saying these in an interview costs you the question

  • Saying a phase itself contains the build logic
  • Thinking `mvn package` only runs the package goal and nothing before it
  • Confusing a phase name with a goal name (e.g., treating `compile` the phase as the same thing as `compiler:compile`)

context