Chapter 14Lesson 05~225 minutes

Checkpoint Lab — Maven 4 Preview, Build Consumer POM, Compatibility, Migration Planning, and Maven 3 Production Baselines

Produce an auditable Maven 4 migration dossier with independently pinned runtimes, build and artifact comparisons, consumer-POM evidence, blockers, rollback, and a go/no-go decision.

Checkpoint LabMigration DossierEvidenceGo/No-GoRollback

A migration dossier is the handoff artifact that lets another engineer reproduce your decision. This checkpoint creates one for a small Maven 3 project and ends with two separate conclusions: whether Maven 4 should remain in compatibility testing, and whether it should become the production standard today.

Current status — verified 2026-08-24. Apache Maven 3.9.16 is the current GA Maven 3 baseline. Maven 4.0.0-rc-6, released 2026-08-04, is still not GA and is used here only for compatibility testing. Maven 4 requires Java 17+ to run; the lab uses JDK 21 for both Maven 3 and Maven 4 so the Maven version—not the launcher JDK—is the deliberate variable. Maven Wrapper 3.3.4 remains the stable wrapper baseline. Given the official release status on 2026-08-24, the expected default decision is GO for continued Maven 4 rc-6 compatibility testing and NO-GO for organization-wide production standardization, unless an explicitly documented pre-GA exception exists. The exercise teaches the decision process, not a permanent future verdict.

Learning objectives

  • Pin Maven 3.9.16 and Maven 4.0.0-rc-6 independently and record distribution/JDK identity.
  • Capture build/test/effective-model/artifact evidence from equivalent isolated lanes.
  • Run mvnup compatibility checks for 4.0.0 and 4.1.0 targets without mutating the baseline.
  • Inspect one Maven 4 consumer-POM transformation in a Maven 4-only experimental copy.
  • Document blockers, known issues, rollback mechanics, and a go/no-go decision.
  • Revert every experimental Maven 4-only change and leave production baseline state untouched.

1. Checkpoint acceptance contract

Your dossier must contain: generation date; official Maven 3/Maven 4 status; Maven/JDK/wrapper identities; exact baseline and candidate POM hashes; Maven 3 and Maven 4 verify results; effective-POM diff; artifact checksum comparison; mvnup check output; consumer-POM observation; plugin/extension inventory; known-issue applicability; rollback instructions; and two decisions—continue compatibility testing? and standardize production now?

2. Create the dossier workspace and record predictions

set -euo pipefail
ROOT="$PWD/../maven4-checkpoint"
rm -rf "$ROOT"
mkdir -p "$ROOT"/{baseline-m3,candidate-m4,candidate-41,evidence,downloads,.lab}

cat > "$ROOT/evidence/predictions.txt" <<'EOF'
Prediction 1: model 4.0.0 source can be built by both Maven 3.9.16 and Maven 4.0.0-rc-6.
Prediction 2: with the same JDK and pinned plugins, the simple JAR should have the same SHA-256 in both lanes.
Prediction 3: model 4.1.0 will intentionally remove Maven 3 build compatibility.
Prediction 4: installed consumer metadata may differ from the source 4.1.0 build POM while preserving consumer coordinates/dependencies.
EOF

3. Capture current official status as a dated assumption

In evidence/status.txt, write the date and the exact official URLs you checked. Do not copy an old course claim blindly. For this generation the evidence is:

Checked: 2026-08-24
Maven 3 GA baseline: 3.9.16
Maven 4 latest listed release: 4.0.0-rc-6 (2026-08-04)
Maven 4 status: not yet GA / release candidate
Maven 4 runtime JDK requirement: Java 17+
Migration tool: mvnup, built into Maven 4 since rc-4
Primary sources:
  https://maven.apache.org/docs/history.html
  https://maven.apache.org/docs/4.0.0-rc-6/release-notes.html
  https://maven.apache.org/guides/mini/guide-migration-to-mvn4.html
  https://maven.apache.org/tools/mvnup.html

