4
votes

I have an OSGI application with Bundles requiring 2 version of IBM MQSeries : 6.0.2 and 7.0.1. We installed the following IBM MQ Bundles (just mentionning the main ones)

  • com.ibm.mq.osgi.client_6.0.2.5.jar
  • com.ibm.msg.client.osgi.wmq_7.0.1.5.jar

We defined our 2 Bundles to Require-Bundle as follows (yes I know, we should use import-package ;-)) Bundle A Require-Bundle: com.ibm.msg.client.osgi.wmq;bundle-version="7.0.1"

Bundle B Require-Bundle: com.ibm.mq.osgi.client;bundle-version="[6.0.2,7.0.0)"

We define additionally org.osgi.framework.bootdelegation=javax.*. No buddy class loading, no Dynamic Class loading.

Now, when Bundle A loads the com.ibm.mq.jms.MQQueueConnectionFactory using

final MQQueueConnectionFactory connectionFactory = new MQQueueConnectionFactory();

I would expect Equinox to load the class from the Bundle com.ibm.msg.client.osgi.wmq_7.0.1.5. This is NOT the case !?!?? The MQQueueConnectionFactory is loaded from Bundle com.ibm.mq.osgi.client_6.0.2.5 !!

As consequence, Bundle A is using MQ 6.0.2.5..

Setting some Equinox Debug options, I can see the following :

Bundle id 56 == com.ibm.mq.osgi.client_6.0.2.5
Bundle id 53 == com.ibm.msg.client.osgi.jms.prereq_7.0.1.5

[...]
BundleLoader[A_1.1.3].loadBundleClass(com.ibm.mq.jms.MQQueueConnectionFactory)
BundleLoader[com.ibm.mq.osgi.client_6.0.2.5].findLocalClass(com.ibm.mq.jms.MQQueueConnectionFactory)
BundleClassLoader[PATH/org.eclipse.osgi/bundles/56/1/.cp/com.ibm.mq.jar].findClassImpl(com.ibm.mq.jms.MQQueueConnectionFactory)
BundleClassLoader[PATH/org.eclipse.osgi/bundles/56/1/.cp/com.ibm.mqjms.jar].findClassImpl(com.ibm.mq.jms.MQQueueConnectionFactory)
  about to read 11659 bytes from com/ibm/mq/jms/MQQueueConnectionFactory.class
  read 11659 bytes from PATH/org.eclipse.osgi/bundles/56/1/.cp/com.ibm.mqjms.jar/com/ibm/mq/jms/MQQueueConnectionFactory.class
  defining class com.ibm.mq.jms.MQQueueConnectionFactory
[...]

The "funny" part being that the javax.jms.* classes are loaded from com.ibm.msg.client.osgi.jms.prereq_7.0.1.5

BundleClassLoader[com.ibm.mq.osgi.client_6.0.2.5].loadClass(javax.jms.QueueConnectionFactory)
BundleLoader[com.ibm.mq.osgi.client_6.0.2.5].loadBundleClass(javax.jms.QueueConnectionFactory)
BundleLoader[com.ibm.msg.client.osgi.jms.prereq_7.0.1.5].findLocalClass(javax.jms.QueueConnectionFactory)
BundleClassLoader[PATH/org.eclipse.osgi/bundles/53/1/.cp/jms.jar].findClassImpl(javax.jms.QueueConnectionFactory)
  about to read 371 bytes from javax/jms/QueueConnectionFactory.class
  read 371 bytes from /opt/fxportal/FXMB/application/configuration/org.eclipse.osgi/bundles/53/1/.cp/jms.jar/javax/jms/QueueConnectionFactory.class
  defining class javax.jms.QueueConnectionFactory
BundleLoader[com.ibm.msg.client.osgi.jms.prereq_7.0.1.5] found local class javax.jms.QueueConnectionFactory

IMHO, this has to do with the org.osgi.framework.bootdelegation setting and the fact that the 7.0.1.5 JMS prereq occurs before the 6.0.2.5 one.

Can someone explains the Bundle Class Loader behaviour ?? Why do Equinox wires the bundle A this way ?? And how can I achieve the expected behaviour ??

Bundle B is working as expected...

2

2 Answers

0
votes

Don't if this is a valid answer but try using this format when defining the dependency in BUndle A version="[7.0.1,7.0.1]" which denotes a strict version range. Also worse case if you're still having issues can you can you load the class directly from the Bundle by doing Platform.getBundle("com.ibm.msg.client.osgi.wmq").loadClass("com.myclass")?

0
votes

I faced similar situation when I use do OSGi related coding in IDE. This wiring done by your IDE, is wrong. It wires the class from com.ibm.mq.osgi.client_6.0.2.5 while you expect it to wire the same class of com.ibm.msg.client.osgi.wmq_7.0.1.5 . The same problem is happening when in the second issue you talked about. You can check this by finding com.ibm.mq.jms.MQQueueConnectionFactory class where IDE using it. ( You can use Ctrl + Mouse click to see which version is wired ).