1

I have a java project where I use an external jar (not controlled by me). Until now whenever that a new version of that library is out, I update my project to use the more recent one, but now is required that the project uses different versions of that library.

My problem is I don't have any clue how to do that. How do I tell in java to make the imports according a version of a jar,

What I need to do:

    int versionFlag = getVersion2use();
    if(verssionFlag = 0){
           use imports from last version
    }else if(verssionFlag = 1){
          use imports from last version 1
    } else if(verssionFlag = 2){
         use imports from last version 2
    }

This is to be used at runtime!

rgomes
  • 221
  • 7
  • 20
  • Is this maven project ? – John Jun 03 '15 at 13:22
  • Do you need this flexibility at runtime or at build time? – justAbit Jun 03 '15 at 13:23
  • Quick question - you want the same code base to use different versions of the library depending on some condition? I am not sure what you're intending to do but that sounds a bit unnecessary/impractical. For example, if the next version of the API has a breaking change, you're going to have to update your code and the same code can't be used reliably for 2 different versions. If the API of the jar has not changed (but got improved) then you get the benefit by upgrading. – Praba Jun 03 '15 at 13:23
  • "but now is required that the project uses different versions of that library." Could you provide more context? Why does it need different versions of the same library? I am guessing you have dependency hell, where two libraries/frameworks you are using need different versions of the same jar? – Gimby Jun 03 '15 at 13:47
  • The project needs to support backward compatibility, I need to select which code to run, depending of the user library version choose. I need to load the imports according the version choice to guarantee that older version (more tested and in production) of the sofware runs avoiding unexpected bugs of the new library – rgomes Jun 03 '15 at 14:23
  • Sound more like you want to selectively execute different versions of the application rather than different versions of the code – Gimby Jun 03 '15 at 14:56
  • I realize that last comment may sound like its the exact same thing; I mean run different versions of the packaged application. Rather than solving this in your code, solve it BEFORE you run the application in some way. – Gimby Jun 03 '15 at 15:03

3 Answers3

2

This is usually something that a project will do at build time rather than dynamically at runtime.

That said, here's a good answer on how to add a jar to the system classloader dynamically at runtime, which is something you could work into your general logic above:

How should I load Jars dynamically at runtime?

With respect to imports, there's no way around the fact that you can't dynamically pick your imports. So if you're lucky the two versions have the same basic API. If that holds, add the jar to classloader as early as possible in your app and then develop like normal.

If the two versions have different a different API, however, then you're going to have to write some very convoluted code that tries building objects and almost ubiquitously catches all the many different class load / class incompatibility exceptions (such as ClassNotFoundException). Worse, you'll probably have to do this behind some sort of facade or factory architecture so that you can actually keep running software insulated from all these class loading shenanigans. In short, if the two have different APIs you may actually be better off writing two separate products.

Community
  • 1
  • 1
Trevor Brown
  • 169
  • 3
1

At Runtime

Classes with the same name in the same package follow a first available rule. The first one that is on the classpath is the one that is used.

You can not easily do what you want at runtime without a wrapper program to move the libraries into and out of the system classpath before the Java application is started.

A launcher script/program that dynamically builds the classpath and only includes the version you need of each library and passes it to java -cp is the only way to do what you want at runtime.

At build time

If it is at build time, then just use something like the shade plugin in Maven to build an uberjar with all the required libraries embedded in a single .jar for each of the versions. So 3 versions would be 3 separate uberjar assemblies.

Community
  • 1
  • 1
-1

If you can do it at build time, you can use a dependency manager, like Maven.

It provides you with a means to be able to select which versions of which library you use at build-time.

If you need to do this at runtime, you might need to package all libraries in your project. You can use shading (see here) to make sure you don't get import issues, because when importing different versions of libs you end up with similar imports.

Shading can help you make for example:

 com.foo.Class in jarv1
 com.foo.Class in jarv2

To become

 com.foo.v1.Class in jarv1
 com.foo.v2.Class in jarv2

This will make sure your code can still use all libs you want.

Rob Audenaerde
  • 19,195
  • 10
  • 76
  • 121
  • i did not downvote you but you basically offered 0 value answer. – John Jun 03 '15 at 13:24
  • I'm not the downvoter but your answer is not helping as such. If the OP can use Maven, then he might as well replace the existing jar with the latest one. So how is Maven helping? – Praba Jun 03 '15 at 13:25
  • OP was not clear about his knowledge of dependency management. Besides that, if he wants to do it at runtime, he needs to shade libs or else they cannot co-exist if they have the same package structure. – Rob Audenaerde Jun 03 '15 at 13:31
  • @prabugp Maven will help because it can be used to easily update versions, (automatically) stay with the latest version, and provide easy means for shading as well. – Rob Audenaerde Jun 03 '15 at 13:39
  • I understand that point (and I do know Maven btw) but I believe the OP is asking for dynamically loading the jar. Even with Maven, you statically update the pom file and rather than you downloading the jar, maven does it for you. – Praba Jun 03 '15 at 13:43