How does project.build.outputTimestamp make a Maven archive reproducible, and what values can it take?
answer
- one property -> all packaging plugins
- Maven Archiver consumes it
- ISO-8601 or epoch seconds
- value 1 = derive from SCM commit
- stamps entries + sorts order
basics
~10 sSetting project.build.outputTimestamp gives Maven Archiver a fixed timestamp to stamp on every archive entry instead of the current time, and it sorts entries. It accepts an ISO-8601 instant or Unix epoch seconds.
solid answer
~40 s`project.build.outputTimestamp` is the standard Maven property that drives reproducibility. When set, Maven Archiver (used by maven-jar-plugin, maven-war-plugin, maven-assembly-plugin, maven-source-plugin, etc.) uses it as the last-modified time for *every* entry in the produced archive instead of the current wall-clock time, and it writes entries in a stable, sorted order. That removes the two big non-determinism sources. The value is either an ISO-8601 instant like `2024-01-01T00:00:00Z` or an integer Unix epoch (seconds). Maven also normalizes related manifest fields. Teams commonly set it from the SCM commit timestamp so each release is deterministic yet meaningful; modern Apache/Spring parent POMs accept a special value (e.g. `1`) that resolves the commit date automatically in CI. One property propagates through all archiving plugins, so you rarely configure plugins individually.
code
bash · 1 linemvn -Dproject.build.outputTimestamp=$(git log -1 --format=%ct) clean packagego deeper
Knows there is a property that fixes archive timestamps.
Knows the accepted value formats and that it normalizes timestamps and ordering.
Knows it is consumed by shared Maven Archiver so one setting covers all packaging plugins, and can derive it from SCM.
Standardizes the property in the org BOM/parent and combines it with verification gates, knowing its scope and limits.
## The single lever Maven exposes one well-known property: **`project.build.outputTimestamp`**. It lives under `<properties>` in your POM (or a parent/BOM). Setting it switches Maven from 'stamp the current time on each entry' to 'stamp this fixed time on every entry, and order entries deterministically.' ## What reads it The property is consumed by **Maven Archiver**, the shared component behind the packaging plugins: - `maven-jar-plugin` - `maven-war-plugin` - `maven-ejb-plugin` - `maven-source-plugin` - `maven-assembly-plugin` - `maven-shade-plugin` (honors it too) Because they all share Maven Archiver, **one property** makes all of them reproducible — you don't normally configure each plugin. ## Accepted values - **ISO-8601 instant:** `2024-01-01T00:00:00Z` (the most common, human-readable form). - **Unix epoch seconds:** an integer like `1704067200`. - **Special derive-from-SCM value:** recent parent POMs (Apache parent, Spring Boot starter parent) support setting it to `1`, which tells the `git-commit-id` / SCM tooling to substitute the commit timestamp. This makes each release deterministic but tied to its real commit. ## What it normalizes - Per-entry **last-modified timestamps** -> all set to the fixed value. - **Entry ordering** -> sorted, stable across OS/filesystem. - File **permissions/UID/GID** in the archive are normalized. ## Example ```xml <project> <properties> <project.build.outputTimestamp>2024-01-01T00:00:00Z</project.build.outputTimestamp> </properties> </project> ``` Deriving it from git in CI: ```bash # epoch seconds of the last commit mvn -Dproject.build.outputTimestamp=$(git log -1 --format=%ct) clean package ``` ## Caveat: not everything is covered `outputTimestamp` fixes the *archiving* layer. Other plugins that generate content (some code generators, `Build-Jdk-Spec` differences, `Implementation-Build` git hashes if you inject them) can still introduce variance. Verify with `artifact:check-buildplan`.
- Why is it enough to set this once rather than per plugin?All packaging plugins delegate to the shared Maven Archiver component, which reads the property, so a single property propagates to jar/war/assembly/source/shade outputs.
- What does the value '1' do in modern parent POMs?It signals the parent's SCM/git-commit-id wiring to resolve the property to the actual commit timestamp, so each release is deterministic and tied to its commit.
saying these in an interview costs you the question
- Thinking you must configure each plugin's timestamp separately.
- Believing outputTimestamp alone guarantees full reproducibility regardless of other generators.
- Confusing it with maven.build.timestamp (which is the volatile current time used in filtering).