# How Maven Plugins Are Defined in the API Layer: The Complete Guide

> Learn how Maven plugins are defined in the API layer using the @Mojo annotation and PluginDescriptor. Understand goal metadata and plugin XML parsing for runtime models.

- Repository: [The Apache Software Foundation/maven](https://github.com/apache/maven)
- Tags: deep-dive
- Published: 2026-07-07

---

**Maven plugins are defined in the API layer through the `@Mojo` annotation that declares goal metadata and the `PluginDescriptor` infrastructure that parses [`plugin.xml`](https://github.com/apache/maven/blob/main/plugin.xml) into runtime model objects.**

In the Apache Maven codebase, plugin semantics are formally specified entirely within the API layer through two complementary mechanisms: annotations that developers use to declare goals, and descriptor classes that Maven's core uses to interpret those declarations at runtime. This architecture ensures that plugin metadata flows from source code annotations through build-time generation to runtime execution models.

## The @Mojo Annotation API

The primary mechanism for defining Maven plugins in the API layer begins with the **`@Mojo`** annotation located in `org.apache.maven.api.plugin.annotations.Mojo`. This annotation transforms a standard Java class into a Maven goal by declaring its identity and execution requirements.

When developers extend **`org.apache.maven.api.plugin.AbstractMojo`** (or implement `org.apache.maven.api.plugin.Mojo`) and annotate their class with `@Mojo`, each attribute maps directly to corresponding fields in **`MojoDescriptor`**:

| `@Mojo` attribute | `MojoDescriptor` method |
|-------------------|-------------------------|
| `name` | `setGoal()` |
| `defaultPhase` | `setPhase()` |
| `projectRequired` | `setProjectRequired()` |
| `aggregator` | `setAggregator()` |
| `onlineRequired` | `setOnlineRequired()` |
| `configurator` | `setComponentConfigurator()` |
| `dependencyCollection` | `setDependencyCollectionRequired()` |

During compilation, Maven Plugin Tools reads these annotations and generates a [`plugin.xml`](https://github.com/apache/maven/blob/main/plugin.xml) descriptor that mirrors the annotation values exactly, bridging the gap between compile-time metadata and runtime configuration.

## Plugin Descriptor Infrastructure

At runtime, Maven loads plugin JARs and uses **`PluginDescriptorBuilder`** located in `org.apache.maven.plugin.descriptor.PluginDescriptorBuilder` to transform the XML descriptor into in-memory model objects. This builder serves as the factory for creating the runtime representation of plugin metadata.

The builder process follows three distinct steps:

1. **Namespace Detection**: Identifies the XML namespace (`PLUGIN_2_0_0`) to determine the descriptor format version.
2. **Parsing Strategy**: Uses the StAX-based `PluginDescriptorStaxReader` for the new format, or falls back to the legacy Plexus configuration path for older plugins.
3. **Model Population**: Constructs a **`PluginDescriptor`** instance containing:
   - Basic coordinates (`groupId`, `artifactId`, `version`, `goalPrefix`)
   - A collection of **`MojoDescriptor`** objects created via `buildComponentDescriptor()`
   - Dependency information, lifecycle mappings, and metadata (description, required Maven/Java versions)

The **`PluginDescriptor`** class acts as the central API model that Maven's core (`DefaultMavenPluginManager`) uses to locate and execute goals. It provides helper methods such as `getMojo(String goal)` to retrieve specific `MojoDescriptor` instances by name.

## From Annotation to Runtime Execution

Maven plugins are defined in the API layer through a complete metadata pipeline that transforms source annotations into executable components:

```

@Mojo-annotated class → Maven Plugin Tools → plugin.xml
                              ↓
                 PluginDescriptorBuilder parses plugin.xml
                              ↓
               PluginDescriptor (API model) stored in Maven core
                              ↓
                Maven resolves goal, creates Mojo instance,
                injects @Parameter fields, and executes

```

This flow demonstrates how the API layer serves as the single source of truth for plugin semantics. The annotation describes *what* a goal is, while the descriptor classes define *how* Maven should treat that goal during the build lifecycle.

## Practical Implementation Examples

### Minimal Mojo Definition

The following example demonstrates the simplest valid plugin definition using the API layer annotations:

```java
package com.example.maven;

import org.apache.maven.api.plugin.AbstractMojo;
import org.apache.maven.api.plugin.annotations.Mojo;
import org.apache.maven.api.plugin.annotations.Parameter;

/**
 * Prints a greeting.
 */
@Mojo(name = "greet", defaultPhase = "process-resources")
public class GreetMojo extends AbstractMojo {

    @Parameter(property = "greet.message", defaultValue = "Hello, Maven!")
    private String message;

    @Override
    public void execute() {
        getLog().info(message);
    }
}

```

When executing `mvn com.example.maven:greet`, Maven's core performs these API layer operations:

1. Loads the plugin JAR and locates [`plugin.xml`](https://github.com/apache/maven/blob/main/plugin.xml)
2. Uses `PluginDescriptorBuilder` to parse the descriptor and create `MojoDescriptor` instances
3. Finds the `MojoDescriptor` for the **"greet"** goal via `getMojo("greet")`
4. Instantiates `GreetMojo`, injects the `message` parameter, and invokes `execute()`

### Advanced Configuration Attributes

For complex build scenarios, the `@Mojo` annotation supports advanced execution constraints that map directly to `MojoDescriptor` flags:

```java
@Mojo(
    name = "verify",
    defaultPhase = "verify",
    aggregator = true,
    onlineRequired = true,
    dependencyCollection = true,
    configurator = "my.custom.Configurator"
)
public class VerifyMojo extends AbstractMojo {
    // implementation details
}

```

This configuration triggers specific behaviors in Maven's core:
- **`aggregator = true`** → Sets `MojoDescriptor.setAggregator(true)`, receiving the entire multi-module project context
- **`onlineRequired = true`** → Sets `MojoDescriptor.setOnlineRequired(true)`, failing fast if Maven runs in offline mode
- **`dependencyCollection = true`** → Sets `MojoDescriptor.setDependencyCollectionRequired()`, ensuring full dependency resolution before execution

## Summary

Maven defines plugins in the API layer through a rigorous annotation-to-model architecture:

- **`@Mojo`** annotations in `org.apache.maven.api.plugin.annotations` provide compile-time metadata that describes goal identity, default phases, and execution requirements
- **`PluginDescriptorBuilder`** transforms [`plugin.xml`](https://github.com/apache/maven/blob/main/plugin.xml) (generated from annotations) into `PluginDescriptor` and `MojoDescriptor` runtime models
- **`PluginDescriptor`** serves as the central API contract that Maven's core uses to locate goals, instantiate Mojos, and manage plugin lifecycle
- All metadata flows from source annotations through XML descriptors to in-memory models, ensuring consistency across the build lifecycle

## Frequently Asked Questions

### What is the difference between @Mojo and MojoDescriptor?

The **`@Mojo`** annotation is a compile-time construct located in `org.apache.maven.api.plugin.annotations.Mojo` that developers use to annotate their Java classes. **`MojoDescriptor`** is a runtime model class in `org.apache.maven.plugin.descriptor` that represents the parsed metadata as a Java object. The `PluginDescriptorBuilder` transforms the annotation data into `MojoDescriptor` instances when Maven loads a plugin.

### Where does Maven store the metadata from @Mojo annotations?

Maven stores the metadata in a file named **[`plugin.xml`](https://github.com/apache/maven/blob/main/plugin.xml)** inside the plugin's JAR file under `META-INF/maven/`. The Maven Plugin Tools processor generates this XML file during the plugin's build process by reading the `@Mojo` and `@Parameter` annotations. At runtime, the `PluginDescriptorBuilder` class parses this XML to create the `PluginDescriptor` object model.

### How does AbstractMojo relate to the API layer definition?

**`org.apache.maven.api.plugin.AbstractMojo`** provides the base implementation that connects user-written plugins to Maven's execution engine. While the `@Mojo` annotation defines the plugin's metadata for the descriptor system, `AbstractMojo` provides the `execute()` contract and `getLog()` utility that the runtime uses after the `PluginDescriptor` identifies the correct goal class to instantiate.

### Can a plugin work without the @Mojo annotation?

Technically, older plugins using the legacy Plexus container system could define metadata purely through [`plugin.xml`](https://github.com/apache/maven/blob/main/plugin.xml) descriptors without annotations. However, in modern Maven (4.x and current 3.x), the **`@Mojo`** annotation is the standard and recommended mechanism for defining Maven plugins in the API layer, as it provides type-safe metadata that the `PluginDescriptorBuilder` can reliably parse into the `MojoDescriptor` model.