How does Maven know what goals a plugin offers, and how do you bind a goal to a lifecycle phase?
answer
- META-INF/maven/plugin.xml = descriptor
- generated by maven-plugin-plugin
- descriptor + helpmojo goals
- defaultPhase on @Mojo
- <execution><phase> in consumer POM
basics
~20 sThe plugin ships a descriptor file, META-INF/maven/plugin.xml, generated from your @Mojo/@Parameter annotations by the maven-plugin-plugin. To bind a goal to a phase, set defaultPhase on @Mojo or add an <execution> with a <phase> in the consumer POM.
solid answer
~40 sEvery Maven plugin JAR carries a **plugin descriptor** at `META-INF/maven/plugin.xml`. It lists each goal, its implementing Mojo class, parameters, defaults, and lifecycle binding. You almost never write it by hand — the **maven-plugin-plugin**'s `descriptor` goal scans your `@Mojo`/`@Parameter` annotations at build time and generates it (it also generates a `help` goal if you bind `helpmojo`). For binding: a Mojo can declare `@Mojo(name = "x", defaultPhase = LifecyclePhase.PACKAGE)`, which auto-binds when the user just lists the plugin. More commonly the consumer POM controls it with an `<execution>` that sets `<phase>` and `<goals>`. So binding is two-sided: the plugin suggests a default phase, the POM can override or pin it explicitly. Maven uses the descriptor at runtime to map `prefix:goal` or `g:a:v:goal` to the class and inject parameters.
code
xml · 12 lines<plugin>
<groupId>com.example</groupId>
<artifactId>greeting-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<id>greet-on-package</id>
<phase>package</phase>
<goals><goal>greet</goal></goals>
</execution>
</executions>
</plugin>go deeper
Knows plugin.xml exists, is generated, and that goals bind to phases via executions.
Configures maven-plugin-plugin (descriptor + helpmojo) and writes correct <execution> bindings.
Chooses good default phases, manages goal prefixes, understands override precedence.
Defines org conventions for plugin naming/prefixes and lifecycle binding so plugins behave predictably across teams.
## The plugin descriptor A plugin JAR contains `META-INF/maven/plugin.xml` — the **plugin descriptor**. For each goal it records: the goal name, the fully-qualified Mojo class, every parameter (name, type, required, default, expression), the requested dependency-resolution scope, thread-safety, and any default lifecycle phase. Maven reads this to know what the plugin can do and how to configure it. ## You don't hand-write it The **maven-plugin-plugin** generates the descriptor from annotations. In your plugin POM: ```xml <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-plugin-plugin</artifactId> <version>3.x.x</version> <executions> <execution> <id>default-descriptor</id> <goals><goal>descriptor</goal></goals> </execution> <execution> <id>help-goal</id> <goals><goal>helpmojo</goal></goals> </execution> </executions> </plugin> ``` The `descriptor` goal (bound to `process-classes` for `maven-plugin` packaging) scans `@Mojo`/`@Parameter` and writes `plugin.xml`. `helpmojo` generates a `help` goal so users can run `mvn yourplugin:help`. ## Goal prefix The descriptor also carries a **goalPrefix** (e.g. `greeting`) so users can run `mvn greeting:greet` instead of the full `g:a:v:greet`. By convention it's derived from `*-maven-plugin` / `maven-*-plugin` naming, or set explicitly. ## Binding a goal to a phase Maven's build **lifecycle** is an ordered list of phases (validate → compile → test → package → install → deploy). A goal does nothing on its own until it's bound to a phase or invoked directly. **Two ways to bind:** 1. **Plugin-side default** — `@Mojo(name = "greet", defaultPhase = LifecyclePhase.PROCESS_RESOURCES)`. If the consumer just declares the plugin with an execution and no `<phase>`, this default applies. 2. **Consumer-side execution** — explicit and authoritative: ```xml <plugin> <groupId>com.example</groupId> <artifactId>greeting-maven-plugin</artifactId> <version>1.0.0</version> <executions> <execution> <id>greet-on-package</id> <phase>package</phase> <goals><goal>greet</goal></goals> </execution> </executions> </plugin> ``` Now `mvn package` triggers the goal automatically. You can also run it ad hoc with `mvn greeting:greet`, which ignores phase binding entirely.
- Where does the goal prefix (so you can type mvn greeting:greet) come from?From the goalPrefix in the descriptor, conventionally derived from the *-maven-plugin / maven-*-plugin artifact name, or set explicitly via the maven-plugin-plugin configuration.
- If you set defaultPhase on the Mojo and the consumer also specifies <phase>, which wins?The consumer's explicit <phase> in the execution wins; defaultPhase is only the fallback when no phase is specified.
saying these in an interview costs you the question
- Saying you write plugin.xml by hand
- Thinking a goal runs automatically with no phase binding and no direct invocation
- Confusing the lifecycle phase with the goal name
- Believing defaultPhase can't be overridden by the POM