If those pages show different facts when you run the checkpoint later, update the dossier and decision. Status is version-sensitive evidence.

4. Create one Maven 3-compatible source baseline

Put the BASE_POM from Lesson 2 plus the deterministic App.java and one-test AppTest.java into baseline-m3. Copy the trusted Maven 3.9.16 wrapper into that directory, then clone the whole project to candidate-m4 before changing any wrapper property.

# From a trusted wrapper-enabled Maven 3.9.16 project:
cp mvnw mvnw.cmd "$ROOT/baseline-m3/"
cp -R .mvn "$ROOT/baseline-m3/"
# Add pom.xml and src/ as shown in Lesson 2.
cp -R "$ROOT/baseline-m3/." "$ROOT/candidate-m4/"

sha256sum "$ROOT/baseline-m3/pom.xml" "$ROOT/candidate-m4/pom.xml"   > "$ROOT/evidence/source-pom-before.sha256"

5. Independently pin and verify both runtimes

The Maven 3 wrapper is the pre-existing trusted baseline. For Maven 4, download rc-6 plus its SHA-512 sidecar, verify it, derive SHA-256, and add that value to the candidate wrapper's distributionSha256Sum exactly as in Lesson 2. Preserve both wrapper property files in evidence.

cd "$ROOT"
MAVEN_USER_HOME="$ROOT/.lab/home-m3" ./baseline-m3/mvnw -v | tee evidence/maven3-version.txt
MAVEN_USER_HOME="$ROOT/.lab/home-m4" ./candidate-m4/mvnw -v | tee evidence/maven4-version.txt
java -version 2> evidence/java-version.txt

cp baseline-m3/.mvn/wrapper/maven-wrapper.properties evidence/wrapper-m3.properties
cp candidate-m4/.mvn/wrapper/maven-wrapper.properties evidence/wrapper-m4.properties
Gate: both lanes must report JDK 21 in this checkpoint; Maven 3 must report 3.9.16 and Maven 4 must report 4.0.0-rc-6. Otherwise stop—the test is not comparing the intended baselines.

6. Build and compare the Maven 3 and Maven 4 lanes

cd "$ROOT/baseline-m3"
MAVEN_USER_HOME="$ROOT/.lab/home-m3" ./mvnw -Dmaven.repo.local="$ROOT/.lab/repo-m3" clean verify   | tee "$ROOT/evidence/verify-m3.log"
MAVEN_USER_HOME="$ROOT/.lab/home-m3" ./mvnw org.apache.maven.plugins:maven-help-plugin:3.5.2:effective-pom -Doutput="$ROOT/evidence/effective-m3.xml"
sha256sum target/maven4-migration-lab-1.0.0.jar   > "$ROOT/evidence/jar-m3.sha256"

cd "$ROOT/candidate-m4"
MAVEN_USER_HOME="$ROOT/.lab/home-m4" ./mvnw -Dmaven.repo.local="$ROOT/.lab/repo-m4" clean verify   | tee "$ROOT/evidence/verify-m4.log"
MAVEN_USER_HOME="$ROOT/.lab/home-m4" ./mvnw org.apache.maven.plugins:maven-help-plugin:3.5.2:effective-pom -Doutput="$ROOT/evidence/effective-m4.xml"
sha256sum target/maven4-migration-lab-1.0.0.jar   > "$ROOT/evidence/jar-m4.sha256"

diff -u "$ROOT/evidence/effective-m3.xml" "$ROOT/evidence/effective-m4.xml"   > "$ROOT/evidence/effective-model.diff" || true

Record whether the JAR digest values match. If not, inspect JAR entries, manifest metadata, plugin behavior, and timestamps before continuing. Never wave away a byte difference because “both builds succeeded.”

7. Capture compatibility and migration-tool findings

cd "$ROOT"
mkdir -p .lab/tools
unzip -q downloads/apache-maven-4.0.0-rc-6-bin.zip -d .lab/tools
M4_HOME="$ROOT/.lab/tools/apache-maven-4.0.0-rc-6"

