Maven-API vs Maven-Impl Modules: Understanding the Apache Maven 4 Architecture

The maven-api modules expose the public, immutable contracts that third-party code can depend on, while the maven-impl modules supply the concrete runtime implementations that fulfill those contracts.

Apache Maven 4 restructured its codebase in the apache/maven repository to enforce a strict boundary between stable public interfaces and internal implementation details. The maven-api and maven-impl module groups form the two halves of this architecture, allowing plugin developers to compile against guaranteed-stable APIs while the Maven core team evolves the engine internals without breaking external contracts.

What Is maven-api?

The maven-api aggregate module defines the public, immutable Maven 4 API. According to the source tree at api/pom.xml, this group contains only interfaces, value objects, and service-provider contracts—never concrete implementation logic. This strict boundary ensures that external code can safely rely on these types without exposure to internal engine changes.

Core API Sub-Modules

The API aggregate organizes functionality into focused sub-modules:

  • maven-api-annotations – Annotation definitions used throughout the API
  • maven-api-di – Dependency injection abstractions (e.g., @Inject)
  • maven-api-xml, maven-api-model, maven-api-settings, maven-api-toolchain – Immutable model objects representing POMs, settings, and toolchains
  • maven-api-core, maven-api-spi, maven-api-cli – Core service-provider interfaces for project building, repository systems, and CLI operations

What Is maven-impl?

The maven-impl aggregate module, declared in impl/pom.xml, supplies the concrete implementations of the API contracts. This is where the actual Maven engine, dependency injection container, XML parsers, and command-line interface reside. All mutable runtime state and wiring logic lives here rather than in the API.

Implementation Components

Key sub-modules within the implementation aggregate include:

  • maven-core – The real Maven build engine handling sessions, execution, and plugin management (contains org.apache.maven.execution.MavenSession)
  • maven-logging, maven-jline – Logging infrastructure and console support
  • maven-di – The default DI container (Sisu) that wires API implementations together
  • maven-xml – XML handling utilities used by the core
  • maven-cli – The mvn command-line driver
  • maven-testing – Test harness for the implementation

Key Differences Between Maven-API and Maven-Impl

Understanding the maven-api vs maven-impl distinction requires examining four architectural boundaries:

Contract vs Realization The maven-api modules expose what Maven can do through interfaces like ModelBuilder, while maven-impl provides how it is done through concrete classes such as MavenSession.

Immutability Guarantees API modules enforce immutability in value objects (Model, Settings) to prevent external code from modifying internal state, whereas implementation classes in impl/maven-core manage mutable runtime state during builds.

Dependency Direction Code in impl/ depends on api/, but never the reverse. This ensures the API remains free of implementation details and circular references.

Service Provider Pattern The API defines service interfaces (e.g., org.apache.maven.api.services.ModelBuilder in api/maven-api-model/src/main/java/org/apache/maven/api/services/ModelBuilder.java) that the implementation fulfills, allowing runtime discovery via the DI container.

Practical Code Examples

Consuming the Stable API

When writing plugins or tools that need to parse POMs without embedding the full Maven runtime, depend only on the API. The following example uses the ModelBuilder interface:

// API only – no Maven core classes are referenced
import org.apache.maven.api.model.Model;
import org.apache.maven.api.services.ModelBuilder;
import org.apache.maven.api.services.ModelBuilderException;
import org.apache.maven.api.services.ModelSource;

ModelBuilder modelBuilder = serviceLocator.lookup(ModelBuilder.class);
Model model = modelBuilder.build(
        ModelSource.fromPath(Paths.get("pom.xml")),
        new ModelBuilderRequest()
).getModel();

This code compiles against the maven-api modules alone and works with any compliant Maven 4 implementation.

Using Implementation Classes

To execute a full build, you must use the concrete implementation classes from impl/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java and the CLI driver:

// Implementation – uses Maven core classes
import org.apache.maven.execution.MavenSession;
import org.apache.maven.cli.MavenCli;

public class BuildRunner {
    public static void main(String[] args) throws Exception {
        MavenCli cli = new MavenCli();
        // The CLI internally creates a MavenSession (implementation)
        int result = cli.doMain(new String[] {"clean", "install"}, 
                                new File(".").getAbsolutePath(), 
                                System.out, System.out);
        System.exit(result);
    }
}

This approach brings in the maven-impl modules and initializes the complete Maven engine including Sisu DI wiring and logging infrastructure.

Summary

  • maven-api defines immutable contracts, interfaces, and value objects in api/pom.xml that guarantee backward compatibility for plugin developers.
  • maven-impl provides the concrete build engine, CLI, and DI container declared in impl/pom.xml that realizes the API contracts at runtime.
  • The separation allows third-party code to depend only on the stable API while the Maven core team evolves implementation details in the impl modules.
  • API classes like org.apache.maven.api.services.ModelBuilder expose functionality without implementation details, whereas org.apache.maven.execution.MavenSession in the impl module manages mutable build state.

Frequently Asked Questions

Can I depend on maven-impl in my Maven plugin?

No. You should declare dependencies only on maven-api modules. The maven-impl classes represent internal implementation details that can change between releases. Relying on them creates brittle plugins that may break when the Maven core updates its internal structure.

What dependency injection framework does maven-impl use?

The maven-impl module uses Sisu as its default DI container, configured in the maven-di submodule. This container wires together the API interfaces with their concrete implementations at runtime, satisfying injection points defined in maven-api-di.

Are maven-api classes backward compatible across Maven 4 versions?

Yes. The maven-api modules are designed as stable, immutable contracts specifically to guarantee backward compatibility. According to the apache/maven source structure, these interfaces and value objects only change in major version releases, whereas maven-impl can evolve independently between maintenance releases.

Where can I find the source for the ModelBuilder interface?

The ModelBuilder interface resides in api/maven-api-model/src/main/java/org/apache/maven/api/services/ModelBuilder.java within the API module tree. In contrast, its runtime implementation lives in the implementation module, though external code should only reference the interface type.

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 →