# How to Extend Maven's Core Functionality Programmatically: A Complete Guide

> Extend Maven's core functionality programmatically by implementing AbstractMavenLifecycleParticipant. Learn how to hook into Maven's lifecycle for custom execution within its process.

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

---

**You can extend Maven's core functionality programmatically by implementing `AbstractMavenLifecycleParticipant` and registering your class as a service provider, allowing your code to execute at key lifecycle hooks inside Maven's own process.**

Maven's architecture supports deep runtime customization through *core extensions*, which are regular Java components discovered via the Plexus IoC container. According to the `apache/maven` source code, these extensions plug directly into Maven's internal lifecycle, executing before, during, and after project builds.

## The Core Extension Point: AbstractMavenLifecycleParticipant

The foundation for programmatic extension is the abstract class **`org.apache.maven.AbstractMavenLifecycleParticipant`**. Located at [[`impl/maven-core/src/main/java/org/apache/maven/AbstractMavenLifecycleParticipant.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/AbstractMavenLifecycleParticipant.java)](https://github.com/apache/maven/blob/master/impl/maven-core/src/main/java/org/apache/maven/AbstractMavenLifecycleParticipant.java), this class defines three primary callback methods that Maven invokes at critical build phases.

Maven's main entry point, [[`DefaultMaven.java`](https://github.com/apache/maven/blob/main/DefaultMaven.java)](https://github.com/apache/maven/blob/master/impl/maven-core/src/main/java/org/apache/maven/DefaultMaven.java) (lines 355-379), iterates through all registered participants and calls these methods via its internal `callListeners` logic.

### Lifecycle Callback Methods

Subclasses override the specific hooks needed for their use case:

- **`afterSessionStart(MavenSession)`** – Executes immediately after the `MavenSession` is created. Use this to inject system properties or activate profiles before project parsing begins.

- **`afterProjectsRead(MavenSession)`** – Runs after all `MavenProject` objects are built but before they are sorted and executed. Ideal for adding or modifying projects and tweaking model data.

- **`afterSessionEnd(MavenSession)`** – Invoked after the build completes (on a best-effort basis). Use for resource cleanup, statistics reporting, or post-build notifications.

## How Maven Discovers Core Extensions

Maven locates extensions using two mechanisms, loading them from the extension classpath (either the `extensions` directory in `${M2_HOME}` or via the `<extensions>` POM element):

1. **Java Service Provider (Preferred)** – A text file at `META-INF/services/org.apache.maven.AbstractMavenLifecycleParticipant` containing the fully-qualified class name of your implementation.

2. **Component Descriptor (Legacy)** – A [`META-INF/plexus/components.xml`](https://github.com/apache/maven/blob/main/META-INF/plexus/components.xml) file declaring the implementation class and its role.

When Maven starts, `DefaultMaven` automatically detects and registers these implementations, making them available for lifecycle callbacks.

## Creating a Core Extension: Step-by-Step

Follow these steps to build and deploy a Maven core extension:

1. **Create a Maven project** that packages your extension as a JAR artifact.

2. **Add the dependency** on `maven-core` (or `maven-embedder`) to compile against `AbstractMavenLifecycleParticipant`.

3. **Implement the extension class** by extending `AbstractMavenLifecycleParticipant` and overriding the necessary callback methods.

4. **Register the service** by creating the file `src/main/resources/META-INF/services/org.apache.maven.AbstractMavenLifecycleParticipant` containing your class name.

5. **Deploy the extension** by installing it to your local repository and referencing it in a project's [`pom.xml`](https://github.com/apache/maven/blob/main/pom.xml) using the `<extensions>` element.

## Complete Implementation Example

Here is a concrete implementation that logs all projects after they are read:

```java
// src/main/java/com/example/LogAfterProjects.java
package com.example;

import org.apache.maven.AbstractMavenLifecycleParticipant;
import org.apache.maven.MavenExecutionException;
import org.apache.maven.execution.MavenSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Simple core extension that logs the list of projects after they are read.
 */
public class LogAfterProjects extends AbstractMavenLifecycleParticipant {
    private static final Logger log = LoggerFactory.getLogger(LogAfterProjects.class);

    @Override
    public void afterProjectsRead(MavenSession session) throws MavenExecutionException {
        log.info("=== Maven core extension: afterProjectsRead ===");
        session.getAllProjects()
               .forEach(p -> log.info("  project: {}", p.getArtifactId()));
    }
}

```

Create the service descriptor file at `src/main/resources/META-INF/services/org.apache.maven.AbstractMavenLifecycleParticipant`:

```

com.example.LogAfterProjects

```

## Activating Your Extension in a Build

To use the extension in a project, declare it in the [`pom.xml`](https://github.com/apache/maven/blob/main/pom.xml):

```xml
<project>
    <!-- ... -->
    <build>
        <extensions>
            <extension>
                <groupId>com.example</groupId>
                <artifactId>log-after-projects</artifactId>
                <version>1.0.0</version>
            </extension>
        </extensions>
    </build>
</project>

```

When you run `mvn verify`, Maven loads your extension class, invokes `afterProjectsRead` after parsing the projects, and prints the artifact IDs to the console. This confirms that your code is executing inside Maven's core process, as implemented in the `apache/maven` repository.

## Summary

- **Core extensions** allow you to programmatically extend Maven by implementing `AbstractMavenLifecycleParticipant`.
- Three lifecycle hooks—`afterSessionStart`, `afterProjectsRead`, and `afterSessionEnd`—provide injection points before, during, and after the build.
- Maven discovers extensions via the **ServiceLoader mechanism** (`META-INF/services/`) or legacy Plexus [`components.xml`](https://github.com/apache/maven/blob/main/components.xml).
- Extensions run in Maven's own process, loaded from the extension classpath defined in [`pom.xml`](https://github.com/apache/maven/blob/main/pom.xml) or `${M2_HOME}/extensions`.

## Frequently Asked Questions

### What is the difference between a Maven plugin and a core extension?

A Maven plugin executes specific goals bound to lifecycle phases within a project build, while a core extension runs inside Maven's own process and operates on the `MavenSession` itself before any plugins execute. Core extensions can modify project lists, inject properties, and intercept the entire build lifecycle, whereas plugins are project-scoped tools.

### Can I modify project dependencies using a core extension?

Yes. Since `afterProjectsRead` receives the fully populated `MavenSession` with all `MavenProject` instances, you can programmatically manipulate the project model, including adding, removing, or modifying dependencies before Maven resolves them and executes the build.

### Where should I package my core extension so Maven can find it?

Package your extension as a JAR and either install it to your local repository and reference it via `<extensions>` in a [`pom.xml`](https://github.com/apache/maven/blob/main/pom.xml), or place it directly in the `${M2_HOME}/lib/ext` (or `extensions`) directory for global availability across all builds.

### Is the `AbstractMavenLifecycleParticipant` API stable across Maven versions?

Yes, this API has been stable since Maven 3.0 and remains the primary mechanism for core extension in Maven 4. The `apache/maven` integration test suite includes reference implementations (such as those found in `its/core-it-suite/src/test/resources/mng-7772-core-extensions-found/`) that verify this contract remains intact across releases.