skip to content

Goal-to-Phase Binding

Which plugin goals are wired to which phases, chosen automatically by the <packaging> value. Interviewers ask it to confirm you understand that Maven runs plugins, not built-in build steps.

on this pageshow

questions

6

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

open as a page

Walk me through binding a plugin goal to a custom phase using an <execution> block. What does each sub-element control?

level: middleimportance: must knowfreq 60%

basics

~10 s

Inside a plugin you add <executions><execution>, give it an <id>, name the <phase> to attach to, list the <goals>, and optionally a <configuration>. That tells Maven to run those goals during that phase.

open as a page

How does the <packaging> element change the default goal-to-phase bindings? Contrast jar, war, pom, and maven-plugin.

level: middleimportance: should knowfreq 55%

basics

~10 s

The <packaging> value selects which plugin goals are bound by default. jar binds jar:jar at package; war binds war:war; pom binds almost nothing (only install/deploy); maven-plugin adds plugin descriptor goals.

open as a page

What is the difference between invoking `mvn test` (a phase) and `mvn surefire:test` (a goal directly)? When would you use each?

level: seniorimportance: should knowfreq 45%

basics

~20 s

mvn test runs the whole lifecycle up to test (validate, compile, test-compile, then tests). mvn surefire:test runs only that one goal, skipping compilation, so it can fail or use stale classes if you haven't built first.

open as a page

Maven has three built-in lifecycles. Name them and explain how 'clean' and 'site' relate to the default lifecycle and its goal bindings.

level: seniorimportance: should knowfreq 35%

basics

~10 s

The three lifecycles are clean, default, and site. They are independent. mvn clean package runs the clean lifecycle then the default lifecycle. clean binds clean:clean; site binds site:site.

open as a page

How would you disable or override an inherited goal binding (e.g., skip the default jar or surefire execution) coming from packaging or a parent POM?

level: principalimportance: should knowfreq 30%

basics

~10 s

Redeclare the plugin and its execution by the same id and set <phase>none</phase> to unbind it, or use the plugin's skip flag (e.g., -DskipTests / <skip>true</skip>). For default packaging executions, target the id 'default-<goal>'.

open as a page