110

I use the following two dependencies:

compile 'com.google.guava:guava:14.0.1'
compile 'com.google.guava:guava-gwt:14.0.1'

Both must be the same version to work correctly. Since my other dependencies use a higher version, Gradle uses different versions for each dependency.

I found this by running gradle dependencies:

compile - Compile classpath for source set 'main'.
 +--- com.google.guava:guava:14.0.1 -> 17.0
 +--- com.google.guava:guava-gwt:14.0.1
 |    +--- com.google.code.findbugs:jsr305:1.3.9
 |    \--- com.google.guava:guava:14.0.1 -> 17.0 

How can I force Gradle to set the same version for these two dependencies?

Mahozad
  • 18,032
  • 13
  • 118
  • 133
Michael
  • 32,527
  • 49
  • 210
  • 370

11 Answers11

151

Add this section to just above your dependencies block.

Groovy/Gradle:

configurations.all {
  resolutionStrategy { 
    force 'com.google.guava:guava:14.0.1'
    force 'com.google.guava:guava-gwt:14.0.1'
  }
}

Kotlin Script:

configurations.all {
  resolutionStrategy {
    force("com.google.guava:guava:14.0.1")
    force("com.google.guava:guava-gwt:14.0.1")
  }
}
milosmns
  • 3,595
  • 4
  • 36
  • 48
cmcginty
  • 113,384
  • 42
  • 163
  • 163
83
configurations.all {
  resolutionStrategy.eachDependency { details ->
    if (details.requested.group == 'com.google.guava') {
      details.useVersion "14.0.1"
    }
  }
}

dependencies {
  compile 'com.google.guava:guava'
  compile 'com.google.guava:guava-gwt'
}
Vyacheslav Shvets
  • 1,735
  • 14
  • 23
  • 1
    For some reason force method didn't prevent other versions of library being added to jar file but with your method I'll get multiple exact version of same library in jar file. One step closer. Thanks! – reith Jun 13 '18 at 08:06
  • 1
    DependencyResolveDetails not found in androidsudio 3.3.0 – Mr X Jan 25 '19 at 07:26
  • @MrX I've removed unnecessary DependencyResolveDetails mention from the code. Please try again – Vyacheslav Shvets Nov 19 '20 at 00:09
  • Thank you, it's the perfect solution when you have multiple artifacts in the group! – Max Sep 01 '22 at 02:03
43

I had a similar situation where one of the dependencies used spring-web 4.2.4 which was broken. You have to force specific library version you want. As mentioned in another comment, it might cause compatibility issues but sometimes is necessary.

Least intrusive way of forcing a library version I found was instead of using

compile "org.springframework:spring-web:4.2.3.RELEASE"

specifying dependency configuration as forced:

compile("org.springframework:spring-web:4.2.3.RELEASE"){
    force = true
}

I used it when I needed to downgrade Spring version temporarily (until next release).

Pijusn
  • 11,025
  • 7
  • 57
  • 76
20

One of your dependencies is forcing the guava version to update. Use gradle dependencies to locate which library is evicting your version.

The problem you have is that if you force it to use 14.0.1 another library may not work properly. Can you not just use the 17.0 version as your dependency?

Rather than maintain individual version numbers in the build.gradle I use a dependencies.gradle file which will have a mapping of version numbers and pull that into the build.gradle. That way I only need to maintain the single guava version. So your example will be:

dependencies.gradle

ext {
    ver = [
        guava: '14.0.1'
    ]
}

and then in the build.gradle file you can have:

apply from: "dependencies.gradle"

dependencies {
    compile group: 'com.google.guava', module: 'guava', version: ver.guava
    compile group: 'com.google.guava', module: 'guava-gwt', version: ver.guava
}

then when I want to move to 17.0 I only need to change the dependencies.gradle.

I am also a definite fan of setting transitive dependencies to false with

configurations.compile { transitive = false }

this way you do not have some dependencies evicted at compile time, although you may have a problem at run time if the evicting library is not fully backward compatible. Lets face it if you are writing the code you should know what libraries you use and you should be explicit about your dependencies. It protects you from one of your dependencies upgrading and messing you up.

