Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
177 views
in Technique[技术] by (71.8m points)

Conflicting library version in a java maven project

When building a maven project that has many dependencies, some of those dependencies depend on the same library but use a different version which is causing errors when running an application.

For example, if I add two different project dependencies, A and B that both depend on apache commons http client but each one on a different version, once the class-loader loads A's apache commons http client classes, B will try to use them since they are already loaded by the class loader.

But B's bytecode depends on a different version of the loaded classes causing multiple problems when running the application. A common one is methodnotfound exception ( since A's version of http client doesnt use a specific method anymore ).

What is the general strategy when building to avoid such conflicts ? Does one have to manually check the dependency tree to figure out which common libraries colide with each other ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use the tree goal of the Maven dependency plugin to display all transitive dependencies in your project and look for dependencies that say "omitted for conflict".1

mvn dependency:tree -Dverbose
mvn dependency:tree -Dverbose | grep 'omitted for conflict'

Once you know which dependency has version conflicts, you can use the includes parameter to show just dependencies that lead to that one to see how a particular dependency is being pulled in. For example, a project where different versions of C are pulled in by A and B:

mvn dependency:tree -Dverbose -Dincludes=project-c

[INFO] com.my-company:my-project:jar:1.0-SNAPSHOT
[INFO] +- project-a:project-a:jar:0.1:compile
[INFO] |  - project-c:project-c:jar:1.0:compile
[INFO] - project-b:project-b:jar:0.2:compile
[INFO]    - project-x:project-x:jar:0.1:compile
[INFO]       - (project-c:project-c:jar:2.0:compile - omitted for conflict)

To actually resolve the conflict, in some cases it may be possible to find a version of the transitive dependency that both of your primary dependencies will work with. Add the transitive dependency to the dependencyManagement section of your pom and try changing the version until one works.

However, in other cases it may not be possible to find a version of the dependency that works for everyone. In these cases, you may have to step back the version on one of the primary dependencies in order to make it use a version of the transitive dependency that works for everybody. For instance, in the example above, A 0.1 uses C 1.0 and B 0.2 uses C 2.0. Assume C 1.0 and 2.0 are completely incompatible. But maybe it is possible for your project to use B 0.1 instead, which happens to depend on C 1.5, which is compatible with C 1.0.

Of course these two strategies will not always work, but I have found success with them before. Other more drastic options include packaging your own version of the dependency that fixes the incompatibility or trying to isolate the two dependencies in separate classloaders.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...