rgomes
rgomes

Reputation: 221

How to use different version of a library at Runtime?

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!

Upvotes: 1

Views: 5540

Answers (3)

user177800
user177800

Reputation:

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.

Upvotes: 1

Trevor Brown
Trevor Brown

Reputation: 169

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.

Upvotes: 2

Rob Audenaerde
Rob Audenaerde

Reputation: 20019

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.

Upvotes: -1

Related Questions