Platforms are used to ensure that all dependencies in a project align with a consistent set of versions.

Platforms help you manage and enforce version consistency across different modules or libraries, especially when you are working with a set of related dependencies that need to be kept in sync.

Using a platform

A platform is a specialized software component used to control transitive dependency versions. Typically, it consists of dependency constraints that either recommend or enforce specific versions. Platforms are particularly useful when you need to share consistent dependency versions across multiple projects.

In a typical setup you have:

  • A Platform Project: Which defines constraints for dependencies used across different subprojects.

  • A Number of Subprojects: Which depend on the platform and declare dependencies without specifying versions.

The java-platform plugin supports creating platforms in the Java ecosystem. Platforms are also commonly published as Maven BOMs (Bill of Materials), which Gradle natively supports.

To use a platform, declare a dependency with the platform keyword:

build.gradle.kts
dependencies {
    // get recommended versions from the platform project
    api(platform(project(":platform")))
    // no version required
    api("commons-httpclient:commons-httpclient")
}
build.gradle
dependencies {
    // get recommended versions from the platform project
    api platform(project(':platform'))
    // no version required
    api 'commons-httpclient:commons-httpclient'
}

This notation automatically performs several actions:

If strict version enforcement isn’t needed, you can disable it using the doNotEndorseStrictVersions method.

Creating a platform

In Java projects, the java-platform plugin combined with dependency constraints can be used to create a platform:

plugins {
    id("java-platform")
}

dependencies {
    constraints {
        api("com.google.guava:guava:30.1-jre")
        api("org.apache.commons:commons-lang3:3.12.0")
    }
}

This defines a custom platform with specific versions of guava and commons-lang3 that can be applied in other projects.

Importing a platform

Gradle supports importing BOMs, which are POM files containing <dependencyManagement> sections that manage dependency versions.

In order to qualify as a BOM, a .pom file needs to have pom set. This means that the POM file should explicitly specify <packaging>pom</packaging> in its metadata.

Gradle treats all entries in the block of a BOM similar to Adding Constrains On Dependencies.

Regular Platform

To import a BOM, declare a dependency on it using the platform dependency modifier method:

build.gradle.kts
dependencies {
    // import a BOM
    implementation(platform("org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE"))
    // define dependencies without versions
    implementation("com.google.code.gson:gson")
    implementation("dom4j:dom4j")
}
build.gradle
dependencies {
    // import a BOM
    implementation platform('org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE')
    // define dependencies without versions
    implementation 'com.google.code.gson:gson'
    implementation 'dom4j:dom4j'
}

In this example, the Spring Boot BOM provides the versions for gson and dom4j, so no explicit versions are needed.

Enforced Platform

The enforcedPlatform keyword can be used to override any versions found in the dependency graph, but should be used with caution as is effectively transitive and exports forced versions to all consumers of your project:

build.gradle.kts
dependencies {
    // import a BOM. The versions used in this file will override any other version found in the graph
    implementation(enforcedPlatform("org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE"))

    // define dependencies without versions
    implementation("com.google.code.gson:gson")
    implementation("dom4j:dom4j")

    // this version will be overridden by the one found in the BOM
    implementation("org.codehaus.groovy:groovy:1.8.6")
}
build.gradle
dependencies {
    // import a BOM. The versions used in this file will override any other version found in the graph
    implementation enforcedPlatform('org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE')

    // define dependencies without versions
    implementation 'com.google.code.gson:gson'
    implementation 'dom4j:dom4j'

    // this version will be overridden by the one found in the BOM
    implementation 'org.codehaus.groovy:groovy:1.8.6'
}

When using enforcedPlatform, exercise caution if your software component is intended for consumption by others. This declaration is transitive and affects the dependency graph of your consumers. If they disagree with any enforced versions, they’ll need to use exclude. Instead, if your reusable component strongly favors specific third-party dependency versions, consider using a rich version declaration with strictly.