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:
dependencies {
// get recommended versions from the platform project
api(platform(project(":platform")))
// no version required
api("commons-httpclient:commons-httpclient")
}
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:
-
Sets the
org.gradle.category
attribute to platform, ensuring Gradle selects the platform component. -
Enables the
endorseStrictVersions
behavior by default, enforcing strict versions defined in the platform.
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:
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")
}
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:
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")
}
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
.