Issue
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 method-not-found exception (since A's version of http client doesn't use a specific method any more).
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 collide with each other?
Solution
Welcome to maven dependency hell, as it's fondly known. This is a somewhat common problem as projects grow and more external dependencies are introduced.
Besides Apache Commons (mentioned in your original question), logging frameworks (log4j, slf4j) are another frequent culprit.
I agree with the advice given by "matts" on how to resolve conflicts once they are identified. In terms of catching these version conflicts early, you can also use the maven "enforcer" plugin. Refer to the "dependencyConvergence" config. Also see this SO post.
Using the enforcer plugin will fail the build immediately on version conflict, which saves you from the manual checks. This is an aggressive strategy, but prevents the type of run-time problems that prompted your question/post. Like anything, the enforcer plugin has pros and cons. We started using it within the last year, but then discovered it can be a blessing and a curse. Many versions of libs/frameworks are backwards compatible, and so depending (whether directly or indirectly) on both version 1.2.3 and 1.2.4 is often fine at both compile-time and run-time. However, the enforcer plugin will flag this conflict and require you to declare exactly which version you want. Assuming the number of dependency-conflicts is small, this does not require much work. However, once you introduce a large framework (e.g. Spring MVC) it can get nasty.
Hopefully that's useful information.
Answered By - Todd Patterson
Answer Checked By - Pedro (JavaFixing Volunteer)