Writing Java Applications that Work with Different Incompatible Versions of a Java API/Library
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.