Nacho Coloma
  • 7,070
  • 2
  • 40
  • 43
Klunk
  • 815
  • 7
  • 22
10

This is for Kotlin DSL (build.gradle.kts) tested with Gradle 7.1:

dependencies {
    implementation("org.jsoup", "jsoup") {
        version {
            strictly("1.14.3")
        }
    }
}

Another way:

dependencies {
    implementation("org.jsoup:jsoup") {
        version {
            strictly("1.14.+") // You can also use dynamic versions
        }
    }
}

Another way as suggested by other answers:

configurations.all {
    resolutionStrategy {
        force("org.jsoup:jsoup:1.14.3")
        force("com.google.guava:guava-gwt:14.0.1")
    }
}
Mahozad
  • 18,032
  • 13
  • 118
  • 133
9

Another option is to use dependency constraint: https://docs.gradle.org/current/userguide/dependency_constraints.html

dependencies {
    implementation 'org.apache.httpcomponents:httpclient'
    constraints {
        implementation('org.apache.httpcomponents:httpclient:4.5.3') {
            because 'previous versions have a bug impacting this application'
        }
        implementation('commons-codec:commons-codec:1.11') {
            because 'version 1.9 pulled from httpclient has bugs affecting this application'
        }
    }
}
Chris
  • 4,662
  • 2
  • 19
  • 27
sendon1982
  • 9,982
  • 61
  • 44
  • Is there a means of doing this in a loop? For example, I need to constrain about 8 packages in group `io.netty` and would like to not copy-paste a constraint for each one and I see no wildcard support. – drobert Nov 23 '22 at 21:40
5

I would suggest against setting transitive = false, as this approach would force yo to resolve the dependency tree yourself, manually.

You could either force the desired guava version via configurations.all, or add the dependency explicitly and set it forced = true.

Examples here: http://www.devsbedevin.net/android-understanding-gradle-dependencies-and-resolving-conflicts/

Vaiden
  • 15,728
  • 7
  • 61
  • 91
2

Alternatively you can use dependencySets (or mavenBom when BOM POM is available) support in spring-dependency-management Gradle plugin. Note that this plugin is also automatically applied with spring-boot Gradle plugin. For more details see here.

plugins {
  id 'io.spring.dependency-management' version '1.0.1.RELEASE'
}

dependencyManagement {
  dependencies {
    dependencySet(group: 'com.google.guava', version: '14.0.1') {
      entry 'guava'
      entry 'guava-gwt'
    }
  }
}

dependencies {
  compile 'com.google.guava:guava'
  compile 'com.google.guava:guava-gwt'
}
Stevo Slavić
  • 2,298
  • 2
  • 24
  • 32
1

If it's OK to just use the newer version for both dependencies, the simplest way to fix your problem is to update your dependencies:

compile 'com.google.guava:guava:17.0'
compile 'com.google.guava:guava-gwt:17.0'

That will make sure both of them are on 17.0. It's simpler than trying to force both of them on the older version and as an added bonus you get a newer version, which (probably) comes with bug fixes and new features.

To be fair @Klunk mentions this in his answer, by asking "Can you not just use the 17.0 version as your dependency?", but it's just in passing and easy to miss, so I thought it made sense to post as a separate answer.

Marcin Koziński
  • 10,835
  • 3
  • 47
  • 61
1

You can "force" versions for the libraries/dependencies in gradle like this:

    configurations.all {
        resolutionStrategy {
            force("org.jetbrains.kotlin:kotlin-stdlib:1.4.32",
                "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.32", 
"org.jetbrains.kotlin:kotlin-reflect:1.4.32"
            )
        }
    }

You can get more information on this here: https://docs.gradle.org/current/dsl/org.gradle.api.artifacts.ResolutionStrategy.html

Pavan
  • 31
  • 2
0

app/build.gradle

dependencies {
    compile('com.google.guava:guava') {
        version {
            strictly '14.0.1'
        }
    }
    compile('com.google.guava:guava-gwt') {
        version {
            strictly '14.0.1'
        }
    }
}

Version Gradlew

Gradle 6.7
dguard
  • 109
  • 2
  • 5