How Maven API Modules Are Organized in Apache Maven 4

The Maven 4 API is organized into eleven focused, loosely-coupled modules under the top-level api directory, each defining distinct parts of the public contract—from annotations and XML handling to core types and service-provider interfaces—declaring their own Maven coordinates and assembled by the maven-api parent POM.

The Apache Maven 4 codebase introduces a completely redesigned API structure that replaces the monolithic approach of previous versions. Understanding how Maven API modules are organized is essential for plugin developers and tooling authors who need to interact with Maven's immutable public contract. The new architecture splits functionality into discrete JAR artifacts under the api directory, with the parent POM at api/pom.xml declaring the exact module order to prevent circular dependencies.

The Hierarchical Structure of Maven API Modules

The eleven Maven API modules are declared in the <modules> section of the parent POM at api/pom.xml (lines 34-46), ensuring each module compiles only after its dependencies are built. This declaration order reflects a strict layering strategy: foundational utilities form the base, immutable data models build upon them, and high-level services consume both. The hierarchy prevents circular references and guarantees that downstream consumers can depend on thin, specific artifacts rather than the entire API surface.

Foundation Layer: Annotations, DI, and XML

maven-api-annotations

The base of the dependency graph is maven-api-annotations, containing marker annotations defined in org.apache.maven.api.annotations. Key files include ThreadSafe.java and Nonnull.java, which supply compile-time nullability and threading contracts used throughout the codebase. No other Maven API module depends on it implicitly; it is the leaf of the dependency graph that all other modules import.

maven-api-di

The maven-api-di module provides lightweight dependency-injection utilities in the org.apache.maven.api.di package. The central class is ServiceLocator.java, which implements an annotation-driven service locator pattern. This module depends only on maven-api-annotations and is used by most API services to resolve implementation instances at runtime.

maven-api-xml

Found in org.apache.maven.api.xml, the maven-api-xml module defines an immutable XML abstraction consisting of XmlNode.java and XmlService.java. These types provide raw XML access for the model parser and plugins without exposing mutable DOM structures. It depends solely on maven-api-annotations.

Data Model Layer: Immutable Configuration Types

maven-api-model

The maven-api-model module contains the immutable representation of the Project Object Model (POM) in org.apache.maven.api.model. Generated from Modello MDO files, key classes include Model.java and Build.java, replacing the mutable org.apache.maven.model from previous versions. This module depends on both maven-api-annotations and maven-api-xml.

maven-api-plugin

Located in org.apache.maven.api.plugin, this module describes plugins and their mojos through immutable types like PluginDescriptor.java and MojoDescriptor.java. It depends on maven-api-annotations and maven-api-model.

maven-api-settings

The maven-api-settings module provides an immutable representation of settings.xml through Settings.java and Server.java in org.apache.maven.api.settings. It depends only on maven-api-annotations.

maven-api-toolchain

Found in org.apache.maven.api.toolchain, this module holds toolchain configuration (e.g., JDK selectors) via Toolchain.java. It depends on maven-api-annotations.

maven-api-metadata

The maven-api-metadata module defines repository metadata types like Metadata.java in org.apache.maven.api.metadata, similar to the legacy org.apache.maven.artifact.repository.metadata.Metadata. It depends on maven-api-annotations.

Service and Extension Layer

maven-api-core

The maven-api-core module is the central aggregation point located in org.apache.maven.api. It provides high-level immutable types like Project.java (lines 30-78), ProducedArtifact.java, and DependencyCoordinates.java, along with core service interfaces. According to the POM at maven-api-core/pom.xml (lines 33-62), this module depends on all other API modules: annotations, DI, XML, model, settings, toolchain, plugin, and metadata. It serves as the primary dependency for consumers who need the complete immutable model.

maven-api-spi

The maven-api-spi module defines Service-Provider Interfaces in org.apache.maven.api.spi that decouple the immutable API from concrete implementations. Key files include ModelParser.java and ProjectBuilder.java. This module depends on maven-api-core, maven-api-di, and maven-api-model, allowing Maven 3 or Maven 4 runtimes to provide their own implementations of these contracts.

maven-api-cli

Finally, maven-api-cli provides minimal command-line entry point helpers in org.apache.maven.api.cli, primarily through MavenCLI.java. This module depends on maven-api-core and maven-api-spi, making it useful for embedding Maven programmatically without the full launcher infrastructure.

Practical Usage: Working Across Maven API Modules

When building tools against the Maven 4 API, you typically interact with multiple modules through the DI layer. The ServiceLocator from maven-api-di resolves SPI implementations from maven-api-spi, while working with immutable types from maven-api-core and maven-api-model:

// Obtain a ServiceLocator (DI) – the entry point for any Maven API user
ServiceLocator locator = ServiceLocator.lookup();

// Acquire a ProjectBuilder SPI implementation (provided by the Maven runtime)
ProjectBuilder builder = locator.lookup(ProjectBuilder.class);

// Build a Project from a pom.xml file (immutable Project)
Path pom = Paths.get("/my/project/pom.xml");
Project project = builder.build(pom);

// Access model data without mutating anything
Model model = project.getModel();
String javaVersion = model.getProperties().get("maven.compiler.source");

// Retrieve the main artifact (if any)
Optional<ProducedArtifact> mainArtifact = project.getMainArtifact();
mainArtifact.ifPresent(a -> System.out.println("Main artifact: " + a.getPath()));

This code uses the ServiceLocator from maven-api-di, the ProjectBuilder SPI from maven-api-spi, and the immutable Project and Model types from maven-api-core and maven-api-model.

Summary

  • Maven API modules are strictly layered into eleven artifacts under the api directory, preventing circular dependencies through the build order declared in api/pom.xml.
  • The architecture separates concerns: annotations provide contracts, DI provides wiring, XML provides parsing, model provides POM representation, and core provides high-level services.
  • SPI modules (maven-api-spi) decouple the API from implementations, allowing Maven 4 to provide runtime-specific behavior while keeping the contract stable.
  • All types are immutable, making the API safe for concurrent plugin execution and embedding.
  • Consumers should depend on maven-api-core for general use, or specific modules (like maven-api-model) for lightweight tooling.

Frequently Asked Questions

What is the purpose of maven-api-core in Maven 4?

The maven-api-core module aggregates all other Maven API modules to provide the central immutable types and high-level service interfaces. It contains Project.java (lines 30-78) and declares dependencies on all other API modules in its POM (lines 33-62), serving as the primary entry point for consumers who need the complete Maven object model.

How does maven-api-spi differ from maven-api-core?

While maven-api-core defines the immutable data types and service interfaces that consumers use, maven-api-spi defines the Service-Provider Interfaces that implementations must provide. The SPI module depends on maven-api-core and maven-api-di, allowing runtime environments like Maven 3 or Maven 4 to inject concrete implementations of ProjectBuilder and ModelParser without exposing implementation details to API consumers.

Why are Maven API modules organized hierarchically?

The hierarchical organization enforces a strict dependency graph where foundational modules (annotations, XML, DI) have no dependencies, while higher-level modules sequentially build upon them. This structure, enforced by the module list in api/pom.xml (lines 34-46), ensures that changes to low-level utilities propagate predictably and that consumers can depend on minimal artifact sets (e.g., just maven-api-model) without pulling in the entire API surface.

Which Maven API module should I depend on for plugin development?

Plugin developers should typically depend on maven-api-core for access to Project and service interfaces, and maven-api-plugin for descriptor types like PluginDescriptor. If your plugin only needs to read the POM without full project resolution, depending solely on maven-api-model and maven-api-xml provides a lighter footprint while maintaining access to the immutable Model and XmlNode types.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →