Production Capstone: Build, Test, Secure, Publish, and Optimize a Multi-Module JVM Platform: Requirements, Constraints, and Target Architecture
Translate a production-style JVM platform brief into measurable build requirements before writing build logic. Choose a Gradle-first architecture with an explicit Maven consumer boundary, define trust and evidence flows, and establish invariants that can be independently verified.
Learning objectives
- Translate business/release/security requirements into build-engineering invariants before choosing commands.
- Separate Gradle runtime, Java toolchain, dependency graph, repository state, caches, publications, and CI evidence.
- Choose a Gradle-first multi-project design with one Maven interoperability boundary instead of duplicate full builds.
- Define measurable clean-room, test, reproducibility, origin, secret, promotion, and cache-trust acceptance criteria.
- Read two compound diagrams that cover architecture/build graph and trust/artifact/evidence flows.
Capstone rule: evidence before confidence. A
successful build is only one signal. This chapter
treats tool identity, dependency origin, test coverage, artifact
bytes, publication metadata, cache provenance, and promotion history
as separate evidence that must agree.
1. Production brief: Orbit JVM Platform
Orbit is a fictional internal JVM platform with a shared text-normalization library and a small command-line application. Two product teams change application behavior independently, while a platform team owns dependency/version policy and build controls. Releases must run on Java 17, build on controlled JDK 21 agents, and be consumable by one legacy Maven service.
The business requirement is not “use Gradle.” It is: produce a tested, traceable, reproducible artifact that can be promoted without rebuilding, while keeping dependency and credential trust boundaries explicit. Gradle is chosen as the primary implementation because the course has already established its multi-project, platform, test-suite, verification, cache, and publishing models. Maven remains a consumer/interoperability contract—not a second source build.
2. Translate the brief into explicit build requirements
| Concern | Requirement | Independent evidence |
|---|---|---|
| Compatibility |
Gradle runs on JDK 21; Java sources compile with
--release 17.
|
./gradlew -version, toolchain report,
javap -verbose major version 61.
|
| Build identity | Gradle Wrapper 9.7.1 distribution and wrapper JAR are verified. |
Pinned distributionSha256Sum; wrapper JAR
SHA-256 comparison.
|
| Module ownership |
platform → core → app policy/dependency
direction is explicit.
|
projects, dependency reports, project paths.
|
| Dependency policy | Commons Lang 3.20.0 and JUnit 6.1.3 are governed by the platform; project aliases stay versionless. |
Platform constraints, lockfiles,
dependencyInsight.
|
| Tests |
Unit and integration evidence is required; integration suite
participates in check.
|
Task graph, XML/HTML reports, test counts, failing-test propagation. |
| Supply chain | Only declared repositories may resolve dependencies; external artifacts are checksum-verified. |
Settings repository policy plus reviewed
gradle/verification-metadata.xml.
|
| Artifact identity | JARs are reproducible across clean source copies and isolated Gradle User Homes. | SHA-256 comparison from two clean directories. |
| Publication | Platform and core publish to disposable staging; clean Maven consumer resolves the promoted core. | Repository tree, POM/module metadata, Maven clean-repo compile. |
| Promotion | Release bytes are copied from staging after acceptance; no rebuild is allowed in promotion. | Before/after artifact SHA-256 equality. |
| Secrets/caches | No committed credentials; cache readers/writers are bounded by trust level. | Repository scan, provider-neutral CI contract, cache policy. |
3. Name the state stores before changing any of them
Orbit has several independent state stores. Treating them as “the build cache” would hide important failure modes:
| State store | Examples | What it means |
|---|---|---|
| Source/governance |
settings.gradle.kts, build scripts, catalog,
lockfiles, verification metadata
|
Declared model and policy under review. |
| Wrapper/toolchain |
gradlew, wrapper JAR/properties, installed JDKs
|
Executable build-tool/compiler identity. |
| Resolved dependencies | Gradle dependency metadata/artifact cache | Downloaded external inputs; reusable only within explicit trust policy. |
| Workspace outputs | build/ directories |
Current checkout outputs; not authoritative promotion input unless captured as artifacts. |
| Build/configuration caches | Gradle build cache, configuration cache | Derived reusable state; correctness depends on complete input modeling. |
| Staging/release repository | Disposable Maven-layout file repositories | Published contract consumed by other builds. |
| CI evidence | Test reports, source manifest, tool versions, checksums, logs | Audit trail connecting source → build → artifact → promotion. |
4. Architecture + dependency + build graph
flowchart TD W[Verified Gradle Wrapper 9.7.1] -->|launches pinned build tool| G[Gradle runtime on JDK 21] G -->|configures settings/build model| R[Root build] R -->|project :platform provides constraints| P[:platform java-platform] R -->|project :core uses platform + source| C[:core java-library] R -->|project :app uses core + platform| A[:app application] P -->|version policy edge| C P -->|version policy edge| A C -->|project dependency/API edge| A C -->|unit verification| CT[core:test] A -->|unit verification| AT[app:test] A -->|integration verification| IT[app:integrationTest] CT -->|required by check| Q[check gate] AT -->|required by check| Q IT -->|explicitly attached| Q Q -->|accepted component| PUB[staging publication]
The wrapper-to-Gradle arrow transfers executable tool identity.
Gradle-to-root transfers the configured model. Platform-to-core/app
arrows transfer version constraints, not JAR code.
Core-to-app transfers compiled API/runtime classes. Test arrows
transfer pass/fail evidence into the check gate. Only
an accepted gate may feed the staging publication.
5. Trust boundary + artifact + evidence flow
flowchart TD SRC[Reviewed source + governance] -->|hash source manifest| BUILD[Ephemeral build workspace] UP[(Maven Central)] -->|verified dependency bytes| BUILD BUILD -->|test XML/HTML + tool identity| EVID[Evidence bundle] BUILD -->|core-1.0.0.jar + POM + module metadata| STAGE[(Disposable staging repo)] STAGE -->|SHA-256 verified, copy exact bytes| REL[(Disposable release repo)] REL -->|Maven repository contract| MC[Maven 3.9.16 clean consumer] EVID -->|binds source + tests + checksums| APPROVE[Promotion decision] APPROVE -->|authorizes copy, never rebuild| REL CACHE[(Dependency/build caches)] -->|read only if trust policy allows| BUILD BUILD -->|write only from approved lane| CACHE
The upstream repository is outside the project trust boundary, so its artifacts require repository policy and verification metadata. The build workspace is disposable. Staging is not release authority. The promotion decision consumes evidence, and the release repository receives bytes copied from staging. The Maven consumer proves an external metadata contract. Cache arrows are conditional: a cache hit is accepted only when the cache writer/read policy matches the build’s trust level.
6. Write invariants before implementation
| Invariant ID | Acceptance criterion | Failure blocks |
|---|---|---|
| I-01 Tool identity | Gradle 9.7.1 distribution checksum and wrapper JAR checksum match official values; JDK 21 recorded. | Any build execution. |
| I-02 Target runtime | All application/library class files target Java 17 (major 61). | Publication/promotion. |
| I-03 Graph policy | No unmanaged external version; lock/constraint evidence explains selected versions. | Merge/release. |
| I-04 Required tests | Unit + integration suites execute and report; zero/missing integration execution is failure. | Publication. |
| I-05 Clean build | Fresh source copy + isolated Gradle User Home succeeds from declared state. | Release. |
| I-06 Reproducibility | Two clean copies produce identical core JAR SHA-256. | Immutable promotion claim. |
| I-07 Origin/integrity | Dependency repositories are centralized and verification metadata is reviewed. | Trusted build claim. |
| I-08 Secret hygiene | No real repository credentials/signing keys are committed or printed. | CI/release. |
| I-09 Immutable promotion | Release JAR checksum equals staged JAR checksum; promotion does not run compilation/tests. | Release. |
| I-10 Bounded caches | Untrusted branches cannot write shared authoritative caches; build outputs are not restored as dependency caches. | CI trust boundary. |
| I-11 Maven boundary | Maven 3.9.16 clean consumer resolves/compiles against promoted core without Gradle-only assumptions. | Interoperability acceptance. |
7. Pin the current baseline explicitly
| Layer | Pinned capstone baseline | Why |
|---|---|---|
| Gradle | 9.7.1 | Current recommended 9.7 patch release at generation time. |
| Gradle distribution SHA-256 | acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a |
Wrapper verifies downloaded -bin distribution
before use.
|
| Gradle Wrapper JAR SHA-256 | 7a9ce74cff467ca1bf60a4fcd9f05185acceda4d0f382434d393e17864262c5d | Bootstrap JAR is executable supply-chain input. |
| Build/compiler JDK | 21 | Controlled build/toolchain runtime for the capstone. |
| Java release target | 17 | Supported runtime contract and JUnit 6 floor. |
| JUnit | 6.1.3 | Current documented course test baseline; requires Java 17+. |
| Commons Lang | 3.20.0 | Concrete governed external dependency. |
| Maven boundary | Maven 3.9.16 via Wrapper 3.3.4 | Current GA Maven line; Maven 4 RC remains preview. |
8. Read-only preflight before creating the capstone
Start from identity and filesystem evidence. Do not generate wrappers or mutate caches yet:
java -version
javac -version
test -f gradlew && ./gradlew -version || true
test -f gradle/wrapper/gradle-wrapper.properties && cat gradle/wrapper/gradle-wrapper.properties || true
git status --short 2>/dev/null || true
pwd
python --version
If the project Wrapper is not present, bootstrap it only from a trusted Gradle 9.7.1 installation or from a previously reviewed course skeleton. A wrapper script downloaded ad hoc from an arbitrary source defeats invariant I-01 before the build begins.
9. Mandatory local/free path and optional enterprise boundaries
The mandatory capstone requires only a JDK, the checked-in wrapper, Git/Python/shell utilities, Maven Central for initial external dependencies, and project-local directories. Staging and release repositories are ordinary directories using Maven repository layout. The Maven consumer uses an isolated local repository.
Hosted CI, Nexus/Artifactory, Develocity, remote HTTP build caches, HSM-backed signing, and cloud secret managers are valid production integrations but are not required here. Their role is represented as an interface contract: trusted inputs, writers/readers, authentication, retention, immutable promotion, and evidence export.
10. Why Gradle primary + Maven boundary is the chosen architecture
| Alternative | Benefit | Cost/risk | Capstone decision |
|---|---|---|---|
| Two complete Maven + Gradle builds | Maximum syntax practice | Duplicate source-build logic, two policy surfaces, divergence risk | Reject. |
| Maven primary only | Predictable lifecycle, broad interoperability | Would underuse later Gradle governance/cache/variant material | Not chosen. |
| Gradle primary + Maven clean consumer | One source build plus real cross-tool contract | Requires careful POM/platform metadata mapping | Choose. |
| Gradle primary + no Maven check | Simpler | Does not prove mixed-estate boundary from Chapter 30 | Reject. |
11. Implementation order is itself a control
Lesson 2 follows this dependency order: wrapper/toolchain → settings/repositories → module graph → version policy → tests → lock/verification metadata → packaging → staging publication → clean Maven consumption → evidence bundle → immutable promotion → performance baseline. Later steps depend on evidence produced by earlier steps. Do not start by copying a giant final build script: incremental construction makes causal failures visible.
Knowledge check
Why is the Maven build not duplicated in the capstone?
The capstone needs cross-tool understanding, not two competing source-build authorities. Gradle owns the source build; Maven independently proves the published contract.
What does the :platform project contribute to
:core?
Dependency constraints/version policy, not application classes.
Why does a matching dependency lockfile not prove a trustworthy build?
Locking captures selected versions; it does not prove repository origin, artifact integrity, wrapper integrity, secret hygiene, or test coverage.
Which invariant forbids rebuilding during promotion?
I-09: the release artifact must be the exact staged bytes, proven by checksum equality.
Why is cache trust an architectural concern?
Caches contain distributed derived state. A writer at a lower trust level can poison results consumed by a higher-trust build if policy does not separate writers/readers.
What does Java class major version 61 prove?
That the class file targets Java 17 bytecode; it does not by itself prove dependency/test/security correctness.
Official references and version notes
- Gradle 9.7.1 release notes — pinned Gradle baseline for the capstone.
- Gradle Wrapper and release checksums — wrapper/distribution identity and integrity.
- Gradle JVM toolchains — build JVM versus compiler/test launchers.
- Dependency verification — checksum/signature verification metadata and review workflow.
- Repository declarations and content filtering — dependency origin controls.
- Java testing and JVM Test Suite — unit/integration verification model.
- Maven Publish — Gradle publication to Maven repository layout and clean Maven consumption.
- Build Cache and Configuration Cache — bounded build-state reuse.
- Gradle performance guidance — measurement-first optimization and profiling.
- Apache Maven release history — Maven 3.9.16 GA consumer baseline; Maven 4.0.0-rc-6 remains pre-GA.
- Apache Maven Wrapper 3.3.4 — stable Maven Wrapper baseline.
- Maven Compiler Plugin 3.15.0 — clean Maven consumer compilation baseline.
- JUnit 6.1.3 — Java 17+ test runtime baseline.
- Apache Commons Lang release notes — Commons Lang 3.20.0 dependency baseline.
Version-sensitive statements were rechecked against primary documentation on 2026-08-24. Mandatory work remains local/free. Hosted CI, commercial build analytics, production repository managers, remote caches, and real signing/credential systems are optional integration boundaries only.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.