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?
answer
- phase>none = unbind
- match the inherited id
- default-<goal> ids
- skipTests vs maven.test.skip
- merge-by-id is the mechanism
basics
~10 sRedeclare 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>'.
solid answer
~40 sThere are two levers. (1) **Unbind an execution**: redeclare the same plugin and an `<execution>` with the matching `<id>` and set `<phase>none</phase>`. Default bindings from packaging have well-known ids like `default-jar`, `default-test`, `default-compile`; redeclaring `default-jar` with phase `none` stops the jar from being built. Parent-POM executions are overridden the same way by matching their id. (2) **Skip via configuration**: many plugins expose a skip parameter — `surefire` has `<skipTests>`/`-DskipTests` and `<skip>`, `jar` and others vary. Skipping leaves the binding in place but makes the goal a no-op. Prefer `phase>none` when you genuinely want the goal removed, and the skip flag for conditional/profile-driven cases. The id-merge rule is what makes this work: same id merges, so your redeclaration overrides the inherited one rather than adding a duplicate.
code
xml · 11 lines<!-- Stop a module from building its jar (override packaging default) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>default-jar</id>
<phase>none</phase>
</execution>
</executions>
</plugin>go deeper
Know -DskipTests skips running tests.
Use a plugin's <skip> config and know skipTests vs maven.test.skip.
Apply phase>none with the correct default-<goal> id to truly unbind an inherited goal.
Design parent POMs with stable execution ids so overrides are predictable, and choose skip-vs-unbind deliberately across a large module tree.
## Why you'd override a binding A module inherits bindings from its packaging and from parent POMs. Sometimes you need to suppress one — e.g., a module that should not produce a jar, or one where you want to relocate tests to a different phase. ## Lever 1: phase 'none' (unbind by id) The canonical trick: redeclare the plugin, match the inherited execution's `<id>`, and set `<phase>none</phase>` (any unknown/non-phase value works, but `none` is the convention). Because executions merge by id, this **overrides** the inherited binding and detaches the goal from the lifecycle. Default, packaging-supplied executions have predictable ids of the form `default-<goal>`: - `default-jar` (jar:jar) - `default-compile` / `default-testCompile` - `default-test` (surefire:test) - `default-resources` / `default-testResources` - `default-install`, `default-deploy` ```xml <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <executions> <execution> <id>default-jar</id> <!-- matches the packaging default --> <phase>none</phase> <!-- unbind it: no jar produced --> </execution> </executions> </plugin> ``` ## Lever 2: skip flags (no-op the goal) Many plugins offer a skip parameter, keeping the binding but doing nothing: ```xml <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration><skipTests>true</skipTests></configuration> </plugin> ``` or on the CLI: `mvn install -DskipTests` (compiles tests but doesn't run) vs `-Dmaven.test.skip=true` (also skips compiling tests). Note these are plugin-specific; not every goal has a skip. ## Lever 3: override config / relocate You can also keep the goal but change its phase or configuration by redeclaring the same id with a new `<phase>` and `<configuration>`. This is how a parent's binding gets repointed in a child. ## Choosing - **Remove permanently for this module** -> `phase>none`. - **Conditionally / per-environment** -> skip flag, ideally toggled via a profile property. - **Keep but change when/how it runs** -> redeclare same id with new phase/config. ## Governance angle In a large reactor, design parent-POM executions with stable, documented ids so children can override predictably. Undocumented or duplicated ids make overrides brittle — a child that uses the wrong id ends up *adding* a second execution instead of suppressing the inherited one.
- What is the difference between -DskipTests and -Dmaven.test.skip=true?-DskipTests compiles test sources but skips running them (surefire/failsafe). -Dmaven.test.skip=true also skips compiling the test sources entirely.
- Why must you match the inherited execution's id to disable it?Executions merge by id during inheritance. A matching id overrides the inherited binding; a different id just adds another execution, leaving the original active.
- What are the ids of packaging-default executions?They follow default-<goal>, e.g. default-jar, default-compile, default-test, default-install.
saying these in an interview costs you the question
- Adding a new execution with a fresh id and expecting it to suppress the inherited one (it adds, not removes)
- Assuming every plugin has a skip flag
- Confusing skipTests (skip running) with maven.test.skip (skip compile + run)
- Thinking you can delete an inherited binding without redeclaring its plugin/id