Java 8 here.
Say there is an old version of the widget
libray, with Maven coordinates widgetmakers:widget:1.0.4
, that has a class defined in it like so:
public class Widget {
private String meow;
// constructor, getters, setters, etc.
}
Years pass. The maintainers of this widget
library decide that a Widget
should never meow
, rather, that it should in fact bark
. And so a new release is made, with Maven coordinates widgetmakers:widget:2.0.0
and with Widget
looking like:
public class Widget {
private Bark bark;
// constructor, getters, setters, etc.
}
So now I go to build my app, myapp
. And, wanting to use the latest stable versions of all my dependencies, I declare my dependencies like so (inside of build.gradle
):
dependencies {
compile (
,'org.slf4j:slf4j-api:1.7.20'
,'org.slf4j:slf4j-simple:1.7.20'
,'bupo:fizzbuzz:3.7.14'
,'commons-cli:commons-cli:1.2'
,'widgetmakers:widget:2.0.0'
)
}
Now let's say that this (fictional) fizzbuzz
library has always depended on a 1.x version of the widget
library, where Widget
would meow
.
So now, I'm specifying 2 versions of widget
on my compile classpath:
widgetmakers:widget:1.0.4
which is pulled in by the fizzbuzz
library, as a dependency of it; andwidgetmakers:widget:2.0.0
which I am referencing directlySo obviously, depending on which version of Widget
gets classloaded first, we will either have a Widget#meow
or a Widget#bark
.
Does Gradle provide any facilities for helping me out here? Is there any way to pull in multiple versions of the same class, and configure fizzbuzz
classes to use the old version of Widget
, and my classes to use the new version? If not, the only solutions I can think of are:
myapp/bin
and then give them different version-prefixes. Admittedly I don't see a clear solution here, but am sure something is feasible (yet totally hacky/nasty). Or...fizzbuzz
maintainers to upgrade it to the latest widget
version, or, sadly, downgrading myapp
to use the older widget
version.But Gradle (so far) has been magic for me. So I ask: is there any Gradle magic that can avail me here?
Don't know the specifics of Gradle, as I'm a Maven person, but this is more generic anyway. You basically have two options (and both are hacky):
Gradle will only set up the classpath with your dependencies, it doesn't provide its own runtime to encapsulate dependencies and its transitive dependencies. The version active at runtime will be the one according to the classloading rules, which I believe is the first jar in the classpath order to contain the class. OSGI provides runtime that can deal with situations like this and so will the upcoming module system.
EDIT: Bjorn is right in that it will try to resolve conflicts in different versions; it'll compile the classpath based on its strategies, so the order you put your dependencies in the file doesn't matter. However you still only get one class per classname, it won't resolve OP's issue
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With