Ad-Hockery

ad-hockery: /ad·hok'@r·ee/, n.
Gratuitous assumptions... which lead to the appearance of semi-intelligent behavior but are in fact entirely arbitrary. Jargon File

Gradle and Groovy’s Invoke Dynamic support

Since version 2.0 the Groovy distribution has included an alternate artifact that enables invoke dynamic support.

You can include that in a Gradle project by specifying a dependency like this:

build.gradle
compile "org.codehaus.groovy:groovy-all:2.3.3:indy"

However if you have other libraries that depend on groovy they may pull in the regular version transitively giving you two versions of Groovy in your dependency graph. This happens to me a lot with Spock which depends on groovy-all:2.0.5. For example I probably have a dependency like this as well:

build.gradle
testCompile "org.spockframework:spock-core:0.7-groovy-2.0"

I noticed that the External Libraries section of the project tree in IntelliJ IDEA contained two groovy-all jars. One is groovy-all-2.3.3 and the other is groovy-all-2.3.3-indy. That’s not good. I only want the indy version.

To debug where the dependency is coming from you can use Gradle’s dependencyInsight target like this:

gradle dependencyInsight --dependency groovy-all

By default the dependencyInsight only searches the compile configuration and you may well see nothing there. You can search other configurations by adding an argument on the command line. For example:

gradle dependencyInsight --dependency groovy-all --configuration testCompile

The output from the command looks like this:

:dependencyInsight
org.codehaus.groovy:groovy-all:2.3.3 (conflict resolution)
\--- compile

org.codehaus.groovy:groovy-all:2.0.5 -> 2.3.3
\--- org.spockframework:spock-core:0.7-groovy-2.0
     \--- testCompile

Here we can see groovy-all version 2.3.3 explicitly included as a compile dependency and pulled in transitively by Spock. Gradle’s conflict resolution has selected version 2.3.3 but what the output doesn’t show us is the variant. It doesn’t appear to be possible to tell whether the indy or regular flavor of groovy-all is pulled in.

To fix this I first tried forcing the version with:

build.gradle
configurations.all {
  resolutionStrategy {
    force "org.codehaus.groovy:groovy-all:2.3.3:indy"
  }
}

The dependencyInsight output changed a little:

:dependencyInsight
org.codehaus.groovy:groovy-all:2.3.3 (forced)
\--- compile

org.codehaus.groovy:groovy-all:2.0.5 -> 2.3.3
\--- org.spockframework:spock-core:0.7-groovy-2.0
     \--- testCompile

However, I could still see both versions of groovy-all in IDEA’s project tree. It looks like the force resolution strategy doesn’t take into account the variant you request.

Unfortunately the only way to get evict the regular groovy-all jar from the dependency tree seems to be to explicitly exclude it from every dependency that pulls it in transitively. For example:

build.gradle
testCompile("org.spockframework:spock-core:0.7-groovy-2.0") {
  exclude module: "groovy-all"
}

Finally the extra jar is gone from IDEA.

Web Statistics