Chapter 04Lesson 01~95 minutes

Apache Maven Installation, Wrapper, Settings, Local Repository, and Project Bootstrap: Concepts, Architecture, and Mental Model

Build a beginner-first mental model of Apache Maven runtime, Maven Wrapper, settings precedence, local repository state, project bootstrap, and the trust boundaries between them.

Maven RuntimeMaven Wrappersettings.xmlLocal RepositoryBootstrap

Learning objectives

  • Separate the Maven runtime from the project-owned Maven Wrapper and explain the bootstrap chicken-and-egg relationship.
  • Identify wrapper scripts/properties, global settings, user settings, project POM, local repository, remote repositories, and generated build output as different state stores.
  • Explain settings precedence and why credentials/proxy/mirror information belongs outside a distributable POM.
  • Treat the local repository as resolver-managed cache/install state rather than as source control or an authoritative artifact repository.
  • Use read-only commands to prove the active Maven/JDK/settings/repository environment before changing it.
Version baseline — verified 2026-08-23. The required path uses JDK 21 and Apache Maven 3.9.16. Maven 3.9.16 is the current recommended GA and requires JDK 8+ to execute; Maven 3.10.0-rc-1 and Maven 4.0.0-rc-6 are previews and are not required. Maven Wrapper 3.3.4 is the current stable wrapper. Wrapper examples use the only-script distribution type and pin the Maven distribution with distributionSha256Sum after the downloaded archive has first been verified against Apache's published release checksum/signature. Re-check these versions before applying the examples to production.

1. The practical problem: “Maven works here” is not an execution contract

Chapter 03 ended with a resolved dependency graph. Before we can trust that graph in CI or on another developer machine, we need to know which Maven built it, which Java runtime launched Maven, which settings redirected repositories or proxies, and which local repository supplied cached state.

A globally installed mvn executable is machine state. A Maven Wrapper is project state that selects a Maven distribution. A settings.xml file is execution-environment state. The local repository is mutable resolver state. Those layers can influence one build simultaneously, but they are not interchangeable.

Trust boundary: wrapper scripts can download and execute a Maven distribution, settings can redirect artifact/plugin downloads, and repository content becomes executable build input. Review those files with the same care you give CI bootstrap code.

2. Maven runtime and Java runtime are two identities

mvn -v does more than print a Maven version: it also reports Maven home and the Java runtime used to execute Maven. That Java runtime can differ from the JDK later selected by a toolchain for compilation. Chapter 02 introduced that distinction; here it becomes an installation diagnostic.

# Bash / Git Bash / macOS / Linux
mvn -v
java -version
printf "JAVA_HOME=%s\n" "${JAVA_HOME:-<unset>}"
# PowerShell
mvn -v
java -version
"JAVA_HOME=$env:JAVA_HOME"

If mvn -v reports an unexpected Java home, changing pom.xml is not the first correction. First fix the launcher environment, package-manager installation, shell startup state, or CI JDK selection that chose the runtime.

3. The Maven Wrapper turns Maven version selection into project state

The Wrapper gives a repository two launchers—mvnw and mvnw.cmd—plus .mvn/wrapper/maven-wrapper.properties. With the current default only-script type, the scripts can download the configured Maven distribution without storing maven-wrapper.jar in the project.

Wrapper execution path and trust boundaries
flowchart TD
  U[Developer or CI] --> S[mvnw / mvnw.cmd]
  S --> P[.mvn/wrapper/maven-wrapper.properties]
  P -->|distributionUrl + SHA-256 pin| D[Maven distribution]
  D --> M[Maven runtime]
  J[JAVA_HOME / java on PATH] --> M
  M --> Q[pom.xml + settings]
  Q --> R[remote repositories]
  Q --> L[local repository]
  M --> O[target/ output]

The wrapper does not magically make every other input reproducible. It stabilizes the Maven distribution. JDK selection, plugin/dependency versions, settings, remote repository policy, and undeclared environment inputs remain separate controls.

4. What should live in version control?

State Typical location Version-control intent Why
Wrapper launchers mvnw, mvnw.cmd Commit They are the project entry point.
Wrapper configuration .mvn/wrapper/maven-wrapper.properties Commit Pins distribution URL/version and checksum policy.
Project model pom.xml Commit Declares project build model.
Project-safe Maven config .mvn/maven.config, .mvn/jvm.config when intentionally used Commit with review Affects every invocation; keep secret-free.
User settings ~/.m2/settings.xml Do not commit personal copy May contain credentials, proxies, local paths.
Local repository ~/.m2/repository by default Do not commit Mutable cache plus locally installed artifacts.
Generated outputs target/ Normally ignore Derived build products, not source of truth.

5. Settings are layered environment policy, not project source

Maven 3 reads global settings from ${maven.home}/conf/settings.xml and user settings from ${user.home}/.m2/settings.xml. When both are present, Maven merges them and user settings take precedence for conflicts. CLI options -gs and -s can select alternate global and user settings files for controlled runs.

Settings can define the local repository location, mirrors, proxies, server credentials, profiles, and plugin groups. A repository id connects a repository or mirror to a <server> credential entry; putting the password in pom.xml would move machine-specific secret state into shared project source.

<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
  <offline>false</offline>
  <servers>
    <server>
      <id>repo-example</id>
      <username>learner-example</username>
      <password>token-FAKE_DO_NOT_USE</password>
    </server>
  </servers>
</settings>
Do not copy that fake credential pattern into production source control. The example only shows how Maven associates a server ID with authentication. Real secrets belong in protected machine/CI configuration and should never be printed by diagnostics.

6. The local repository is mutable resolver state with two roles

By default Maven uses ~/.m2/repository. It caches artifacts downloaded from remote repositories and also stores artifacts produced by local install operations. That mixed role is why “it exists in my local repository” is not proof that an artifact exists in an authoritative remote repository.

Maven's current repository documentation also warns against treating the local repository as a directory whose layout applications should manipulate directly. Resolver tracks origin/context and locking metadata; current resolver implementations can even split cached and locally installed content. For labs, isolate the repository root through Maven configuration rather than deleting normal user state.

# Print the configured local repository path through Maven's model.
mvn help:evaluate -Dexpression=settings.localRepository -q -DforceStdout

# For a disposable run, select a separate repository root.
mvn -Dmaven.repo.local="$PWD/.lab/m2repo" -v

7. Manual bootstrap and archetype bootstrap solve different problems

A manual bootstrap starts from a deliberately small directory and pom.xml. It is excellent for learning because every file has a reason to exist. An archetype is a parameterized project template. Maven's current Quickstart Archetype is version 1.5; it can create a conventional Java project rapidly, but the generated model still requires review.

mvn archetype:generate \
  -DgroupId=com.example \
  -DartifactId=learner-example \
  -DarchetypeArtifactId=maven-archetype-quickstart \
  -DarchetypeVersion=1.5 \
  -DinteractiveMode=false

In a production organization, an internal approved template can encode repository policy and plugin baselines, but that convenience creates a maintenance responsibility: the template itself becomes supply-chain/build logic.

8. Inspect the effective environment before mutating it

For installation/bootstrap questions, four read-only observations answer most first-pass questions: Maven/JDK identity, wrapper properties, effective settings, and effective project model.

mvn -v
cat .mvn/wrapper/maven-wrapper.properties 2>/dev/null || true
mvn org.apache.maven.plugins:maven-help-plugin:3.5.2:effective-settings \
  -Doutput=.lab/effective-settings.xml
mvn org.apache.maven.plugins:maven-help-plugin:3.5.2:effective-pom \
  -Doutput=.lab/effective-pom.xml

help:effective-settings hides passwords by default. Keep it that way. Effective output is useful evidence, but it can still expose internal repository URLs, usernames, proxy hosts, profile properties, and filesystem paths; treat it as potentially sensitive build-environment data.

9. A state map for Chapter 04

Question Inspect first Do not confuse it with
Which Maven executes? ./mvnw -v or mvn -v Compiler target or dependency version
Which Java launches Maven? Java home/version reported by Maven Toolchain-selected compiler JDK
Which repositories/mirrors apply? effective settings + effective POM Files already cached locally
Where is mutable dependency state? local repository path Authoritative remote repository
Which project model is shared? pom.xml + reviewed project config User settings or IDE metadata
Which output was generated? target/ and build log Input source tree

10. Why this matters in DevOps

CI should be able to answer “which Maven and JDK ran, which settings policy applied, where dependencies came from, and what mutable state was reused?” before anyone trusts a produced JAR. A committed wrapper narrows Maven-version drift; isolated/controlled settings and repositories narrow machine drift; captured evidence makes failures diagnosable instead of anecdotal.

11. Mini-lab — inventory your Maven execution layers

Without deleting or changing anything, record the output of mvn -v, whether wrapper files exist, the path of the active local repository, and whether user/global settings exist. Do not print settings contents if they might contain employer/private configuration. Classify every observation as project state, Maven installation state, Java runtime state, user settings state, or mutable repository/cache state.

Verification: you should be able to explain which of those facts would travel with a Git clone and which would not. Cleanup: delete only the note file you created for the exercise.

Knowledge check

A repository has mvnw but a developer runs mvn package. Which Maven version is guaranteed by the wrapper?

If user and global settings.xml define conflicting values, which layer normally dominates?

A JAR exists under ~/.m2/repository. Does that prove the same artifact is published to the organization repository?

Why is distributionSha256Sum useful in wrapper configuration?

Why should effective-settings output be handled cautiously even when passwords are hidden?

Summary

Maven bootstrap has distinct layers: Java launches Maven; the wrapper can select a project-pinned Maven distribution; settings merge machine/user policy; the project model declares build intent; remote repositories provide artifacts; the local repository caches/downloads and stores locally installed artifacts; and target/ contains derived output. Reproducibility improves when those layers are explicit and independently inspectable.

Next lesson

Bootstrap a wrapper-first disposable project

Lesson 2 creates a tiny project, installs the Maven Wrapper, verifies its distribution integrity, isolates wrapper and repository state, captures effective settings safely, and performs the first wrapper-only build.

Official references and version notes

Version-sensitive commands and properties were checked against current Apache Maven documentation on 2026-08-23. Re-check Maven/Wrapper/plugin versions before production use.

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.