TransWikia.com

Which Maven BOM determines a dependency's version in Gradle 5?

Stack Overflow Asked by Robin Ellerkmann on December 16, 2020

I am currently developing a Gradle 5 project that imports two different Maven BOMs. Therefore, I use the native Gradle syntax without the dependency management plugin. However, both BOMs may define different versions for the same dependency.

dependencies {
    implementation platform ("org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}")
    implementation platform ("com.organisation:xyz:${otherBomVersion}")
}

As far as I know in Maven the first BOM which defines a version for a given dependency determines it. In contrast, in the Gradle dependency management plugin the last BOM which defines a version for a given dependency determines it.

How is the order of imported BOMs handled in pure Gradle 5?

2 Answers

The order of BOMs, or wherever the dependency is declared, doesn't matter at all in Gradle. Unlike Maven, which uses a nearest first approach, Gradle takes all dependency information in consideration and selects the highest. The documentation states

Gradle will consider all requested versions, wherever they appear in the dependency graph. Out of these versions, it will select the highest one.

A practical example. The following declaration will always select 2.2.5.RELEASE of Spring Cloud Gateway defined by spring-cloud-dependencies BOM version Hoxton.SR8 no matter which platform() declaration is listed first:

dependencies {
    implementation platform('org.springframework.cloud:spring-cloud-dependencies:Hoxton.SR8')
    implementation platform('org.springframework.cloud:spring-cloud-dependencies:Greenwich.SR6')
    
    implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
}

The dependency insight report may look like this:

> gradlew -q dependencyInsight --dependency spring-cloud-starter-gateway
org.springframework.cloud:spring-cloud-starter-gateway:2.2.5.RELEASE (by constraint)
   variant "compile" [
      org.gradle.status              = release (not requested)
      org.gradle.usage               = java-api
      org.gradle.libraryelements     = jar (compatible with: classes)
      org.gradle.category            = library (not requested)

      Requested attributes not found in the selected variant:
         org.gradle.dependency.bundling = external
         org.gradle.jvm.version         = 8
   ]

org.springframework.cloud:spring-cloud-starter-gateway:2.2.5.RELEASE
--- org.springframework.cloud:spring-cloud-dependencies:Hoxton.SR8
     --- compileClasspath

org.springframework.cloud:spring-cloud-starter-gateway -> 2.2.5.RELEASE
--- compileClasspath

You may use enforcedPlatform() should you prefer versions from a specific BOM.

Answered by thokuest on December 16, 2020

A simpler suggestion would be to use this mechanism described in the Spring Boot Gradle Plugin docs, whereby you can explicitly override versions picked by setting properties.

The example they give:

ext['slf4j.version'] = '1.7.20'

The full list of properties you can set can be found in the Spring Boot reference documentation.

In the end you would have an explicit way to override the defaults given by Spring Boot.

Ah, and now I see you are in fact not using that plugin, so this mechanism doesn't apply to you. Well, if you start using it, the above should work as intended and be predictable.

Answered by rud on December 16, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP