Reputation: 2535
I am developing plugins for a platform that loads plugin classes at runtime, and this platform uses old versions of the javax.persistence API (specifically version 1.0) whereas my plugin requires version 2.1 because it uses hibernate 4.3.5.Final.
I am looking for a way to remove all the classes in the current package 'javax.persistence' and load the newer javax.peristence classes built in my plugin jar at runtime. The platform my plugin runs on is built as a single jar and has all of its dependencies (including javax.persistence) built in the jar using the shade maven plugin, and this is the same for all the dependencies for a plugin.
So is it possible to accomplish this? to be able to replace a dependency on the classpath with a newer version at runtime? If it is not possible, or very hard, I could always fork the platform, and change the pom.xml to exclude javax.peristence classes from being shaded... but that is not preferable...
EDIT: another option is to write a small script to replace the class files in the jar before deploying. At least that will make it so I wouldn't have to manually replace the classes every time I need to update the platform
thanks.
Upvotes: 2
Views: 1211
Reputation: 30995
If you need to load classes at runtime you can use:
URLClassLoader child = new URLClassLoader (myJar.toURL(), this.getClass().getClassLoader());
Class classToLoad = Class.forName ("com.MyClass", true, child);
Method method = classToLoad.getDeclaredMethod ("myMethod");
Object instance = classToLoad.newInstance ();
Object result = method.invoke (instance);
But of course this will introduce a problem controlling your jars and of course a lack of security.
I fully recommend controlling your dependencies through maven.
By the way, if you have class conflicts you always can use the very useful maven goal dependency-tree
to see what jar depends on other jar. Even if you need a deep analysis you can use dependency-analyze
.
For further details about these very useful goals you can check this link:
http://maven.apache.org/plugins/maven-dependency-plugin/plugin-info.html
EDIT: as an update to this answer you can try JCL (java class loader framework) that looks interesting. Its description says:
JCL is a configurable, dynamic and extensible custom classloader that loads java classes directly from Jar files and other sources. The motivation was to create isolated classloaders, which can be easily integrated with IoC frameworks like Spring and with web applications.
And an example:
JarClassLoader jcl = new JarClassLoader();
//Loading classes from different sources
jcl.add("myjar.jar");
jcl.add(new URL("http://myserver.com/myjar.jar"));
jcl.add(new FileInputStream("myotherjar.jar"));
jcl.add("myclassfolder/");
//Recursively load all jar files in the folder/sub-folder(s)
jcl.add("myjarlib/");
JclObjectFactory factory = JclObjectFactory.getInstance();
//Create object of loaded class
Object obj = factory.create(jcl, "mypack.MyClass");
Hope to help
Upvotes: 1