2

I'm writing a multi-vendor JMS adapter, and some silly licensing issues have thrown up the need for a cunning classloader solution/hack - it isn't going to be pretty, but I'd love to hear some ingenious ideas from expert classloader hackers out there...

The architecture is simple - the adapter has all its code in the system classloader, and makes heavy use of interfaces from Sun's J2EE javax.jms.jar, and then loads individual JMS providers' implementations of those interfaces in child URLClassLoaders based on classpath info it loads from some XML config files.

This all worked fine until we realised that the Sun's J2EE JMS jar is governed by a really annoying license that prevents us redistributing it (even though all it contains are industry-standard interfaces!) so we can't just put it on the system classpath along with our code out of the box. But the end-user experience is going to be very rubbish if customers are forced to find and download the jar from the Sun website then copy it to the right place in our installation just to get it working. It seems a shame to force such an irritation on customers given that the JMS provider implementations that we're loading necessarily have all those interfaces already loaded in our own JVM - the only problem is that they're in the provider-specific child classloaders which means they're not accessible in the parent/system classloader where all the vendor-neutral adapter code gets loaded.

So I'd love to hear any clever ideas for solving this (if it's possible!).

e.g. I wondered about trying to load our main classes in a customized urlclassloader subclass rather than using the system classloader (although that would be quite a pain given we would have to reproduce the effect of our existing MANIFEST.MF classpath references) and giving that classloader a reference to one of the child classloaders (once we've parsed our XML configuration) so it can load the "javax.jms.*" interfaces (only) from the child (subverting the normal parent-first policy, and ignoring the vendor-specific classes in the same jar which must not be loaded in the parent). I'm wondering if this is likely to be workable and if anyone has any pointers. I've noticed that some of the adapter classes in the main CL load correctly despite having methods that reference the missing JMS interfaces (but obviously fail when those methods are called) - am I righting thinking that if the CL that contained those classes could be provided with access to the JMS interfaces by the time such methods were called (but after the class was loaded) then it would work? (or is it too late already...)

(FYI I already spotted two related stackoverflow posts which give some useful context but don't fully help with this specified problem: How do you change the CLASSPATH within Java? and How do I create a parent-last / child-first ClassLoader in Java, or How to override an old Xerces version that was already loaded in the parent CL?)

Thanks so much for helping me with this! :)

Community
  • 1
  • 1
Ben Spiller
  • 477
  • 4
  • 12

1 Answers1

0

The Apache Geronimo project has JAR files for the javax.jms API that you can use instead of the ones from Sun. They are licensed under the ASL and can be redistributed freely.

Andreas Veithen
  • 8,868
  • 3
  • 25
  • 28
  • I'll have to check with our legal people that it's ok to grab just the jms jars from the Geronimo project, but from my reading of the apache license it looks like you're right and it should be fine. Thanks! – Ben Spiller Jan 15 '13 at 12:40