You inherit an existing Spring Boot Maven project that is not reproducible. Walk through the minimal steps to make and verify it reproducible.
answer
- add outputTimestamp property
- Boot parent already supports it
- current plugin versions
- check-buildplan static
- build twice -> compare sha256
basics
~10 sAdd project.build.outputTimestamp to the POM (often derived from the commit), make sure packaging plugin versions are current, then run mvn artifact:check-buildplan and rebuild twice to confirm the JAR hashes match.
solid answer
~40 sMinimal path: (1) Add `<project.build.outputTimestamp>` under `<properties>` — a fixed ISO-8601 value, or wire it to the commit timestamp; the Spring Boot parent already supports this property. (2) Ensure packaging plugins (jar/boot repackage, assembly, shade if used) are on reproducible-friendly versions — the Spring Boot parent generally pins good ones. (3) Remove obvious nondeterminism: don't filter `${maven.build.timestamp}` into resources, avoid SNAPSHOT deps in releases. (4) Verify statically with `mvn artifact:check-buildplan`. (5) Verify dynamically: build twice into separate dirs and compare the artifact SHA-256, or run `artifact:compare`. For Spring Boot specifically, the fat-jar repackage also honors the timestamp, so the executable JAR becomes stable too. Add the check to CI so it can't regress.
code
bash · 3 linesmvn clean package -DskipTests && sha256sum target/*.jar > r1
mvn clean package -DskipTests && sha256sum target/*.jar > r2
diff r1 r2 && echo REPRODUCIBLEgo deeper
Knows to add the outputTimestamp property and that there is a way to verify.
Can run check-buildplan and a two-build hash comparison and knows Boot supports the property.
Sequences the change, handles plugin versions and resource-filtering pitfalls, and gates it in CI.
Rolls the pattern into the org parent/BOM and standardizes verification across all services.
## Goal Take a project whose `mvn package` produces a different JAR each run and make it byte-stable, with minimal changes. ## Step 1 — set the timestamp property Add to the POM: ```xml <properties> <project.build.outputTimestamp>2024-01-01T00:00:00Z</project.build.outputTimestamp> </properties> ``` The Spring Boot starter parent recognizes this property and propagates it to the packaging and `spring-boot-maven-plugin` repackage step, so the **executable fat JAR** is normalized too. Many teams set it from git instead of a literal: ```bash mvn -Dproject.build.outputTimestamp=$(git log -1 --format=%cI) clean package ``` ## Step 2 — confirm plugin versions Reproducibility fixes landed over time in maven-jar-plugin, maven-assembly-plugin, maven-shade-plugin, and spring-boot-maven-plugin. The Spring Boot parent usually pins recent, reproducible-friendly versions; if you override versions, keep them current. `check-buildplan` will warn about known-bad versions. ## Step 3 — remove easy nondeterminism - Stop filtering `${maven.build.timestamp}` into resources (it is the volatile current time). - Avoid `-SNAPSHOT` dependencies in release builds. ## Step 4 — static verification ```bash mvn artifact:check-buildplan ``` Fix anything it flags (most commonly: the property wasn't set). ## Step 5 — dynamic verification Build twice and compare hashes: ```bash mvn clean package -DskipTests sha256sum target/*.jar > /tmp/run1.txt mvn clean package -DskipTests sha256sum target/*.jar > /tmp/run2.txt diff /tmp/run1.txt /tmp/run2.txt && echo REPRODUCIBLE ``` Or use `mvn clean verify artifact:compare` against a reference. ## Step 6 — lock it in CI Run `check-buildplan` (and ideally a two-build hash compare) in the pipeline so a future change can't silently break reproducibility.
- Does the Spring Boot fat JAR honor project.build.outputTimestamp?Yes. The spring-boot-maven-plugin repackage step reads the property and normalizes timestamps/ordering in the executable JAR, so the fat jar is reproducible too.
- How would you prove it's reproducible without a reference artifact?Build twice into clean targets and compare the artifact SHA-256 hashes; identical hashes prove byte-identity. artifact:compare is the plugin-driven equivalent.
saying these in an interview costs you the question
- Manually rewriting timestamps in the JAR with a script instead of using the property.
- Assuming adding the property without verifying actually made it reproducible.
- Forgetting the executable/fat JAR (only normalizing the plain jar).