Your code is only as good as its worst library.
Ivy is a dependency manager that makes Ant work with maven repositories, transparently managing and accumulating all your jar's for you, under the hood. The awesome thing about these dependency managers is that they manage transitive dependencies for you, so that you don't have to worry about the dependencies of your dependencies.
90% of the time this is perfect, --- but what happens when you have a transitive dependency that references an old version of a jar, while your source code needs the same library's updated version ?
!! This leads to a compile error !!
Not necessarily in your IDE, but quite possibly in Ant. Or maybe vice-versa. In my case, specifically, I had an old version of commons-io referenced from a jar which my source code depended on. This is a "transitive dependency" (A referenced B which referenced C, making A transitively dependant on C).
This is kind of like a codependent relationship, for those of you that know what that is. Its not good at all, it basically means that any issues in the "old" jar will effect your shiny new application due to the transitive dependency. But java's class loader is smart enough to use the "new" jar in place of the old one, if you can just convince ivy and ant to ignore the old jar.
So how do you solve these sorts of issues ?
1) Track down the bad jar version by inspecting the javac classpath in ant. This can be done by running ant in verbose mode (ant -v) and simply grepping for the library name. In may case, this meant doing something like this (an old version of commons-io was messing up my compilation step):
ant -v > /tmp/out
grep 'commons-io' /tmp/out
2) Once grep confirmed that, indeed, ant was putting an old jar file (that broke my compile) at the beggining of the classpath, I simply had to find out where that jar was coming from. This, again, is easy if you look at the verbose output of your dependency resolution.
3) Finally, in your ivy.xml file, go to the dependency whose transitive dependency is causing the collision. For example, and inside its dependency declaration, add an "exclude" block, which will force ivy NOT to download certain dependencies :
<dependency org="mydepWithAncientTransitives" name=... >
<exclude name="commons-io"/>
</dependency>
Voila
You should now be able to re run your resolve/build step in ant, and this time, the "old" jar won't stand in the way of your compiler - and you should be able to confirm this by again looking at the output of "ant -v".

No comments:
Post a Comment