Folks,

In the current codebase, binding.jms does not run under OSGi.

I want to fix this since I believe that it is important that all Tuscany code should be able to run under OSGi.

The problem area is the binding-jms-runtime module and the method that it uses to load the particular JMS provider.

The code involved is in the JMSResourceFactoryImpl class in org.apache.tuscany.sca.binding.jms.provider - in the getInitialContext() method.

The code here does a load of a JNDI InitialContext:


        // Load the JNDI InitialContext (will load the InitialContextFactory, 
if present)
        context = new InitialContext(props);


The (well known) problem with this under OSGi is that the InitialContext code tries to load an InitialContextFactory class, named as a text string in a properties file, using loadClass method of the ThreadContextClassLoader.

Under OSGi, this breaks since the TCCL does not typically have access rights to the bundle containing the InitialContextFactory class.

For ActiveMQ (which is our default JMS provider today), the class involved is ActiveMQInitialContextFactory which is in the activemq-core bundle/jar.

The existing Tuscany code has no "smart fix" for this situation - unlike META-INF/services style classes, for which we do have a solution.

So to get this to work under OSGi, I propose the following:

1. Change the code in getInitialContext to the following:

        ClassLoader tccl = ClassLoaderContext.setContextClassLoader(
                                JMSResourceFactoryImpl.class.getClassLoader(),
                                
ActiveMQInitialContextFactory.class.getClassLoader(),
                                Thread.currentThread().getContextClassLoader() 
);
        try {
            // Load the JNDI InitialContext (will load the 
InitialContextFactory, if present)
            context = new InitialContext(props);
        } finally
        // Restore the TCCL if we changed it
            if( tccl != null ) 
Thread.currentThread().setContextClassLoader(tccl);
        } // end try

this sets up the TCCL to enable it to load the ActiveMQInitialContextFactory 
class

2. Add a POM dependency on activemq-core

- this can be made a "provided" dependency

3. Add a package dependency to the MANIFEST.MF for package 
org.apache.activemq.jndi

- this can be made an optional dependency

        org.apache.activemq.jndi;resolution:=optional,


This change has the effect of making the jms runtime package depend on ActiveMQ - we may want to provide alternative jms runtime packages for other JMS providers at some later point, but I think we need to get the code working under OSGi right away and so this approach is a good first step.


Yours,  Mike.

Reply via email to