2

Say you have a project (web app) which uses 2 third-party libraries - A and B.
Say A depends on version 1.10 of another third-party library C.
Say B depends on version 1.15 of the same third-party library C.

Which version of C should you put in the lib folder of your web app project?!

Assume you don't know C well, you're not sure if C 1.15 is compatible with 1.10, or anything like that.

Is there a way to put A.jar and B.jar, and both C jars in the lib folder of your project, but at runtime (under Tomcat or JBoss e.g.) have A load C 1.10 jar, but have B load C 1.15 jar.

I don't think this is possible as they share the same web app class loader (and so it will load the C classes either from 1.10 or from 1.15 pretty much unpredictably; whichever of the two JARs happens to be first on the classpath) ... but I'm not sure.

If it's indeed not possible, what's the best practice for handling this kind of conflicts?

peter.petrov
  • 38,363
  • 16
  • 94
  • 159
  • You shouldn't code something that requires 2 versions of the same library. That's just following poor coding standards. I would suggest you update to the latest version of the library, and then update code as needed to be compatible. – Mike Elofson Jan 23 '15 at 17:28
  • @MikeElofson Note that I didn't code it. I just want to use A and B which are two unrelated third-party libraries. They rely on different versions of C. – peter.petrov Jan 23 '15 at 17:29
  • And the libraries that you are using do not package their required jars into the library themselves? – Mike Elofson Jan 23 '15 at 17:32
  • Say they don't (they are not uber jars), say they do (they are uber jars). I would appreciate an answer is both cases. Does it matter in fact, isn't all this loaded by the same classloader? I'm looking for a best practice here as I often stumble upon such issues and I have no general solution for them yet. So I usually have to take just version 1.15 of C (at runtime), and just hope that A will also work fine with it (but I have no guarantees for that, of course). – peter.petrov Jan 23 '15 at 17:33
  • The first thing I would try is use only the latest version (`1.15` in your example) and let testing be the judge. There shouldn't be enough difference between minor versions like that to cause a problem. That may not be the best answer to your question, but [Apache Maven](http://maven.apache.org/plugins/maven-dependency-plugin/examples/resolving-conflicts-using-the-dependency-tree.html) uses a dependency tree to resolve conflicts. See [Dependency conflicts on Maven](http://stackoverflow.com/questions/5278292/dependency-conflicts-on-maven). – gknicker Jan 23 '15 at 17:36
  • @gknicker OK, I will check this out. But at the end of the day, what does Maven put at build/deploy time under your lib web app folder under Tomcat/JBoss: C 1.10 or C 1.15 or both? I mean, I don't see how Maven can auto-solve it for us, if we cannot solve it "manually". You see what I mean. – peter.petrov Jan 23 '15 at 17:38
  • @peter.petrov Yes, I see what you mean. Good question, I don't know the answer. – gknicker Jan 23 '15 at 17:42
  • 1
    Maven will pick the one closest to the root of the dependency tree - a direct dependency is preferred over a first-level transitive dependency (dep-of-a-dep), which is in turn preferred over a second-level one (dep-of-a-dep-of-a-dep). – Ian Roberts Jan 23 '15 at 17:47
  • @IanRoberts I see. So Maven may pick "the wrong" JAR too (I mean wrong from A's or from B's perspective). So yeah, what if JARs are simply incompatible at runtime?! My question here is more logical than technological. How should we in principle treat such situations (like the described one)? – peter.petrov Jan 23 '15 at 19:00

1 Answers1

0

Can suggest two solutions- 1) write your class loaders for both A and B using different versions of jar. You may place C jar files in two different folders in lib, in web app. and create objects for A and B using different class loaders. This is a little tangible approach but will work.

2) though not sure, but OSGI could be helpful.

Rahul Winner
  • 430
  • 3
  • 16