6

This sounds to me like a generic problem so I'm wondering if there is a general recommended way to deal with these situations regardless of the build / dependency management tools used (Gradle in my case). I can imagine this issue arising regardless of the build tool, even in a small project where the few dependencies are handled manually and which is simply built with Java using the jar command.

My Java project uses Velocity 1.7 so it has the Velocity 1.7 JARs in its classpath.

However this project also uses ReportNG, which depends on Velocity 1.4 (it even has the entry Class-Path: velocity-dep-1.4.jar in its manifest, plus its downloaded zip contains velocity-dep-1.4.jar and its home page explicitly mentions that velocity-dep-1.4.jar must be in the classpath).

I'm wondering how to avoid having on my classpath the JARs for both Velocity versions, which is the likely cause of strange behavior I'm seeing and which in any case doesn't sound at all like a good idea.

I'm going to try to make ReportNG use Velocity 1.7 instead of 1.4 but it won't necessarily work and I'd like to avoid doing that if there is a clean way of dealing with these situations.

SantiBailors
  • 1,596
  • 3
  • 21
  • 44
  • do you have any other jars that are unnecessary in the build path? – Jake Arnold May 19 '14 at 10:00
  • No, although I'm not clear why this matters. However I'm not sure I can say that any of those Velocity JARs are unnecessary: the 1.7 ones are needed by the project itself and the 1.4 ones are needed only by ReportNG. – SantiBailors May 19 '14 at 10:07

1 Answers1

2

While you can add both JARs to the classpath, by default Java will use first JAR it finds containing a given class, which, depending how you construct your classpath can have undesirable effects on your system.

To avoid this situation Gradle (like Maven before it) resolve dependency conflicts at build time.

With Gradle, the default dependency resolution uses the newest dependency, which in your case means Velocity 1.7.

With Maven dependency resolution is achieved by using the closest dependency to your project, which in your case, as your project declares a dependency on Velocity 1.7, means it is that version that would be used.

With both approaches, whether your system (or rather ReportNG) will work with Velocity 1.7 is down to you to test.

Nick Holt
  • 33,455
  • 4
  • 52
  • 58
  • Thanks, that helps. I'm actually in the process of trying ReportNG with Velocity 1.7 . So, since I'm using Gradle, the whole project - including its ReportNG dependency - is already using only the Velocity 1.7 JARs, which would mean that the 1.4 JARs might as well not be there at all and it wouldn't make a difference (if I understood correctly). But then I don't understand this: let's say that Velocity 1.4 has a class that is not in 1.7, and let's say that ReportNG is actually referencing that class. What would happen in such case ? – SantiBailors May 19 '14 at 10:45
  • In the case where a class is missing in Velocity 1.7 and ReportNG tries to use that class you would get a `ClassNotFoundException` at runtime. However with a good quality library like Velocity this is unlikely to be the case, though the only way to know for sure is to test, test and test some more – Nick Holt May 19 '14 at 12:04
  • Ok, so since based on your answer I have been using 1.7 only all the time, and 1.4 was ignored due to Gradle dependency resolution, I can conclude that ReportNG is fine with Velocity 1.7 (at least in the ways I've been running it until now) because I'm not getting any runtime exception. However I will keep testing as you suggest. – SantiBailors May 19 '14 at 12:46
  • I can confirm that ReportNG is working fine with Velocity 1.7 for me. – SantiBailors Jul 13 '15 at 10:01