[[sec:using-platform-to-control-transitive-deps]]
= Sharing dependency versions between projects

[[sub:sharing-dep-versions-between-projects]]
== Using a platform to control transitive versions

A <<dependency_management_terminology.adoc#sub::terminology_platform,platform>> is a special software component which can be used to control transitive dependency versions.
In most cases it's exclusively composed of <<dependency_constraints.adoc#sec:adding-constraints-transitive-deps,dependency constraints>> which will either _suggest_ dependency versions or _enforce_ some versions.
As such, this is a perfect tool whenever you need to _share dependency versions between projects_.
In this case, a project will typically be organized this way:

- a `platform` project which defines constraints for the various dependencies found in the different sub-projects
- a number of sub-projects which _depend on_ the platform and declare dependencies _without version_

In the Java ecosystem, Gradle provides a <<java_platform_plugin.adoc#java_platform_plugin,plugin>> for this purpose.

It's also common to find platforms published as Maven BOMs which <<#sub:bom_import,Gradle supports natively>>.

A dependency on a platform is created using the `platform` keyword:

.Getting versions declared in a platform
====
include::sample[dir="java-platform/recommender/groovy/consumer",files="build.gradle[tags=get-recommendations]"]
include::sample[dir="java-platform/recommender/kotlin/consumer",files="build.gradle.kts[tags=get-recommendations]"]
====

[NOTE]
====
This `platform` notation is a short-hand notation which actually performs several operations under the hood:

* it sets the link:{javadocPath}/org/gradle/api/attributes/Category.html[org.gradle.category attribute] to `platform`, which means that Gradle will select the _platform_ component of the dependency.
* it set the link:{javadocPath}/org/gradle/api/artifacts/ModuleDependency.html#endorseStrictVersions--[endorseStrictVersions] behavior by default, meaning that if the platform declares strict dependencies, they will be enforced.

This means that by default, a dependency to a platform triggers the inheritance of all <<rich_versions.adoc#sec:strict-version,strict versions>> defined in that platform, which can be useful for platform authors to make sure that all consumers respect their decisions in terms of versions of dependencies.
This can be turned off by explicitly calling the `doNotEndorseStrictVersions` method.
====

[[sub:bom_import]]
== Importing Maven BOMs

Gradle provides support for importing https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Importing_Dependencies[bill of materials (BOM) files], which are effectively `.pom` files that use `<dependencyManagement>` to control the dependency versions of direct and transitive dependencies.
The BOM support in Gradle works similar to using `<scope>import</scope>` when depending on a BOM in Maven.
In Gradle however, it is done via a regular dependency declaration on the BOM:

.Depending on a BOM to import its dependency constraints
====
include::sample[dir="userguide/dependencyManagement/managingTransitiveDependencies/constraintsFromBOM/groovy",files="build.gradle[tags=dependency-on-bom]"]
include::sample[dir="userguide/dependencyManagement/managingTransitiveDependencies/constraintsFromBOM/kotlin",files="build.gradle.kts[tags=dependency-on-bom]"]
====

In the example, the versions of `gson` and `dom4j` are provided by the Spring Boot BOM.
This way, if you are developing for a platform like Spring Boot, you do not have to declare any versions yourself but can rely on the versions the platform provides.

Gradle treats all entries in the `<dependencyManagement>` block of a BOM similar to <<dependency_constraints.adoc#sec:adding-constraints-transitive-deps,Gradle's dependency constraints>>.
This means that any version defined in the `<dependencyManagement>` block can impact the dependency resolution result.
In order to qualify as a BOM, a `.pom` file needs to have `<packaging>pom</packaging>` set.

However often BOMs are not only providing versions as recommendations, but also a way to override any other version found in the graph.
You can enable this behavior by using the `enforcedPlatform` keyword, instead of `platform`, when importing the BOM:

.Importing a BOM, making sure the versions it defines override any other version found
====
include::sample[dir="userguide/dependencyManagement/managingTransitiveDependencies/enforcedConstraintsFromBOM/groovy",files="build.gradle[tags=dependency-on-bom]"]
include::sample[dir="userguide/dependencyManagement/managingTransitiveDependencies/enforcedConstraintsFromBOM/kotlin",files="build.gradle.kts[tags=dependency-on-bom]"]
====