"$M4_HOME/bin/mvnup" check --directory candidate-m4   | tee evidence/mvnup-400.txt
"$M4_HOME/bin/mvnup" check --model-version 4.1.0 --all --directory candidate-m4   | tee evidence/mvnup-410.txt

Classify every finding as: required for Maven 4 compatibility while staying model 4.0.0; optional Maven 4-only model improvement; plugin/extension update; or unrelated cleanup. Do not let mvnup apply cross the compatibility boundary implicitly.

8. Make Maven 4-only changes only in candidate-41

Copy candidate-m4 to candidate-41, save a before hash, and apply model 4.1.0 there. The Maven 3 baseline and first Maven 4 compatibility candidate remain untouched.

cd "$ROOT"
rm -rf candidate-41
cp -R candidate-m4 candidate-41
sha256sum candidate-41/pom.xml > evidence/pom-41-before.sha256

"$M4_HOME/bin/mvnup" apply --model-version 4.1.0 --all --directory candidate-41   | tee evidence/mvnup-apply-410.txt
sha256sum candidate-41/pom.xml > evidence/pom-41-after.sha256

diff -u candidate-m4/pom.xml candidate-41/pom.xml   > evidence/model-400-vs-410.diff || true

Prediction 3 should now be true by design: if candidate-41 is truly model 4.1.0, Maven 3 is no longer an allowed build runtime for that source model. Do not “test” that by changing the production wrapper; the compatibility fact is defined by the model/runtime contract.

9. Install the Maven 4-only copy and inspect consumer metadata

Build/install candidate-41 only into a new local repository. Locate the installed POM by its actual GAV, copy it to evidence, and compare semantic content with the source build POM.

cd "$ROOT/candidate-41"
MAVEN_USER_HOME="$ROOT/.lab/home-41" ./mvnw -Dmaven.repo.local="$ROOT/.lab/repo-41" clean install   | tee "$ROOT/evidence/install-41.log"

# For the unchanged example coordinates:
INSTALLED="$ROOT/.lab/repo-41/dev/academy/maven4-migration-lab/1.0.0/maven4-migration-lab-1.0.0.pom"
cp "$INSTALLED" "$ROOT/evidence/consumer-41.pom"
diff -u pom.xml "$ROOT/evidence/consumer-41.pom"   > "$ROOT/evidence/build-vs-consumer.diff" || true

Record: emitted model version, GAV, dependency semantics, whether build-only plugin configuration appears, and any warning. If the project publishes a BOM, add a separate test because rc-6 currently documents a BOM consumer-POM property-reference known issue.

10. Inventory plugins, extensions, lifecycle assumptions, and CI changes

Create evidence/compatibility-inventory.md with one row per executable build dependency or platform assumption:

Item Current version/state Maven 4 evidence Blocker? Owner/next action
Maven Compiler Plugin 3.15.0 Verify succeeds in rc-6 lane No for lab Keep pinned.
Maven JAR Plugin 3.5.1 Verify succeeds; checksum compared No for lab Keep pinned.
Surefire / JUnit 3.5.6 / 6.1.3 One required test runs in both lanes No for lab Preserve report evidence.
Core extensions None in lab N/A No Real project must inventory .mvn/extensions.xml.
Launcher JDK 21 Meets Maven 4 Java 17+ requirement No Pin CI image/toolchain.
Build POM model 4.0.0 baseline; 4.1.0 experiment Dual build works before 4.1.0; experiment Maven 4-only Decision boundary Do not merge 4.1.0 while Maven 3 rollback required.
Publishing Disabled in checkpoint Consumer POM inspected only in isolated repo No production publish Run repository-specific staging test later.

11. Document blockers and current known issues

