Imagine a are writing an application that has 2 dependencies; lets call them dependency A
and dependency B
. You have no control over either of those dependencies; they are not your libraries, but your application depends on them none-the-less. It turns out that dependency A
has a dependency on dependency X
(version 1.0); and B has a dependency on X
(version 2.0).
According to the Maven documentation, Dependency mediation will be used to decide which dependency to use:
Dependency mediation - this determines what version of a dependency will be used when multiple versions of an artifact are encountered. Currently, Maven 2.0 only supports using the "nearest definition" which means that it will use the version of the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it explicitly in your project's POM. Note that if two dependency versions are at the same depth in the dependency tree, until Maven 2.0.8 it was not defined which one would win, but since Maven 2.0.9 it's the order in the declaration that counts: the first declaration wins.
So, presuming we declare dependency A
first, then X
version 1.0 will be used in our application. This means dependency B
will be using X
version 1.0 at runtime, where as was compiled against X
version 2.0. If B
is using some 2.0 only features, then we will get a run time error (NoSuchMethodError
, ClassNotFoundException
etc.), that's not good.
So to "fix" this, we can exclude dependency X
from dependency A
, so that X
version 2.0 is used instead. But oh no! X
version 2.0 isn't backwards compatible, so we end up getting run time errors from A
instead.
As far as I can tell, there is no way to fix this properly with Maven. All you can do is hope to get hold of the source code of one of the libraries and fix it your self. Is that correct?
Why is it not possible for both versions of the X
to be packaged into my application, such that A
uses X
version 1.0, B
uses X
version 2.0, and the version of X
available in my application is whatever Maven chooses through dependency mediation. Is it a limitation of Java, or a limitation of Maven? Is this situation common? Are there any other possible solutions? Should all libraries guarantee backwards compatibility to avoid this problem?