# Maven Core Components and Their Functions: A Deep Dive into Apache Maven's Architecture

> Explore Maven core components like MavenCli, MavenProject, and PluginManager. Understand their functions in Apache Maven's architecture for efficient build management.

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

---

**Apache Maven's build engine is orchestrated by a tightly-coupled set of Java components including MavenCli, Maven, MavenSession, MavenProject, ProjectBuilder, and PluginManager that together handle command-line parsing, project resolution, dependency graph construction, and plugin execution.**

Understanding Maven core components and their functions is essential for extending Maven, writing custom plugins, or embedding the build engine in other tools. The `apache/maven` repository organizes these components into a deterministic architecture centered around immutable execution requests and session-based state management.

## The Command-Line Interface: MavenCli and MavenExecutionRequest

### Parsing CLI Options

The **MavenCli** class serves as the entry point for the `mvn` command. Located in [`compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java`](https://github.com/apache/maven/blob/main/compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java), this component parses command-line arguments, configures logging, and prepares the environment for the build. It handles options such as offline mode, custom properties, and specified goals before delegating to the core engine.

### Building the Execution Request

**MavenExecutionRequest** is an immutable-ish holder for all user-supplied configuration. Defined in [`impl/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java), this interface captures goals, system properties, repository settings, and profile activation. The CLI builds this request object once and passes it to the Maven engine, ensuring reproducible builds through stateless configuration.

## The Build Engine: Maven and MavenSession

### Maven as the Central Orchestrator

The **Maven** component (implementation in `impl/maven-core`) acts as the central orchestrator that coordinates the entire build lifecycle. It receives the `MavenExecutionRequest`, bootstraps the container, and drives the reactor. According to the source code, this component creates the `MavenSession` and manages the transition from request to execution.

### MavenSession as Runtime Context

**MavenSession** provides the runtime context for a single Maven build. Found in [`impl/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java), this class stores the execution request, the result object, the list of projects, the current project, and the repository session. It maintains a `ThreadLocal<MavenProject>` to safely track the current project during parallel builds, allowing plugins to call `session.getCurrentProject()` without race conditions.

## Project Resolution: MavenProject and ProjectBuilder

### From POM XML to MavenProject

**MavenProject** represents the in-memory model of a single POM. Defined in [`impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/project/MavenProject.java), it contains project coordinates, build plugins, dependencies, reporting configuration, and the resolved artifact. This object is the primary data structure that plugins interact with during the build.

### Handling Inheritance and Profiles

The **ProjectBuilder** interface, implemented by `DefaultProjectBuilder` in [`impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java), transforms raw POM files into `MavenProject` instances. This component handles XML parsing, parent POM inheritance, property interpolation, profile activation, and validation. It ensures that multi-module project hierarchies are correctly resolved before the reactor sorts the build order.

## Dependency and Repository Management

### ProjectDependencyGraph

After project building, Maven constructs a **ProjectDependencyGraph** (defined in [`impl/maven-core/src/main/java/org/apache/maven/execution/ProjectDependencyGraph.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/execution/ProjectDependencyGraph.java)). This directed graph represents inter-project dependencies and enables topological sorting of the reactor. It supports incremental builds by determining which projects depend on changed artifacts.

### RepositorySystemSession

Maven delegates artifact resolution to Aether through the **RepositorySystemSession**. Exposed via `MavenSession#getRepositorySession()`, this session stores repository-wide settings including mirrors, proxies, authentication, and cache configuration. It provides the bridge between Maven's project model and the underlying artifact transport layer.

## Plugin Lifecycle Management

### InternalPluginManager

The **InternalPluginManager** (located in [`impl/maven-core/src/main/java/org/apache/maven/plugin/InternalPluginManager.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/plugin/InternalPluginManager.java)) resolves, loads, and executes plugins for each project. It maintains a per-project, per-plugin context map called `pluginContextsByProjectAndPluginKey` within the `MavenSession`, ensuring that each plugin instance receives isolated state and preventing cross-contamination in multi-module builds.

### EventDispatcher and TransferListener

**EventDispatcher** publishes Maven-specific events to registered listeners and the build log. Located in [`impl/maven-core/src/main/java/org/apache/maven/monitor/event/EventDispatcher.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/monitor/event/EventDispatcher.java), it handles lifecycle notifications. The **TransferListener** tracks artifact download/upload progress, with implementations like `ConsoleMavenTransferListener` and `BatchModeMavenTransferListener` wired through the CLI to provide user feedback during network operations.

## How Maven Core Components Work Together

The interaction between these components follows a strict lifecycle:

1. **CLI → Request** – `MavenCli` parses arguments and builds a `MavenExecutionRequest`.
2. **Engine Start** – The `Maven` component receives the request and creates a new `MavenSession`.
3. **Project Building** – `Maven` invokes `ProjectBuilder` to read the top-level POM and modules, producing `MavenProject` objects.
4. **Reactor Sorting** – Projects are topologically sorted into a `ProjectDependencyGraph` and stored in the session.
5. **Plugin Execution** – `InternalPluginManager` resolves plugins and executes mojos according to the lifecycle phase.
6. **Result Collection** – `MavenExecutionResult` aggregates exceptions and the final project list.
7. **Shutdown** – The session closes, resources release, and the CLI exits with the appropriate status code.

## Key Design Patterns in Maven Core Architecture

- **Stateless Request Pattern** – `MavenExecutionRequest` is built once and never mutated during the build, ensuring deterministic behavior.
- **Thread-Local Current Project** – `MavenSession` uses `ThreadLocal<MavenProject>` to support parallel builds while allowing plugins to safely query the current project.
- **Plugin Context Isolation** – The `pluginContextsByProjectAndPluginKey` map guarantees isolated state for each plugin instance per project.
- **Extensibility via SPI** – Core services are looked up from the Plexus container, allowing custom implementations of `ProjectBuilder` and other components.

## Programmatic Usage Example

Below is a practical example demonstrating how to interact with Maven core components programmatically:

```java
// 1️⃣ Create an execution request (normally done by MavenCli)
MavenExecutionRequest request = new DefaultMavenExecutionRequest()
        .setBaseDirectory(new File("."))
        .setGoals(Collections.singletonList("install"))
        .setUserProperties(System.getProperties())
        .setOffline(false);

// 2️⃣ Build a Maven session
MavenSession session = new MavenSession(
        plexusContainer,
        request,
        new DefaultMavenExecutionResult(),
        repositorySystemSession);

// 3️⃣ Access the list of projects after building (requires ProjectBuilder)
ProjectBuilder builder = plexusContainer.lookup(ProjectBuilder.class);
ProjectBuildingResult buildResult = builder.build(
        new File("pom.xml"),
        request.getProjectBuildingRequest());

List<MavenProject> projects = buildResult.getProjects();
session.setProjects(projects);

// 4️⃣ Retrieve the current project (used inside a Mojo)
MavenProject current = session.getCurrentProject();
System.out.println("Building " + current.getArtifactId());

// 5️⃣ Resolve a plugin and execute a mojo manually
PluginManager pluginManager = plexusContainer.lookup(PluginManager.class);
PluginDescriptor descriptor = pluginManager.getPluginDescriptor(
        "org.apache.maven.plugins:maven-compiler-plugin", session);
Mojo mojo = pluginManager.getMojo(descriptor, "compile");
mojo.execute();   // In real code you would also set the MojoExecutionContext

```

## Summary

- **MavenCli** in [`compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java`](https://github.com/apache/maven/blob/main/compat/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java) serves as the entry point, parsing command-line arguments into a `MavenExecutionRequest`.
- **Maven** and **MavenSession** (in `impl/maven-core`) orchestrate the build and maintain runtime state, including thread-local current project tracking.
- **ProjectBuilder** and **MavenProject** handle POM parsing, inheritance resolution, and in-memory project representation.
- **ProjectDependencyGraph** enables topological sorting of multi-module builds, while **RepositorySystemSession** manages artifact resolution.
- **InternalPluginManager** executes plugins with isolated contexts via `pluginContextsByProjectAndPluginKey` in the session.
- The architecture emphasizes immutable requests, thread safety, and extensibility through the Plexus container.

## Frequently Asked Questions

### What is the difference between MavenSession and MavenExecutionRequest?

**MavenExecutionRequest** is an immutable configuration object created at startup that holds user-supplied settings like goals, properties, and repository configurations. **MavenSession** is the runtime context that lives for the duration of the build, storing mutable state such as the current project, plugin contexts, and the execution result. While the request defines what to build, the session tracks how the build progresses.

### How does Maven handle multi-module project builds?

Maven uses the **ProjectBuilder** to read all module POMs, then constructs a **ProjectDependencyGraph** to topologically sort projects based on inter-module dependencies. This graph, stored in `MavenSession`, determines the reactor build order and enables parallel execution while respecting dependency constraints.

### Where does Maven store plugin-specific state during a build?

Plugin state is stored in the `pluginContextsByProjectAndPluginKey` map within **MavenSession**. This map ensures that each plugin receives an isolated context per project, preventing state leakage between different modules or plugin instances during multi-module builds.

### Can Maven be embedded in other Java applications?

Yes, Maven is designed for embedding. By using the **MavenCli** or directly instantiating **MavenExecutionRequest** and **MavenSession** through the Plexus container, developers can trigger builds programmatically. The `compat/maven-embedder` module provides the necessary infrastructure to bootstrap the Maven engine within other applications.