How to resolve depedency between different versions - maven

I was exploring maven, currently using Ant. The application which we use here have different modules.
Now if I add dependencies to those how I can solve version conflict. Example module A has the dependecy of version1. while module B has the dependency of version2 now If someone need to work with both the module together than it will automatically resolve to version2 that is higher version.
Is there any internal behavior of maven or any command that I can use to resolve version conflicts?

Maven "solves" this problem by using the nearest declaration for transitives dependencies.
e.g.
A -> X -> externalLib 2.0
B -> externalLib 1.0
C -> A,B will result in using externalLib 1.0 since the declaration (over B) of 1.0 is nearer to C that over A and X
If they have the same distance the position within the POM file decides.
This is typically not the kind of "solution" you want. Since they might be incompatible it is better to choose a version manualle explicitely and declare this version in the pom of C
C -> externalLib 2.1
Note, if there is no version that is compatible to both X and B, there is no solution and Java does not support several versions of the same lib in one classloader. In this case you thould think of using OSGi or similar.

this link provides solution to your problem
http://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html

Related

Maven Transitive Dependency causing NoClassDefFound error

I am getting NoClassDefFoundError while trying to load a class which seems to be due to dependency version conflict.
Project A -> Project B -> Project C.
We have included version 2.0 for Project C within Project A.
whereas
Project B needs version 1.0 for Project C.
Right now when Project B code tries to load the class from Project C, it gets version 2.0.
Is there a way, I can explicitly define to refer to Project C (version 1.0 ) if project B tries to do so and in all other cases it should pick version 2.0
I mean the way we can exclude the transitive dependency, Is there a way to explicitly define inclusion ( only for the reference from the respective project and not the whole application code ).
Thanks.
I seriously doubt that. If I understand the question correctly, your build would result in loading the jar of project C in two different versions simultaneously into the JVM (one for Project B and one for Project A). As they probably share the same packages and class names, there is no way for the JVM to distinguish them.
If project C is your own project and the change from version 1.0 to 2.0 breaks something, I would think about using a new package name, like org.example.c2 instead of org.example.c (like e.g. in the Apache commons-lang project).

Ensuring consistent dependencies version in Maven

In my project I have module M1 it use library A. This library have dependency to library B.
And in another module M2 I want to use library B.
And of course I have "root" module which depend on all my modules so versions of library B should be the same across all projects.
So I added B to dependency of my M2 module but don't know how to specify it version because I need exactly same version as library A use.
If I specify current version of library B then when I will upgrade library A to new version I will forget to update version of B in my module.
Also I don't want to put A as dependency of M2 because I need only limited part of it's functionality.
What is best practices for my case?
The maven enforce plugin can break the build if the versions diverge so that yo do not forget to update: see https://maven.apache.org/enforcer/enforcer-rules/dependencyConvergence.html
There are several options some of them you exclude explicitely. Let me mention them for the sake of completeness anyway:
Include B as a dependency in M2.
Advantage: Cleanest solution with respect to adding only those functionality to M2 that's actually needed.
Disadvantage: Version of B in M2 has to be kept in sync with versin of B in A manually.
Include A as a dependency in M2.
Advantage: Central <DependencyManagement> can be used in your parent POM. Hence, Versions of B will always be the same in all sub-projects.
Disadvantage: Functionality of A not needed in M2 is added to M2.
Include M1 as a dependency in M2.
Advantage: M2 always uses the same version of B as A without having to deal with B as a dependency at all.
Disadvantage: Functionality of M1 and of A not needed in M2 is added to M2.
Use <dependency>/.../<exclusion> to exclude B from A in M1.
Advantage: Central <DependencyManagement> can be used in your parent POM. Hence, Versions of B will always be the same in all sub-projects.
Disadvantage: Version of B has to be kept in sync with version of B in A manually.
[Input is welcome in case there's anything else I haven't thought of.]
Try Maven Enforcer Plugin's Dependency Convergence mentioned by Assen Kolov in his answer. If it works for a mixture of direct and transitive dependencies, like in your case, as well, I'd use it in conjunction with 1.

Best way to handle a Maven transitive dep version?

I'm not quite sure of the best way to handle the following situation in my Maven project...
I have two direct dependencies A and B. Both depend on different versions of C. Dependency A is compatible with both versions of C, but dependency B is only compatible with it's declared version of C. I'd like to simply use whatever version of C that B declares.
I realize that I can exclude the dependency of C in dependency A, but then if I ever removed dependency B or if C was removed as a dependency of B...A would not work anymore.
I also realize that I can declare B's current version of C in my dependency management section, but then I would not seamlessly get the change if B ever changed it's version of C.
What is the prescribed way to handle this sort of situation?
The best way as recommended, although, slightly indirectly, by the maven docs is to use the dependency management feature. Quoting the doc,
A second, and very important use of the dependency management section
is to control the versions of artifacts used in transitive
dependencies.
I can understand that you are forced to update the version of C on your target project, say T, every time B uses a new version of C, but you also have to look at this from the T's POV - the target project T, ought to know and be able to control all the versions of the transitive dependencies it has.

Dependency on two versions of a Jar

I have a module X that is dependent on a Third party library which in turn depends on apache-commons-collections 2.1.
In module X, I want to use the latest apache-commons-collections 3.0 which has some additional methods than 2.1. If I add a dependency to 3.0, I'm guessing this will create a problem since the class loader just picks up the first class it sees in the classpath. Is there a good way to get around this problem?
Thanks,
S
IMHO there is no really good way without additional solution for modularity (like Java EE's EAR or OSGi). I guess however that you're asking about just simple web (or not) module that directly use this 3rd party lib. I'm afraid you have to resolve this conflict manually. If fact, Maven won't provide 2 versions of commons-collections and depend on classloader's resolution, but rather resolve dependencies graph and pick the version it guess it's better with your POMs' declarations in mind. That means, if you declare in module X dependency on commons-collections version 3.0, that version will be used since this declaration is more important than some 3rd party lib's dependencies.
That's a serious problem of Java Platform itself, cousing such problems like the famous JAR hell. Unfortunately, it is your problem to choose and declare commons-collections version that satisfy both you and your 3rd party lib.
Just add the dependency to 3.0 to your project and it will prefer it over the older version of 2.1. To be explicit you can add an exclusion. In any case use the dependency plugin and the analyze and tree goals to see what is happening.
Long story short... this happens all the time and will be fine and in any case you can control what happens.

Automatic exporting of dependencies in InteliJ Idea when reading poms?

i tried to search both here and on jetbranis.net however i did not found an answer.
I have created a project (P) using maven that have to modules (A,*B*). The module A is dependant on module B and module B is dependent on libraries R. When I open P using the InteliJ Idea 10.0.1 everything works smoothly. The only problem that i have is dependency handling.
The dependencies were imported transitively. Both A,*B* are now dependent on libraries R. I would expect B to be dependent on R, but i would expect R to be exported and A to be dependent only on B.
I found some old posts on jetbrains that seam to be related, however it seams that they have opposite problem http://devnet.jetbrains.net/thread/286098. Can anybody advise me please? Did i missed some configuration option?
This is how Maven's dependencies work; each module (aka Maven Project) has an isolated classpath. Dependencies, imported into IDEA, are not 'exported' to prevent interference between transitive dependencies.

Resources