# MavenSession Object Structure and Usage: The Complete Apache Maven Guide

> Explore the MavenSession object structure and usage. Learn how this central immutable state container drives every Maven build, managing execution requests, repositories, and project reactors for efficient builds.

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

---

**The `MavenSession` object is the central immutable state container for every Maven build, encapsulating the execution request, repository system session, project reactor, and thread-local context for multi-threaded builds.**

The `MavenSession` class, located in `org.apache.maven.execution` within the `apache/maven` repository, serves as the definitive source of truth throughout the build lifecycle. It ties together user inputs, project models, and repository configurations into a single cohesive object that persists from command-line parsing to build completion. Understanding the MavenSession object structure and usage is essential for writing robust plugins, customizing build logic, and debugging complex multi-module projects.

## Core State Components

The `MavenSession` implementation 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) maintains several critical fields that define the build environment:

- **MavenExecutionRequest** – Stores command-line goals, user properties, and repository settings supplied by the CLI
- **MavenExecutionResult** – Collects build outcomes, exceptions, and per-project results as execution proceeds
- **RepositorySystemSession** – The Aether (Eclipse Aether/Maven Resolver) session handling artifact resolution, mirrors, and proxies
- **Project Reactor State** – `List<MavenProject> projects`, `allProjects`, and `topLevelProject` representing the modules being built
- **ProjectDependencyGraph** – The calculated dependency relationships between reactor projects
- **Plugin Context Map** – `pluginContextsByProjectAndPluginKey` storing per-project, per-plugin data that survives across multiple mojo executions
- **Thread-Local Current Project** – `ThreadLocal<MavenProject> currentProject` tracking which module is currently being built on each thread

## Session Construction and Initialization

Maven constructs the session through a specific sequence before the reactor builds begin:

1. **Parse Command Line** – The CLI builds a `DefaultMavenExecutionRequest` implementing the `MavenExecutionRequest` interface
2. **Create Repository Session** – `MavenSessionBuilderSupplier` in `impl/maven-impl` constructs the Aether `RepositorySystemSession`
3. **Instantiate Session** – The primary constructor stores the request, result, and repository session:

```java
public MavenSession(RepositorySystemSession repositorySystemSession,
                    MavenExecutionRequest request,
                    MavenExecutionResult result)

```

4. **Populate Projects** – After the reactor builds, `setProjects(List<MavenProject>)` initializes the project list, sets the `topLevelProject`, and configures the thread-local default
5. **Configure Dependency Graph** – Optional mutators set the `ProjectDependencyGraph` and project map for multi-module navigation

## Thread-Local Project Context

The session manages the **current project** concept through a `ThreadLocal` variable, enabling parallel builds while maintaining state isolation:

- `getCurrentProject()` returns the `MavenProject` currently being built on the calling thread
- `setCurrentProject(MavenProject project)` updates the thread-local for aggregator plugins that switch contexts
- This mechanism allows thread-safe access to project-specific data without passing project references through every method call

## Repository System Integration

The `repositorySystemSession` field bridges Maven with the underlying Aether resolver:

```java
RepositorySystemSession repoSession = session.getRepositorySession();

```

This session contains authentication details, mirror configurations, and caching policies. It remains immutable after construction, ensuring consistent artifact resolution throughout the build.

## Plugin Context Storage

Plugins persist data across multiple executions using the session's plugin context mechanism:

```java
Map<String, Object> context = session.getPluginContext(pluginDescriptor, project);
context.put("lastExecutionTime", System.currentTimeMillis());

```

The map is created lazily on first access and stored in `pluginContextsByProjectAndPluginKey`, surviving for the duration of the build to share state between related mojos.

## Code Examples

### Injecting MavenSession into a Mojo

Plugins access the session via parameter injection:

```java
@Mojo(name = "report", defaultPhase = LifecyclePhase.VALIDATE)
public class ReportMojo extends AbstractMojo {

    @Parameter(defaultValue = "${session}", readonly = true)
    private MavenSession session;

    public void execute() throws MojoExecutionException {
        MavenProject current = session.getCurrentProject();
        getLog().info("Building: " + current.getArtifactId());
        getLog().info("Goals: " + session.getGoals());
    }
}

```

### Accessing Build Properties

Retrieve user-supplied properties and execution configuration:

```java
Properties userProps = session.getUserProperties();
boolean isOffline = session.isOffline();
File localRepo = session.getLocalRepository().getBasedir();

```

### Storing Cross-Mojo Data

Maintain state between plugin executions:

```java
public void initializeBuild(MavenProject project, PluginDescriptor descriptor) {
    Map<String, Object> ctx = session.getPluginContext(descriptor, project);
    if (!ctx.containsKey("startTime")) {
        ctx.put("startTime", Instant.now());
    }
}

```

### Creating Sessions Programmatically

For standalone tools or testing:

```java
MavenExecutionRequest request = new DefaultMavenExecutionRequest()
    .setGoals(Arrays.asList("clean", "install"))
    .setBaseDirectory(new File("."));

MavenExecutionResult result = new MavenExecutionResult();
MavenSession session = new MavenSession(repoSystemSession, request, result);
session.setProjects(projectList);

```

## Migration to the Maven 4 API

Maven 4 introduces `org.apache.maven.api.Session` as the modern abstraction. The legacy `MavenSession` maintains a reference to this new API via the `session` field, allowing plugins to bridge between legacy code and new API-centric extensions. Core components set this via `setSession(Session apiSession)` while maintaining backward compatibility with existing plugins that rely on the classic `MavenSession` API.

## Summary

- **MavenSession** serves as the immutable container for all build state, located in `org.apache.maven.execution`
- **Construction** follows a strict path: request parsing → repository session creation → constructor invocation → project population
- **Thread-local management** enables safe parallel execution by tracking the current project per thread via `currentProject`
- **Plugin contexts** provide durable key-value storage across multiple executions of the same plugin on the same project
- **Repository integration** exposes the underlying Aether session through `getRepositorySession()` for direct artifact manipulation
- **Maven 4 compatibility** bridges legacy `MavenSession` code with the new `org.apache.maven.api.Session` abstraction

## Frequently Asked Questions

### How do I access the MavenSession inside a plugin?

Inject the session using the `@Parameter` annotation with `defaultValue="${session}"`. This provides read-only access to the build state, including the current project, user properties, and repository configuration. Access the current project via `session.getCurrentProject()` to determine which module is being built.

### What is stored in the MavenSession thread-local current project?

The `currentProject` ThreadLocal stores a reference to the `MavenProject` actively being built on the specific execution thread. During parallel builds, each thread maintains its own current project reference, allowing thread-safe access to project-specific data without synchronization overhead.

### How does MavenSession differ from MavenProject?

`MavenSession` represents the global build state spanning all modules and the entire execution lifecycle, while `MavenProject` represents a single module's model (POM, dependencies, build configuration). The session contains the list of all projects and tracks which one is currently being built via the thread-local context.

### Can I modify the MavenSession during a build?

Most `MavenSession` fields are immutable after construction, but the **plugin context map** and **current project** thread-local are mutable. Plugins can store data in `getPluginContext()` and change the current project via `setCurrentProject()`, but should not attempt to modify the execution request or repository session after initialization.