Skip to main content

Writing Java Applications that Work with Different Incompatible Versions of a Java API/Library

Posted by garysweaver on July 31, 2008 at 10:57 AM PDT

If you're a Java developer and you've been around for any length of time, you've likely run into the issue of wanting to write something that can deal with different versions of the same Java API that may be incompatible.

What got me thinking about this, is that I recently saw a forum post in the Atlassian Confluence Developer forum where someone was asking about how to get the version number of Confluence so that they could write their plugin to be compatible with different versions of Confluence that have incompatible APIs. And as background, in the past, Atlassian has been very quick to change their API (much quicker than in Apache/Apache Jakarta projects!) sometimes leaving plugin developers needing to update in order to work with the next minor version of Confluence.

Really briefly, here are some options you might want to think about in this situation:

  • Option 1: Just have different versions of your code for different versions of the API it uses. You look at most libraries and applications, and in-general, this is what people do.
  • Option 2: Try to discover classes/methods via reflection when you know that they change and/or are non-existant between versions. Discovering via reflection in certain cases is common across many open-source libraries and applications, but reflection is slow, so you really shouldn't do this unless necessary.
  • Option 3: If you have control over the library/API that is changing constantly, write a library that doesn't change as much that contains interfaces, then in the library that does change, make it dependent on the interface library. Then use Spring or the like to swap out which class or classes implement the interface(s) you are using, and then just change the Spring config (or similar) in the original application in order to use a newer version of the library that changes so much. This isn't totally as great as it sounds because you have to have control over the projects, and it requires more work.
  • Option 4: Like Option 2 except you configure which version you are using and then use reflection or some other method to get the class. If it is just a matter of generating different XML or putting together a request object to some API different, this might be ok. But in-general, this is not a very robust solution for most cases, because if it does have to use reflection to instantiate classes etc. based on that version number, and you misconfigure it, you may not know about those incompatibilities until runtime. Of course you could misconfigure things using one of the other options mentioned, but at least there you will be dealing with the nitty-gritty configuration of implementing classes and not just dealing with a version number that hides what is really going on. However, with adequate error messages, this might be ok.

I'm sure people could think of others, but maybe this will give you a jump-start thinking about this, if you haven't recently.

Related Topics >>

Comments

> there are still places out there where people are using reflection to instantiate classes a lot more than is necessary when they could be using Spring instead to instantiate a class only once Oops- I meant that there are still places where people are using reflection to instantiate classes on every method call when it's not needed. Although using Spring is not a bad thing- I just had to take-off to Target before I could double-check my comment! ;)

@evernat - In response to your comment "saying that reflection is slow is a misconception"... you should should time it sometime- even in Java 5 and 6, it isn't always acceptably fast. I have absolutely no problem with reflection's common use by Spring, Hibernate, etc. because they commonly will cache instances created by reflection. There is still some extra time needed at startup, but it is definitely a good thing. I'm not trying to put-down reflection by any means. However, all of that said- there are still places out there where people are using reflection to instantiate classes a lot more than is necessary when they could be using Spring instead to instantiate a class only once. I've run into some examples in open-source projects recently where either examples or required code for setup involved unnecessary reflection on every call, which is what I was suggesting people try to avoid. Hope that helps...

In your option 2, saying that reflection is slow is a misconception. Reflection was not always the best speed option in 2000 but since jdk 1.4 reflection speed is excellent. You can check this with google. For example, Spring or Hibernate do a lot of reflection and they are not slow because of reflection (event without classes instrumentation). Reflection is a viable option from the performance point of view.

Is this one of the problems that a system like OSGi could solve? Expose each core API as a different bundle, then write your plugin as a collection of bundles that have explicit dependencies on specific host APIs. Then let it load the right one at runtime automatically.