53

Many of my jars have conflicting transitive dependencies (multiple spring versions). I would like to avoid inherited version conflicts by managing all of my dependencies explicitly, is it possible to disable all transitive dependencies in Gradle?

I know I can add transitive = false to each of my dependencies, but I am hoping there is a simpler way.

compile(group: 'org.springframework', name: 'spring', version: '2.5.2') {
    transitive = false
}
Rylander
  • 19,449
  • 25
  • 93
  • 144

5 Answers5

57

I ended up using:

configurations.all {
    transitive = false
}
Rylander
  • 19,449
  • 25
  • 93
  • 144
9

If you want to have just one configuration block for all configurations you can use spread-dot operator to express this.

configurations {
    // other configurations e.g. - compile.exclude module: 'commons-logging'
    all*.transitive = false
}
michal.kreuzman
  • 12,170
  • 10
  • 58
  • 70
9

In my case, I had a project (gradle module) depedency. I used the following to exclude the transitive dependencies in Gradle 3:

implementation(project(':<module_name>')) {
    transitive = false
}

Or in Kotlin script:

implementation(project(':<module_name>')) {
    isTransitive = false
}
stiemannkj1
  • 4,418
  • 3
  • 25
  • 45
0

In Gradle 7.5.1, you can use this code in Groovy DSL:

configurations.configureEach {
    transitive = false
}

If you are using Kotlin DSL:

configurations.configureEach {
    isTransitive = false
}
xfl03
  • 29
  • 4
0

TLDR;

Enforced Platforms are now available, and they provide a much better way to strictly enforce versions rather than disabling transitive dependencies.

More Info

Most of the time disabling transitive will work, but not all of the time; the logic for version resolution still runs. If a certain dependency has gradle module information attached to it that tells gradle that it must absolutely have this specific version, well that's the version you are getting even though you specifically included that dependency and you specified a different specific version.

Example

/my-platform/build.gradle.kts

plugins {
  id("java-platform")
}

dependencies {
  constraints {
    // Use latest from Jackson
    api("com.fasterxml.jackson.core:jackson-annotations:2.15.2")
    api("com.fasterxml.jackson.core:jackson-core:2.15.2")
    api("com.fasterxml.jackson.core:jackson-databind:2.15.2")
    // Use older version of jaxb because Dave, your CTO, is getting
    // kickbacks from IBM to force your app to run on Websphere
    runtime("javax.xml.bind:jaxb-api:2.2.12")
  }
}

Did you notice there's no src folder? It's JUST a gradle build script.

/my-xml-lib/build.gradle.kts

plugins {
  java
}
dependencies {
  implementation(enforcedPlatform(project(":my-platform")))
  implementation("com.fasterxml.jackson.core:jackson-databind:2.14.0")//Resolves to 2.15.2
  runtime("javax.xml.bind:jaxb-api:3.+") //Dude what? Why!? Anyways, this resolves to 2.2.12
}

In case you need to use multiple platforms, remember the following:

enforcedPlatform versions will always win over platform (ie: suggested) versions. The last platform that is included wins over previously included platforms of the same priority level.

dependencies {
  
  implementation(enforcedPlatform("com.my.security.updates:vulnerability-updates:+")) //Always uses latest non-vulnerable versions. Versions here win over "suggested" versions from  evilcorp
  
  implementation(platform("com.stupid.fn:dave:evilcorp-platform:616")) //make Dave happy that you included their platform while not allowing it to replace versions from vulnerability-updates

  implementation(platform(project(":friendly-suggestions-api"))) //wins over anything given from evilcorp, loses to enforced "my-platform"

  implementation(enforcedPlatform(project(":my-platform"))) //Winner over all previously included platform versions, even the vulnerability-updates one
}
Pytry
  • 6,044
  • 2
  • 37
  • 56