skip to content

Maven Wrapper

mvnw and the wrapper properties that pin one exact Maven version for every developer and CI agent. Interviewers ask why the wrapper is committed to the repository at all.

on this pageshow

explore

questions

5

What is the Maven Wrapper, and why would a project commit mvnw/mvnw.cmd into its repository?

level: juniorimportance: must knowfreq 70%

answer

  1. mvnw + mvnw.cmd
  2. self-provisions fixed Maven version
  3. distributionUrl in properties
  4. only JDK needed
  5. reproducible across dev + CI

basics

~20 s

The Maven Wrapper is a small script (mvnw on Unix, mvnw.cmd on Windows) checked into the repo. Running ./mvnw downloads and uses a fixed Maven version automatically, so everyone builds with the same Maven without installing it.

solid answer

~40 s

The Maven Wrapper lets a project pin and self-provision a specific Maven version. You commit four things: the `mvnw` shell script, the `mvnw.cmd` batch script, and `.mvn/wrapper/maven-wrapper.properties` (plus historically a tiny jar). When a developer runs `./mvnw clean install`, the wrapper reads the `distributionUrl` from the properties file, downloads that exact Maven distribution into `~/.m2/wrapper` if not already cached, and delegates the build to it. Benefits: every developer and the CI server use the identical Maven version, so builds are reproducible; nobody needs Maven pre-installed (only a JDK); upgrades are a one-line change reviewed in a PR. It's the Maven equivalent of the Gradle Wrapper.

code

bash · 5 lines
bash
# Generate the wrapper, pinning a specific Maven version
mvn wrapper:wrapper -Dmaven=3.9.6

# Now build with the project-pinned Maven (no global mvn needed)
./mvnw clean verify

go deeper

for a junior

Knows ./mvnw runs Maven without a global install and that it's committed to the repo.

for a middle

Knows the four files involved and that distributionUrl drives which version is downloaded.

for a senior

Frames it as a reproducibility/onboarding tool, knows the per-user cache and CI implications.

for a principal

Sets org policy: every repo ships a wrapper, version bumps go through PR review, CI invokes ./mvnw not mvn.

## What the Maven Wrapper is Maven is normally installed once on a machine (the `mvn` command). That means different people may run different Maven versions, and a CI agent may differ from a laptop, leading to subtle build differences. The **Maven Wrapper** solves this by shipping a tiny launcher *inside the project repository* that knows exactly which Maven version to use and fetches it on demand. ## The files it adds - **`mvnw`** — a POSIX shell script (Unix/macOS/Linux). You run `./mvnw <goals>` instead of `mvn <goals>`. - **`mvnw.cmd`** — the Windows batch equivalent. - **`.mvn/wrapper/maven-wrapper.properties`** — configuration: the `distributionUrl` (which Maven version/zip to download) and, in older versions, a `wrapperUrl`. - **`.mvn/wrapper/maven-wrapper.jar`** — a small bootstrap jar that performs the download (present in the classic/jar wrapper; the newer `script`-type wrapper avoids committing a binary). ## How it works at runtime 1. You run `./mvnw verify`. 2. The script reads `distributionUrl` from `maven-wrapper.properties`. 3. It checks a local cache (typically `~/.m2/wrapper/dists`). If that Maven version isn't there, it downloads and unpacks it. 4. It then invokes that Maven version with your goals. Because the version is read from a committed file, **everyone gets the same Maven**. ## Why commit it - **Reproducible builds** — laptop and CI use one Maven version. - **Zero install** — contributors need only a JDK; no manual Maven setup. - **Reviewable upgrades** — bumping Maven is a one-line diff in the properties file. ```bash # Instead of relying on a globally installed mvn: ./mvnw clean verify # Unix/macOS mvnw.cmd clean verify # Windows ``` You generate it with the plugin goal `mvn wrapper:wrapper`, which scaffolds all of the above.

  • Do developers still need Maven installed if the repo has the wrapper?
    No. They only need a compatible JDK. The wrapper downloads the pinned Maven version itself on first run.
  • Which files must be committed to git for the wrapper to work?
    mvnw, mvnw.cmd, and .mvn/wrapper/maven-wrapper.properties (and maven-wrapper.jar for the jar-based wrapper). They must NOT be gitignored.

Like shipping a printer driver with the document instead of assuming the right printer is already installed.

saying these in an interview costs you the question

  • Saying the wrapper installs Maven globally on the machine (it caches per-user under ~/.m2/wrapper).
  • Claiming you still need to install Maven separately to use the wrapper.
  • Gitignoring mvnw or the .mvn directory, which breaks the point of committing it.

context

open as a page

Walk me through the contents of .mvn/wrapper/maven-wrapper.properties — what do distributionUrl and wrapperUrl control?

level: middleimportance: must knowfreq 55%

basics

~10 s

distributionUrl is the URL of the exact Maven version zip the wrapper downloads and runs. wrapperUrl is where the wrapper's own bootstrap jar is fetched from. Changing distributionUrl pins a different Maven version.

open as a page

How do you create or upgrade the Maven Wrapper in a project, and what does the wrapper:wrapper goal do?

level: middleimportance: should knowfreq 45%

basics

~10 s

Run mvn wrapper:wrapper. It generates mvnw, mvnw.cmd, and .mvn/wrapper files. Add -Dmaven=<version> to pin a specific Maven version. Re-running it with a new version upgrades the wrapper.

open as a page

How does using the Maven Wrapper improve reproducibility in CI, and how would you set up CI to use it well?

level: seniorimportance: should knowfreq 40%

basics

~20 s

CI calls ./mvnw instead of mvn, so it builds with the exact Maven version pinned in the repo — matching developer machines. Cache ~/.m2 (deps) and ~/.m2/wrapper (the Maven distro) so it isn't re-downloaded each run.

open as a page

What are the security and governance considerations of shipping the Maven Wrapper, especially the committed jar and the distributionUrl?

level: principalimportance: should knowfreq 25%

basics

~20 s

The wrapper executes code from a committed jar/script and downloads Maven from distributionUrl, so both are a supply-chain surface. Mitigate with sha256 checksums, an internal mirror URL, the only-script type to avoid a committed binary, and reviewed upgrades.

open as a page