How do you publish a java-platform that enforces alignment so consumers resolve a family to one consistent version?
answer
- java-platform plugin
- constraints { api(...) }
- consumer: platform("...")
- enforcedPlatform = strict override
- allowDependencies() to import BOMs
basics
~10 sApply the java-platform plugin, list the family modules under constraints in dependencies, and publish it. Consumers add platform("you:platform:v"). Because all constraints share the platform version, the family aligns when consumers omit explicit versions.
solid answer
~50 sA reusable, *published* alignment artifact is a `java-platform`. You create a module that applies the `java-platform` plugin and declares the family's coordinates as **constraints** (under `dependencies { constraints { api("g:m:v") } }`). When you publish it (via `maven-publish`), it becomes a real platform consumers import with `platform("you:platform:1.0")`. Constraints provide the version, so consumers depend on the modules *without* versions and all resolve to the platform's coordinates. To *enforce* (override transitive versions rather than just suggest), consumers use `enforcedPlatform(...)`, or the platform itself can be authored to align. By default `java-platform` forbids declaring real dependencies (only constraints); set `javaPlatform { allowDependencies() }` if you must import another BOM. This is the in-house equivalent of a vendor BOM — versioned, shareable across many builds, and the cleanest way to give an org one source of truth for a family's version.
code
kotlin · 12 linesplugins { `java-platform`; `maven-publish` }
dependencies {
constraints {
api("com.fasterxml.jackson.core:jackson-core:2.15.2")
api("com.fasterxml.jackson.core:jackson-databind:2.15.2")
}
}
publishing {
publications { create<MavenPublication>("platform") { from(components["javaPlatform"]) } }
}go deeper
Know that a java-platform is a publishable BOM consumers import with platform(...).
Author one with constraints, publish it, and explain platform vs enforcedPlatform.
Decide platform vs enforcedPlatform per risk, and compose platforms (allowDependencies + imported BOMs).
Run a versioned org platform as the single source of truth for family versions; govern its release cadence.
## What a java-platform is The `java-platform` plugin builds a component that carries *no code* — only **dependency constraints**. It's Gradle's first-class BOM. Publishing it yields Gradle Module Metadata (and a Maven BOM POM) other builds can consume. ```kotlin plugins { `java-platform` `maven-publish` } dependencies { constraints { api("com.fasterxml.jackson.core:jackson-core:2.15.2") api("com.fasterxml.jackson.core:jackson-databind:2.15.2") api("com.fasterxml.jackson.core:jackson-annotations:2.15.2") } } publishing { publications { create<MavenPublication>("platform") { from(components["javaPlatform"]) } } } ``` ## How consumers use it ```kotlin dependencies { implementation(platform("com.acme:jackson-platform:1.0")) implementation("com.fasterxml.jackson.core:jackson-databind") // no version } ``` The `platform(...)` notation imports the constraints. Because every family member's version comes from the *same* platform, the family stays consistent. If a transitive dependency requests a different member version, conflict resolution and the platform constraint together drive a single chosen version. ## platform vs. enforcedPlatform - `platform(...)` — constraints act as *preferences/recommendations*; a higher transitive request can still win. - `enforcedPlatform(...)` — constraints become *forced* (strict), overriding transitive requests. Powerful but blunt; can cause downgrades and surprising failures, so prefer plain `platform` unless you truly need to pin. ## allowDependencies By default a `java-platform` rejects regular `dependencies` (only `constraints` allowed) to keep it dependency-free. To import another platform/BOM inside yours, opt in: ```kotlin javaPlatform { allowDependencies() } dependencies { api(platform("org.springframework.boot:spring-boot-dependencies:3.3.0")) } ``` ## Why publish vs. a virtual platform A virtual platform (metadata-rule `belongsTo(..., true)`) is *local* to whatever build defines the rule. A published `java-platform` is **shareable** — one versioned artifact many repos import — making it the right tool for org-wide governance of a family's version.
- When would you choose enforcedPlatform over platform?When you must hard-override transitive versions (e.g. force a security-patched version family-wide). It's strict and can downgrade deps, so use sparingly and watch for breakage.
- Why does java-platform forbid normal dependencies by default?A platform should carry only constraints, not pull code. allowDependencies() relaxes this so you can import another BOM into yours.
- How does a published java-platform differ from a virtual platform?The java-platform is a real, shareable, versioned artifact published to a repo; a virtual platform is synthesized locally by a metadata rule and not published.
saying these in an interview costs you the question
- Reaching for enforcedPlatform by default — its forced versions cause silent downgrades and hard-to-debug resolution.
- Putting real implementation dependencies in a java-platform without allowDependencies().