3

My Question: What is a good way to deal with two different versions of an API? (Sub-question: Is there any way to avoid classpath reference problems if you include two libraries with the same class-names?)

Description of question: I have a project that uses an API. I have spent the last few months developing for the old version and I'm about to add features for a newer version. So far as I can tell there's only one critical difference. However, I don't have the API yet (waiting on someone to get me the jar) so I can't be sure whether there are more differences.

Description of subquestion: I'm worried that there may be class reference inconsistencies between the two APIs (like I said, I don't have the jar yet to be sure).

I realize you may want some code to look at, but this is a design question, not a coding issue. I'm hoping to get some best practices out of this. Thanks!

Not a duplicate: I've looked at a few questions which may appear to be duplicates, but they didn't really address my issue :)

Community
  • 1
  • 1
kentcdodds
  • 27,113
  • 32
  • 108
  • 187
  • I don't see how .NET answers could be applied generically to a Java question, did you try searching for actually-related questions? Better info. – Dave Newton Jul 03 '12 at 12:55
  • You definitely know this already.., We use `maven` to resolve the dependency conflicts by excluding old versions and include new version to classpath. – RP- Jul 03 '12 at 12:57
  • @Rp- But OP is specifically asking about two libraries on the classpath, each with an implementation if a given class. Obviously "don't" is the best answer. – Dave Newton Jul 03 '12 at 13:02

2 Answers2

3

Avoid, or shade.

If you have full control of the classpath you can use ordering: this is brittle and non-intuitive.

If you don't, you're at the mercy of whatever is, hence shading, and its related headaches.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • 1
    I'm sorry, I've never heard of shading before, could you fill me in? – kentcdodds Jul 03 '12 at 13:02
  • 1
    @kentcdodds Basically re-packaging one of the libraries, generally as part of the build process. – Dave Newton Jul 03 '12 at 13:04
  • I must be really dumb, but I don't think I'm executing the best queries to find what you're talking about. Could you give me a link to some documentation please :) Thanks. – kentcdodds Jul 03 '12 at 13:06
  • @kentcdodds [Your specific problem, sort of](http://java.dzone.com/news/jarjar-solves-class-loading-co) (uses [jarjar](http://code.google.com/p/jarjar/)), if using Maven, see the [Maven shade plugin](http://maven.apache.org/plugins/maven-shade-plugin/), etc. – Dave Newton Jul 03 '12 at 13:13
  • I think that's the answer I'm looking for. Thanks for the help! – kentcdodds Jul 03 '12 at 13:21
  • @kentcdodds It might be, but be wary... if you're targeting the library, then it doesn't sound like it's a dependency of some *other* library--which means you can control what's on the classpath, and include only a single version. – Dave Newton Jul 03 '12 at 13:24
2

There are also classloader isolation strategies you can use. For example, if you're in a container environment (Java EE, OSGi) you can put the different versions of the libraries in different classloader contexts (i.e., different EJB jars, or different web applications) and they won't interfere with each other.

OSGi can do the same sort of thing; deploy library A.1 and A.2 into your OSGi container, and deploy project.uno (which uses A.1) and project.dos (which uses A.2) into the same JVM, and the OSGi container handles resolution of the classpaths.

Joseph Ottinger
  • 4,911
  • 1
  • 22
  • 23
  • OSGi requires retooling the app, of course, and JEE requires... well, JEE, and you have to make sure you're under the right classloader. Without knowing more about the OP's environment and retirements, I'd have a difficult time recommending either as a general-purpose solution. – Dave Newton Jul 03 '12 at 13:07
  • 1
    Agreed. Yet they're both possibilities. – Joseph Ottinger Jul 03 '12 at 13:15