Maven build cache extension: remote server setup
Share Maven build results across machines using Apache's Build Cache Extension and a self-hosted cache server. About ten minutes.
Who owns what
The client is Apache's Maven Build Cache Extension. We maintain the server. If your hit rate looks low, that is usually the extension's own project settings (which files count as inputs, what to skip), not the server. Start with the extension's configuration guide.
1. Add the extension
In .mvn/extensions.xml (create it if it is missing):
<extensions>
<extension>
<groupId>org.apache.maven.extensions</groupId>
<artifactId>maven-build-cache-extension</artifactId>
<version>1.2.3</version>
</extension>
</extensions>
Check Maven Central for the current version. Pin one rather than a range. The versions we test against are the ones in our Maven doc; a version outside that list is not something we claim to have tested.
2. Point it at the server, and switch uploads on
Create .mvn/maven-build-cache-config.xml. Two details matter, and both are easy to miss:
- The
remoteelement goes insideconfiguration. Beside it, the extension fails to start with "Unrecognised tag: 'remote'". - Add
saveToRemote="true"on the machines that should upload. Without it the extension reads from the server but never writes to it, and the server stays empty.
<?xml version="1.0" encoding="UTF-8"?>
<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>
<!-- FosterStack Cache — remote Maven build cache.
https://github.com/fosterstack/cache -->
<remote enabled="true" saveToRemote="true" id="fosterstack-cache">
<url>https://cache.example.com/</url>
</remote>
</configuration>
</cache>
Keep the comment: a cache setting that points at an unfamiliar host looks like data theft to a reviewer without it. Keep the trailing slash on the URL. Use HTTPS for a real server.
3. Add the password, if the server has one
In ~/.m2/settings.xml, or your CI system's equivalent. The id must match the id in step 2:
<settings>
<servers>
<server>
<id>fosterstack-cache</id>
<username>maven</username>
<password>your-password-or-CI-secret</password>
</server>
</servers>
</settings>
If the server has no password set, skip this step. For laptops, the server's optional read-only login lets them read the cache without being able to write to it.
4. Build, then build again
This is a real run: Maven 3.10.0, extension 1.2.3, and a 0.2.1 server, on a one-file project. First build:
mvn package
[INFO] Attempting to restore project demo:demo from build cache
[ERROR] Error downloading cache item: https://cache.example.com//v1.1/demo/demo/ebb9bceba2f7a6bc/buildinfo.xml
[INFO] Remote cache is incomplete or missing, trying local build for demo:demo
[INFO] Saved to remote cache https://cache.example.com//v1.1/demo/demo/ebb9bceba2f7a6bc/demo.jar
[INFO] Saved to remote cache https://cache.example.com//v1.1/demo/demo/ebb9bceba2f7a6bc/buildinfo.xml
[INFO] BUILD SUCCESS
[INFO] Saved to remote cache https://cache.example.com//v1.1/demo/demo/9d9dcaf9-3b6b-40fb-9cb5-da97c975eab5/build-cache-report.xml
The line starting [ERROR] Error downloading cache item is the normal first-time miss, the server saying it does not have that entry yet. The build then ran for real and saved its result to the server. The server's status page showed it:
$ curl -s -u maven:demo-pass localhost:8080/statusz | grep -E '"store_entries"|"cache_hits"|"cache_misses"'
"store_entries": 3,
"cache_hits": 0,
"cache_misses": 3,
Now delete target and the extension's local cache folder, so the only copy left is on the server, and build again:
rm -rf target build-cache # 'build-cache' is the extension's local folder, next to your local repository
mvn package
[INFO] Attempting to restore project demo:demo from build cache
[INFO] Found cached build, restoring demo:demo from cache by checksum ebb9bceba2f7a6bc
[INFO] BUILD SUCCESS
"Found cached build, restoring from cache" is the hit. Maven restored the result from the server instead of building it again.
Maven 3.10 also prints a warning that the credentials for fosterstack-cache are being used for an address with no matching repository entry. In our run the build worked regardless.
If you see no hit, check that the id in the password file matches, that saveToRemote is on for the machine that built first, and that the second run starts from a clean checkout.
Mixed Gradle and Maven shop? Both can use the same server. See Gradle and Maven setup. For CI runners, see Jenkins and CI build cache.