# How Maven’s mvnup Model Upgrade Migration Works for POM Files

> Learn how Maven's mvnup upgrades POM files from model versions 4.0.0 to 4.1.0. Automate XML namespaces, modules, and phase name conversions for Maven 4 syntax.

- Repository: [The Apache Software Foundation/maven](https://github.com/apache/maven)
- Tags: migration-guide
- Published: 2026-07-05

---

**The `mvnup` command automates Maven POM migrations from model version 4.0.0 to 4.1.0 by executing the `ModelUpgradeStrategy`, which updates XML namespaces, converts deprecated `<modules>` elements to `<subprojects>`, migrates legacy phase names to Maven 4 syntax, and preserves original formatting.**

Maven 4 introduces a stricter POM model with version 4.1.0 and a revised XML namespace. To help developers transition existing projects, the `apache/maven` repository provides the **`mvnup`** command-line tool, which implements a **Maven mvnup model upgrade migration** strategy that handles structural transformations automatically.

## Architecture of the mvnup Migration Tool

The migration tool follows a strategy-based architecture where specialized components handle distinct aspects of the upgrade process.

### Entry Points and Orchestration

The migration begins in [`impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/Help.java`](https://github.com/apache/maven/blob/main/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/Help.java), which parses CLI options such as `--model` and `--all`. The **`StrategyOrchestrator`** class, located at [`impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/StrategyOrchestrator.java`](https://github.com/apache/maven/blob/main/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/StrategyOrchestrator.java), coordinates execution by discovering POM files and invoking applicable strategies in priority order. The **Model‑Upgrade strategy** runs at approximately priority 40.

### Context and Utility Classes

The **`UpgradeContext`** class ([`impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/UpgradeContext.java`](https://github.com/apache/maven/blob/main/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/UpgradeContext.java)) maintains the `InvokerRequest`, parsed `UpgradeOptions`, and provides indented logging helpers for progress reporting. **`ModelVersionUtils`** ([`impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelVersionUtils.java`](https://github.com/apache/maven/blob/main/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelVersionUtils.java)) detects current model versions by inspecting the `<modelVersion>` element or falling back to the XML namespace URI, and validates upgrade feasibility via `canUpgrade(current, target)`. Low-level XML manipulation that preserves formatting and indentation is handled by **`DomUtils`** ([`impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/DomUtils.java`](https://github.com/apache/maven/blob/main/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/DomUtils.java)).

## Step-by-Step Migration Flow

The **`ModelUpgradeStrategy`** implements the core migration logic through the following sequence:

1. **CLI Option Parsing** – `UpgradeOptions` processes arguments. If `--all` is present, `ModelUpgradeStrategy.determineTargetModelVersion` forces the target to `4.1.0`; otherwise, it uses the value supplied via `--model`.

2. **POM Discovery** – `PomDiscovery` recursively walks the project tree, returning a `Map<Path, Document>` containing every [`pom.xml`](https://github.com/apache/maven/blob/main/pom.xml) file.

3. **Applicability Check** – `ModelUpgradeStrategy.isApplicable` returns `true` when `--all` was supplied or when the target version differs from the current `MODEL_VERSION_4_0_0`.

4. **Version Detection** – For each POM, `ModelVersionUtils.detectModelVersion` identifies the current model version, falling back to the XML namespace URI if the `<modelVersion>` element is absent.

5. **Feasibility Validation** – `ModelVersionUtils.canUpgrade` ensures the transition is supported, such as `4.0.0 → 4.1.0`.

6. **Core Upgrade Execution** – `ModelUpgradeStrategy.performModelUpgrade` performs three main transformations:
   - Updates or creates the `<modelVersion>` element via `DomUtils.insertContentElement`
   - Replaces the root element's `xmlns` attribute and updates `xsi:schemaLocation` using `ModelVersionUtils.getSchemaLocationForModelVersion`
   - Renames `<modules>` to `<subprojects>` and `<module>` to `<subproject>` for target versions ≥ 4.1.0, including within `<profiles>` sections

7. **Phase Name Migration** – Inside `<build>` and within profiles, deprecated Maven 3 phase names (e.g., `pre-clean`, `post-site`) are converted to Maven 4 equivalents (`before:clean`, `after:site`) using a mapping generated by `createPhaseUpgradeMap`.

8. **Result Reporting** – An **`UpgradeResult`** object tracks processed, modified, and error POMs for the final console summary.

## Key Source Files and Implementation Details

The migration logic is implemented in the following files within the `impl/maven-cli` module:

- **[`ModelUpgradeStrategy.java`](https://github.com/apache/maven/blob/main/ModelUpgradeStrategy.java)** – [`impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategy.java`](https://github.com/apache/maven/blob/main/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategy.java) contains applicability logic (lines 88-110), core upgrade implementation (lines 144-166), and module-to-subproject conversion (lines 198-226).

- **[`ModelVersionUtils.java`](https://github.com/apache/maven/blob/main/ModelVersionUtils.java)** – [`impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelVersionUtils.java`](https://github.com/apache/maven/blob/main/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelVersionUtils.java) handles version detection, upgrade path validation, and supplies namespace and schema location constants.

- **[`StrategyOrchestrator.java`](https://github.com/apache/maven/blob/main/StrategyOrchestrator.java)** – [`impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/StrategyOrchestrator.java`](https://github.com/apache/maven/blob/main/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/StrategyOrchestrator.java) coordinates discovery and strategy execution.

- **[`PomDiscovery.java`](https://github.com/apache/maven/blob/main/PomDiscovery.java)** – [`impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/PomDiscovery.java`](https://github.com/apache/maven/blob/main/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/PomDiscovery.java) locates all [`pom.xml`](https://github.com/apache/maven/blob/main/pom.xml) files in multi-module builds.

- **[`DomUtils.java`](https://github.com/apache/maven/blob/main/DomUtils.java)** – [`impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/DomUtils.java`](https://github.com/apache/maven/blob/main/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/DomUtils.java) preserves XML formatting during element insertion and removal.

## Practical Usage Examples

### Running the Migration

```bash

# Preview changes without modifying files

mvnup check

# Apply 4.1.0 upgrade to all POMs in the project tree

mvnup apply --all

```

### Transformation Results

**Before migration:**

```xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <modules>
        <module>module-a</module>
        <module>module-b</module>
    </modules>
    <build>
        <plugins>
            <plugin>
                <executions>
                    <execution>
                        <phase>pre-clean</phase>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

```

**After `mvnup apply --all`:**

```xml
<project xmlns="http://maven.apache.org/POM/4.1.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.1.0
                             https://maven.apache.org/xsd/maven-4.1.0.xsd">
    <modelVersion>4.1.0</modelVersion>
    <subprojects>
        <subproject>module-a</subproject>
        <subproject>module-b</subproject>
    </subprojects>
    <build>
        <plugins>
            <plugin>
                <executions>
                    <execution>
                        <phase>before:clean</phase>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

```

## Summary

- The **`mvnup`** command automates Maven 4 POM migrations through the `ModelUpgradeStrategy` class at priority 40.
- **Model version updates** change POMs from `4.0.0` to `4.1.0`, including namespace and schema location updates.
- **Structural transformations** rename `<modules>` to `<subprojects>` and update deprecated phase names to Maven 4 syntax (`pre-clean` → `before:clean`).
- **Formatting preservation** is handled by `DomUtils` to maintain XML indentation and comments.
- **Validation** occurs via `ModelVersionUtils.canUpgrade` to ensure only supported migration paths are executed.

## Frequently Asked Questions

### What is the `mvnup` command in Maven 4?

The `mvnup` command is a CLI tool introduced in Maven 4 that automates the migration of POM files from the legacy 4.0.0 model to the newer 4.1.0 model. According to the `apache/maven` source code, it executes strategies like `ModelUpgradeStrategy` to handle namespace updates, structural changes, and phase name migrations automatically.

### How does `mvnup` determine if a POM needs upgrading?

The `ModelUpgradeStrategy.isApplicable` method checks if the `--all` flag was passed or if the target model version differs from the current version. `ModelVersionUtils.detectModelVersion` identifies the current schema by first inspecting the `<modelVersion>` element, then falling back to parsing the XML namespace URI if the element is missing.

### What structural changes does the Maven model upgrade perform?

Besides updating the model version and XML namespace, the migration renames the `<modules>` element to `<subprojects>` and each `<module>` child to `<subproject>`, including occurrences within `<profiles>` sections. It also converts deprecated Maven 3 phase names like `pre-clean` and `post-site` to Maven 4's `before:clean` and `after:site` syntax using the `createPhaseUpgradeMap` method.

### Are there any prerequisites before running `mvnup apply`?

Ensure your project is under version control and you have Maven 4 installed. The `mvnup check` command allows you to preview changes before applying them, as the tool modifies XML files in-place while preserving formatting via `DomUtils`. The tool validates upgrade paths through `ModelVersionUtils.canUpgrade` to prevent invalid transitions.