Maven build cache extension in a multi-module project: a real run
With many modules, the Apache Maven Build Cache Extension keeps one stored result per module. We ran a three-module project against a self-hosted cache (FosterStack Cache 0.2.1, Maven 3.10.0, extension 1.2.3) and recorded which modules were restored and which were built.
The short answer
- Every module is stored and restored on its own.
- Change one module and the modules it depends on are still restored.
- Change one module and the modules that depend on it are built again.
- You set the cache up once, in the parent project. Modules need no changes.
What we ran
Three modules: core has no dependencies, util uses core, and app uses util. Each has six small Java classes. Every build used a fresh copy of the project and an empty local build cache, so the only shared thing was the cache server. All six builds ended with BUILD SUCCESS.
| Build | core | util | app |
|---|---|---|---|
| 1. First build, as CI would do it | built | built | built |
| 2. Another machine, same code | restored | restored | restored |
3. Edit inside a method in core | built | built | built |
| 4. A teammate makes the same edit | restored | restored | restored |
5. Edit only app | restored | restored | built |
6. Edit only util | restored | built | built |
"Restored" is the log line Found cached build, restoring demo:core from cache for that module. "Built" means Maven compiled it, then saved the result.
What this means for your project
- Work flows downstream, not upstream (builds 5 and 6). An edit rebuilt that module and the modules that use it, and nothing before it.
- A small edit in a base module rebuilds everything above it (build 3). Even a change inside a method rebuilt all three modules in this run. Put code that changes often in modules near the top of the dependency chain.
- The first person pays (builds 3 and 4). The teammate with the same edit built nothing.
- This differs from Gradle in our other run. There, a change inside a method in the base module left the modules above it restored; see Gradle build cache for a monorepo. Plan around the tool you use.
Set it up once, in the parent
Two files in the .mvn folder at the root of the project, the same as for a single module:
<!-- .mvn/extensions.xml -->
<extensions>
<extension>
<groupId>org.apache.maven.extensions</groupId>
<artifactId>maven-build-cache-extension</artifactId>
<version>1.2.3</version>
</extension>
</extensions>
<!-- .mvn/maven-build-cache-config.xml -->
<cache xmlns="http://maven.apache.org/BUILD-CACHE-CONFIG/1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/BUILD-CACHE-CONFIG/1.2.0 https://maven.apache.org/xsd/build-cache-config-1.2.0.xsd">
<configuration>
<enabled>true</enabled>
<remote enabled="true" saveToRemote="true" id="fosterstack-cache">
<url>http://127.0.0.1:18180/</url>
</remote>
</configuration>
</cache>
Replace the address with your server's. We used 127.0.0.1 over plain HTTP because the test ran on one machine; use HTTPS across a network. For logins, see Maven remote build cache setup.
If modules are not restored
See Maven build cache not restoring. To turn the cache off or skip it for one build, see enable or disable the extension.
First run: Maven 3.10.0 with maven-build-cache-extension 1.2.3 and FosterStack Cache 0.2.1, macOS (arm64).
Second run: Linux, 0.2.2
The run above was on a Mac with 0.2.1. We ran the table again on a GitHub-hosted Linux machine with FosterStack Cache 0.2.2, Maven 3.10.0, extension 1.2.3 and Java 21, each build on a fresh copy of the project with an empty local build cache. All six rows matched the table, and every build ended with BUILD SUCCESS.