Building bluetape4k-dependencies Part 2: Making the 1.0.0 BOM a Public Contract

Part 1 covered why bluetape4k-dependencies was needed. Once
repositories move independently, users ask which combination is safe.
projects is 1.11.0,exposed is 1.11.0,aws is 0.4.0...Which combination should my application import?This part is about turning that answer into a real public artifact.
A BOM Needs More Than the Name
Section titled “A BOM Needs More Than the Name”Calling something a BOM does not make it useful. A useful BOM must participate in dependency resolution.
Weak contract: README says "use these versions"
Public contract: Maven Central artifact imports those versions into dependency resolutionThe first version had to answer where the source of truth lived. The central BOM should not duplicate every artifact already managed by repository-owned BOMs.
dependencies { api(platform(libs.bluetape4k.bom)) api(platform(libs.bluetape4k.aws.bom)) api(platform(libs.bluetape4k.exposed.bom)) api(platform(libs.bluetape4k.image.bom)) api(platform(libs.bluetape4k.text.bom)) api(platform(libs.bluetape4k.graph.bom)) api(platform(libs.bluetape4k.leader.bom)) api(platform(libs.bluetape4k.javers.bom))}Each repository keeps responsibility for its modules. The central BOM combines those repository BOMs and shared external dependency lines.
Build It with Gradle java-platform
Section titled “Build It with Gradle java-platform”Gradle’s java-platform plugin is the right shape for this artifact.
plugins { `java-platform` `maven-publish` signing}
javaPlatform { allowDependencies()}The allowDependencies() call matters because this platform imports other platforms. The central BOM delegates to
sub-BOMs instead of restating every module constraint.
External dependency families can still be constrained where the central line needs to keep the ecosystem coherent:
constraints { api(libs.exposed.core) api(libs.fabric8.kubernetes.client) api(libs.ktor.bom) api(libs.netty.bom) api(libs.testcontainers.bom)}BOM and Catalog Have Different Readers
Section titled “BOM and Catalog Have Different Readers”bluetape4k-dependencies also has a Gradle Version Catalog, but the catalog is not the public BOM.
| Item | Who uses it | What it affects |
|---|---|---|
| BOM | Applications and library users | dependency resolution |
| Gradle Version Catalog | bluetape4k maintainers | build script aliases, plugin/library versions |
An application imports:
implementation(platform("io.github.bluetape4k:bluetape4k-dependencies:1.3.1"))Maintainers may also pin a catalog:
[versions]kotlin = "2.2.0"
[libraries]bluetape4k-core = { module = "io.github.bluetape4k:bluetape4k-core" }Those two surfaces should not be described as the same artifact. The BOM is a Maven Central resolution contract. The catalog is a build-authoring contract for the repositories that produce and test the ecosystem.

Clean Up the Spring Boot Artifact Names First
Section titled “Clean Up the Spring Boot Artifact Names First”The public contract also had to avoid transitional names. If a Spring Boot 4 line is the public direction, the artifact names and dependency guidance should not preserve old temporary names that confuse users.
Transitional naming leaks internal migration state.Public naming should describe the supported consumption path.That cleanup belonged before the first public contract, not after users had already copied examples.
POM Metadata Is Also a Feature
Section titled “POM Metadata Is Also a Feature”The published POM is what downstream tools read. License, SCM, developer metadata, dependency scopes, and empty versions all matter.
publishing { publications.withType<MavenPublication>().configureEach { pom { name.set("bluetape4k-dependencies") description.set("Dependency management BOM for the bluetape4k ecosystem") url.set("https://github.com/bluetape4k/bluetape4k-dependencies") } }}Before publishing, inspect the result locally.
./gradlew publishToMavenLocalThe check is not ceremony. It catches missing SCM entries, snapshot references, or an empty version before Maven Central makes the mistake permanent.
What Users See
Section titled “What Users See”The final user-facing Gradle shape is intentionally small.
dependencies { implementation(platform("io.github.bluetape4k:bluetape4k-dependencies:1.3.1")) implementation("io.github.bluetape4k:bluetape4k-core") implementation("io.github.bluetape4k.exposed:bluetape4k-exposed-jdbc")}Maven is equally explicit.
<dependencyManagement> <dependencies> <dependency> <groupId>io.github.bluetape4k</groupId> <artifactId>bluetape4k-dependencies</artifactId> <version>1.3.1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement>Applying This to Your Own Libraries
Section titled “Applying This to Your Own Libraries”| Question | Guideline |
|---|---|
| Does each repository already have a BOM? | Prefer importing sub-BOMs in the central BOM. |
| Is the central BOM repeating every artifact? | Repetition increases missing and stale constraints. |
| Are you explaining the catalog like a user artifact? | Catalog is build authoring; BOM is dependency resolution. |
| Does the artifact name match the future direction? | Do not publish migration-era naming as the first public contract. |
| Did you inspect the generated POM? | Catch license, SCM, snapshot, and empty-version errors before release. |
Read Next
Section titled “Read Next”The next part covers release-train behavior through 1.3.0: snapshot inputs, Maven Central visibility, transient 403s,
POM metadata, and the 1.3.1 patch.
Series
Section titled “Series”For the user-facing import path, start with the usage guide.
- Building bluetape4k-dependencies Part 1: Why the BOM Became Necessary
- Building bluetape4k-dependencies Part 2: Making the 1.0.0 BOM a Public Contract
- Building bluetape4k-dependencies Part 3: Maven Central Has No Rollback Button
Comments
Leave a note or reaction with your GitHub account.