The Java Platform Plugin
The Java Platform plugin brings the ability to declare platforms for the Java ecosystem. A platform can be used for different purposes:
-
a description of modules which are published together (and for example, share the same version)
-
a set of recommended versions for heterogeneous libraries. A typical example includes the Spring Boot BOM
-
sharing a set of dependency versions between subprojects
A platform is a special kind of software component which doesn’t contain any sources: it is only used to reference other libraries, so that they play well together during dependency resolution.
Platforms can be published as Gradle Module Metadata and Maven BOMs.
The java-platform plugin cannot be used in combination with the java or java-library plugins in a given project.
Conceptually a project is either a platform, with no binaries, or produces binaries.
|
Usage
To use the Java Platform plugin, include the following in your build script:
plugins {
`java-platform`
}
plugins {
id 'java-platform'
}
API and runtime separation
A major difference between a Maven BOM and a Java platform is that in Gradle dependencies and constraints are declared and scoped to a configuration and the ones extending it. While many users will only care about declaring constraints for compile time dependencies, thus inherited by runtime and tests ones, it allows declaring dependencies or constraints that only apply to runtime or test.
For this purpose, the plugin exposes two configurations that can be used to declare dependencies: api
and runtime
.
The api
configuration should be used to declare constraints and dependencies which should be used when compiling against the platform, whereas the runtime
configuration should be used to declare constraints or dependencies which are visible at runtime.
dependencies {
constraints {
api("commons-httpclient:commons-httpclient:3.1")
runtime("org.postgresql:postgresql:42.2.5")
}
}
dependencies {
constraints {
api 'commons-httpclient:commons-httpclient:3.1'
runtime 'org.postgresql:postgresql:42.2.5'
}
}
Note that this example makes use of constraints and not dependencies. In general, this is what you would like to do: constraints will only apply if such a component is added to the dependency graph, either directly or transitively. This means that all constraints listed in a platform would not add a dependency unless another component brings it in: they can be seen as recommendations.
For example, if a platform declares a constraint on |
By default, in order to avoid the common mistake of adding a dependency in a platform instead of a constraint, Gradle will fail if you try to do so. If, for some reason, you also want to add dependencies in addition to constraints, you need to enable it explicitly:
javaPlatform {
allowDependencies()
}
javaPlatform {
allowDependencies()
}
Local project constraints
If you have a multi-project build and want to publish a platform that links to subprojects, you can do it by declaring constraints on the subprojects which belong to the platform, as in the example below:
dependencies {
constraints {
api(project(":core"))
api(project(":lib"))
}
}
dependencies {
constraints {
api project(":core")
api project(":lib")
}
}
The project notation will become a classical group:name:version
notation in the published metadata.
Sourcing constraints from another platform
Sometimes the platform you define is an extension of another existing platform.
In order to have your platform include the constraints from that third party platform, it needs to be imported as a platform
dependency:
javaPlatform {
allowDependencies()
}
dependencies {
api(platform("com.fasterxml.jackson:jackson-bom:2.9.8"))
}
javaPlatform {
allowDependencies()
}
dependencies {
api platform('com.fasterxml.jackson:jackson-bom:2.9.8')
}
Publishing platforms
Publishing Java platforms is done by applying the maven-publish
plugin and configuring a Maven publication that uses the javaPlatform
component:
publishing {
publications {
create<MavenPublication>("myPlatform") {
from(components["javaPlatform"])
}
}
}
publishing {
publications {
myPlatform(MavenPublication) {
from components.javaPlatform
}
}
}
This will generate a BOM file for the platform, with a <dependencyManagement>
block where its <dependencies>
correspond to the constraints defined in the platform module.
Consuming platforms
Because a Java Platform is a special kind of component, a dependency on a Java platform has to be declared using the platform
or enforcedPlatform
keyword, as explained in the managing transitive dependencies section.
For example, if you want to share dependency versions between subprojects, you can define a platform module which would declare all versions:
dependencies {
constraints {
// Platform declares some versions of libraries used in subprojects
api("commons-httpclient:commons-httpclient:3.1")
api("org.apache.commons:commons-lang3:3.8.1")
}
}
dependencies {
constraints {
// Platform declares some versions of libraries used in subprojects
api 'commons-httpclient:commons-httpclient:3.1'
api 'org.apache.commons:commons-lang3:3.8.1'
}
}
And then have subprojects depend on the platform to get recommendations:
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'
}