At minimum, the dossier should explicitly answer:

  • Is Maven 4 GA today? No, rc-6 on this generation date.
  • Does every build agent provide Java 17+? Record actual image evidence.
  • Do any plugins/extensions use unsupported/internal APIs? Record coordinates and test results.
  • Do Maven 3 and Maven 4 required test suites both execute and fail correctly?
  • Are JAR checksums and published/installed dependency semantics acceptable?
  • Does the project publish BOMs affected by the rc-6 known issue?
  • Can the release lane revert to the Maven 3 wrapper without reverting unrelated source work?

12. Write two decisions, not one

Use a short record such as:

Decision date: 2026-08-24

Compatibility lane: GO
Reason: Maven 4.0.0-rc-6 is the latest RC; JDK 21 is available; the controlled
model-4.0.0 build/test lane is valuable for discovering migration blockers.

Production standardization: NO-GO
Reason: Apache still classifies Maven 4 as not yet GA. Keep Maven 3.9.16 as the
production baseline. Re-evaluate when Maven 4 reaches GA and after plugin/
extension, consumer-metadata, CI, and rollback gates are satisfied.

Model 4.1.0 adoption: DEFER
Reason: it intentionally removes Maven 3 build compatibility; no required Maven
4-only feature justifies that rollback cost in this checkpoint.

If your organization explicitly accepts pre-GA tooling, document that exception separately; do not rewrite the upstream release status.

13. Roll back every experimental change

Rollback verification means more than deleting files. Re-run the baseline wrapper after candidate cleanup to prove the original path still works.

cd "$ROOT"
rm -rf candidate-m4 candidate-41 .lab/repo-m4 .lab/repo-41 .lab/tools

cd baseline-m3
MAVEN_USER_HOME="$ROOT/.lab/home-m3-rollback" ./mvnw -Dmaven.repo.local="$ROOT/.lab/repo-m3-rollback" clean verify   | tee "$ROOT/evidence/rollback-m3-verify.log"

Delete the whole checkpoint directory only after copying any dossier evidence you intend to retain. Never use this lab as a reason to remove the normal user ~/.m2 state.

14. Verification checklist

  • Current Maven release status is dated and sourced.
  • Maven 3.9.16 and Maven 4.0.0-rc-6 are independently pinned.
  • Both baseline/candidate use the intended JDK 21.
  • Candidate Maven 4 distribution integrity is verified before execution.
  • Model 4.0.0 source is compared under both runtimes before 4.1.0 edits.
  • Required tests/build scope complete under both lanes.
  • Artifact SHA-256 results are compared and any mismatch explained.
  • Effective model/warning differences are preserved.
  • mvnup check evidence exists for 4.0.0 and 4.1.0 targets.
  • Consumer POM semantics are inspected in an isolated repository.
  • Plugin/extension and CI runtime assumptions are inventoried.
  • Known RC issues relevant to artifact types are documented.
  • Production publishing/signing credentials were never introduced to the RC lane.
  • Rollback to Maven 3 is executed and verified.

Knowledge check

Why does the dossier contain separate “compatibility lane” and “production standardization” decisions?

What is the strongest evidence that Maven 4 did not change this simple artifact?

Why keep candidate-41 separate from candidate-m4?

If a Maven 4 RC known issue affects your published BOM, what should the decision record say?

What proves rollback is real?

When can the model 4.1.0 decision change from defer to adopt?

15. Production operating model and Chapter 15 bridge

Chapter 14 adds an upgrade rule to the production build-engineering model: major build-tool versions move through prepare → parallel test → controlled migration, with artifact/metadata invariants and rollback preserved at every boundary. Version status, launcher JDK, plugins/extensions, POM model, consumer metadata, CI images, and repository publishing are separate migration surfaces.

Chapter 15 now begins the Gradle half of the course. The same discipline carries over—wrapper identity, JDK/runtime boundaries, executable build scripts, generated/cache state, and reproducible evidence—but Gradle has a different project/task/configuration model that must be learned on its own terms.

Official references and version notes

Version-sensitive statements in this lesson were checked against current Apache Maven primary documentation on 2026-08-24.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.