views:

188

answers:

4

In my Java project I'm using two different frameworks (let's say A.jar and B.jar) and both of them require one common framework (let's say Log4j.jar) but in two different versions. How it is treated by Java if framework A needs Log4J v1.1 and B needs Log4j v1.2? Will it cause some kind of conflict/error or will by somehow (how?) resolved?

If it will not cause conflict/error (my project can be compiled and run) - can I use any version of Log4j myself in this project? Or am I forced to select lower / higher version number of Log4j?

Update: to be more specific... What if some part of Log4j API changed in v1.2 (let's say one single method doIt() signature changed) and both A and B call doIt. What will happend? Will my project run? Will it crash on first use of doIt? What version of Log4j I must put on classpath - v1.2 or both?

+10  A: 

In a flat class loading scheme, there is no library versioning support. You need to use the most recent version of the library and remove other versions from the classpath.

Some frameworks, like OSGi, provide mechanisms for handling these cases, but it isn't clear that you're relying on a plug-in framework.


Edit:

What if some part of Log4j API changed in v1.2 (let's say one single method doIt() signature changed) and both A and B call doIt. What will happen? Will my project run? Will it crash on first use of doIt?

A call relying on a signature that is not present will likely result in a NoSuchMethodError. This probably will not happen until the method is invoked. Other errors may occur if other mechanisms rely on the signature (e.g. class inheritance).

What version of Log4j I must put on classpath - v1.2 or both?

Making two versions of a library on the classpath will just result in one set of classes being loaded randomly. The behaviour will be undefined, but could potentially result in all sorts of unpleasant errors and exceptions.

McDowell
+3  A: 

If your lucky picking one version of the third party jar will just work. In the end one needs a container that understands and enables versioning of components all to coexist, something like OSGI.

mP
A: 

Although not recommended but you can use both versions. Put each version in a place where only that framework can see.

The optimal solution will be to get the last versions of both A and B, where both use the last common libraries

medopal
How would you suggest one might achieve this?
Buhb
You could theoretically do this with some manual ClassLoader contortions; instantiate classes from A and B in separate classloaders, which can each only see the relevant version of the library. In practice this would be so annoying to implement and maintain that it's not really *feasible*.
Andrzej Doyle
I have made it once using a Maven plugin, not sure what was it. It's not that complicated to make, but as i said its not recommended. It will be a disaster for the developer after you.
medopal
Will it result in a classloader hack like the one Andzej mentioned or is it centered around some other idea?
Buhb
+3  A: 

Java doesn't natively support the management of multiple versions of the same piece of code, that is, you can only use at most one version within the same JVM (with the default class loader). However, checkout question 1705720, which has several answers pointing out possible ways of achieving that (OSGi or custom class loaders).

But I doubt it worth the trouble as multiple log4j versions are not required by your code directly. In you case, I'd suggest to start from using the newer log4j version (v1.2) first and verify if it would cause any problem for framework A. If it does cause conflict, then fall-back to log4j v1.1 and verify again. If you really are out of luck, then you need to get your hands dirty...

Update: for you specific description, there's no way of using either log4j v1.1 or v1.2, as framework A and B each require different signature. You have to roll your own version of any of log4j or framework A, or B.

bryantsai
What does it mean "there's no way" - what exactly will happen if I try to? Will it not compile? Will it crash when run - when loading or later (on first intermediate use of method doIt)?
WildWezyr
say you put log4j-1.1.jar;log4j-1.2.jar in your class path in that sequence, the class (version) from log4j-1.1.jar would be used. class searching would stopped as long as it finds one. so since v1.1 is used, whatever code expecting the signature of log4j v1.2 would have problem (method not found).
bryantsai