# How to Customize the Jenkins Build Process with Maven: A Complete Guide

> Master Jenkins build customization with Maven. Learn to configure execution, JVM options, settings files, and environment variables for powerful builds.

- Repository: [Jenkins/jenkins](https://github.com/jenkinsci/jenkins)
- Tags: how-to-guide
- Published: 2026-07-30

---

**Jenkins provides a dedicated Maven builder (`hudson.tasks.Maven`) that lets you customize builds through executable selection, JVM options, settings files, and automatic environment variable injection.**

Customizing the Jenkins build process with Maven is essential for teams requiring fine-grained control over their CI/CD pipelines. According to the `jenkinsci/jenkins` source code, the `hudson.tasks.Maven` class implements a flexible builder that manages everything from tool resolution to argument construction. Understanding these internals allows you to optimize builds for performance, isolation, and reproducibility.

## Core Components of the Maven Build System

The Maven integration relies on three primary classes working together:

| Component | Source File | Purpose |
|-----------|-------------|---------|
| **Maven Builder** | [`core/src/main/java/hudson/tasks/Maven.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/hudson/tasks/Maven.java) | The build step that launches Maven, parses targets, and assembles command lines. |
| **MavenInstallation** | Inner class of [`Maven.java`](https://github.com/jenkinsci/jenkins/blob/main/Maven.java) | Represents a Maven installation, resolves the executable path, and configures environment variables like `M2_HOME` and `PATH+MAVEN`. |
| **GlobalMavenConfig** | [`core/src/main/java/jenkins/mvn/GlobalMavenConfig.java`](https://github.com/jenkinsci/jenkins/blob/main/core/src/main/java/jenkins/mvn/GlobalMavenConfig.java) | Supplies default [`settings.xml`](https://github.com/jenkinsci/jenkins/blob/main/settings.xml) and [`global-settings.xml`](https://github.com/jenkinsci/jenkins/blob/main/global-settings.xml) paths that can be overridden per-job. |

## How the Maven Builder Executes Your Build

The `perform` method in [`hudson/tasks/Maven.java`](https://github.com/jenkinsci/jenkins/blob/main/hudson/tasks/Maven.java) orchestrates execution through six distinct phases:

1. **Target Parsing** – The `targets` field splits on the pipe character (`|`), allowing multiple Maven invocations in a single build step (e.g., `"clean install | site"`).

2. **Executable Resolution** – If `mavenName` references a `MavenInstallation`, Jenkins calls `MavenInstallation.getExecutable` to locate the binary. If unconfigured, `DecideDefaultMavenCommand` inspects the workspace for [`pom.xml`](https://github.com/jenkinsci/jenkins/blob/main/pom.xml) to choose between `mvn` or `maven`.

3. **Settings Handling** – Unless the user passes `-s` or `-gs` arguments, the builder injects paths from `SettingsProvider.getSettingsRemotePath` and `GlobalSettingsProvider.getSettingsRemotePath`.

4. **Environment Injection** – When `injectBuildVariables` is `true` (default), Jenkins automatically adds `-D` arguments for all build variables before appending custom properties from the `properties` field.

5. **Private Repository Isolation** – Setting `usePrivateRepository` to `true` adds `-Dmaven.repo.local=$WORKSPACE/.repository` to isolate dependencies per build.

6. **Process Launch** – The assembled `ArgumentListBuilder` is passed to `Launcher.launch()`. On Unix, the command executes directly; on Windows, it converts to a batch command.

## Customization Points and Configuration Fields

You can configure these fields in the job UI or through Pipeline steps:

| Field | Control | Example |
|-------|---------|---------|
| `targets` | Maven goals and CLI options | `"clean package -DskipTests"` |
| `mavenName` | Reference to a `MavenInstallation` | `"Maven-3.9"` |
| `pom` | Relative path to POM file | `"submodule/pom.xml"` |
| `properties` | Additional `-D` properties (newline-separated) | `"env=prod\nopt=true"` |
| `jvmOptions` | Memory and JVM settings (`MAVEN_OPTS`) | `"-Xmx2g -XX:+UseG1GC"` |
| `usePrivateRepository` | Boolean for isolated local repos | `true` |
| `settings` / `globalSettings` | Custom XML configuration files | `FilePathSettingsProvider` instance |
| `injectBuildVariables` | Automatic `-D` variable injection | `true` (default) |

## Configuring Maven Installations Globally

Before customizing individual jobs, define your Maven tools:

1. Navigate to *Manage Jenkins* → *Global Tool Configuration* → *Maven*.
2. Add a `MavenInstallation` specifying the name and `MAVEN_HOME` directory, or enable the automatic installer (implemented in the inner class `MavenInstaller`).
3. The `Maven.DescriptorImpl` class persists these configurations via the `setInstallations` method.

Jenkins stores this metadata to resolve executables via `MavenInstallation.getExecutable` at runtime.

## Using Maven in Jenkins Pipelines

For Pipeline projects, use the `tools` directive to expose the installation, then invoke Maven directly or through the builder:

```groovy
pipeline {
    agent any
    tools {
        maven 'Maven-3.9'  // Must match a configured MavenInstallation name
    }
    environment {
        APP_ENV = 'production'
    }
    stages {
        stage('Build') {
            steps {
                sh '''
                    mvn clean install \
                        -Dmaven.repo.local=$WORKSPACE/.repository \
                        -Dapp.env=$APP_ENV
                '''
            }
        }
    }
}

```

Alternatively, the `withMaven` step wraps the same `hudson.tasks.Maven` logic and accepts parameters like `mavenSettingsConfig` and `injectBuildVariables: false` for advanced customization.

## Advanced Customization Scenarios

| Scenario | Implementation |
|----------|----------------|
| **Version-per-branch builds** | Define separate `MavenInstallation` entries (e.g., `Maven-3.8`, `Maven-3.9`) and parameterize the `mavenName` field. |
| **Custom settings.xml per job** | Configure the *Settings file* option to use a `FilePathSettingsProvider`, which overrides `GlobalMavenConfig` defaults for that specific build. |
| **Disable variable injection** | Set `injectBuildVariables` to `false` in the UI or Pipeline to prevent automatic `-D` argument generation. |
| **Chained Maven commands** | Use pipe syntax in targets: `"clean deploy | site-deploy"` executes sequentially while preserving the same environment context. |

## Summary

- The `hudson.tasks.Maven` class is the core engine for Maven integration, handling command assembly in its `perform` method.
- Configure `MavenInstallation` instances globally to manage multiple Maven versions and automatic downloads.
- Use `injectBuildVariables` to automatically pass Jenkins environment variables as Maven properties, or disable it for stricter control.
- Enable `usePrivateRepository` to ensure build isolation through per-workspace local repositories.
- Override global settings via `GlobalMavenConfig` or per-job providers like `FilePathSettingsProvider`.

## Frequently Asked Questions

### How do I specify a custom Maven version for a specific job?

Define multiple `MavenInstallation` entries in *Global Tool Configuration*, then reference the specific installation name in your job configuration via the `mavenName` field. In Pipeline, use the `tools { maven 'InstallationName' }` block.

### Where does Jenkins find the settings.xml file?

By default, Jenkins reads paths from [`GlobalMavenConfig.java`](https://github.com/jenkinsci/jenkins/blob/main/GlobalMavenConfig.java). You can override this per-job by selecting a custom provider (such as `FilePathSettingsProvider`) in the build step configuration, or by passing explicit `-s` and `-gs` arguments in your targets.

### Can I run multiple Maven commands in a single build step?

Yes. Enter multiple commands separated by the pipe character (`|`) in the *Goals and options* field. Jenkins executes them sequentially while maintaining the same environment variables and working directory.

### How do I disable automatic injection of Jenkins variables?

Set the `injectBuildVariables` field to `false` in the Maven build step configuration. In Pipeline syntax using the `withMaven` step, specify `injectBuildVariables: false` to prevent the builder from automatically passing build parameters as system properties.