You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tuscany.apache.org by Mike Edwards <mi...@gmail.com> on 2010/12/09 17:19:33 UTC

[DISCUSS] Enabling binding.jms to run under OSGi

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.

Re: [DISCUSS] Enabling binding.jms to run under OSGi

Posted by Mike Edwards <mi...@gmail.com>.
Comments inline,


Yours,  Mike.
>
> Mike,
>
> The only Tuscany user I know of who uses OSGi and the JMS binding does
> it by having their own custom JMSResourceFactory impl.

I don't think that makes a good story.  So in order to use OSGi + JMS users are required to swrite 
their own implementations of JMSResourceFactory.  I don't want to see OSGi users being treated as 
second class citizens.

> If its a
> problem I'd be happy to help add a new module to plug in a custom
> JMSResourceFactory as that seems a much better approach than adding
> ActiveMQ specific code to the current module.

Plugging in a custom resource factory is not the objective.  Having Tuscany binding.jms work "out of 
the box" running under OSGi is the objective.

>
> Another approach that might be worth looking at to help get started
> would be to use a JMS broker running as a separate process to the OSGi
> container. That way to start with you just have to deal with getting
> Tuscany running in OSGi without needing to deal with how to get JMS
> working in OSGi. There's an itest that shows doing that:
> testing/itest/jms/externalBroker.

I'm not sure that is relevant to the main task here.

> You still have the issue of loading
> the InitialContextFactory class, but if the approach suggested by
> Ramond works then it sounds like thats solvable too.

Unfortunately, Raymond's suggestion does not seem to work - I tried a number of ways with the code 
that Raymond suggested and I could not get it to work.

>
>     ...ant
>




Re: [DISCUSS] Enabling binding.jms to run under OSGi

Posted by ant elder <an...@gmail.com>.
On Fri, Dec 10, 2010 at 1:12 PM, Mike Edwards
<mi...@gmail.com> wrote:
>>
>> I've added a new module, binding-jms-runtime-activemq, which has a new
>> ActiveMQ specific JMSResourceFactory impl that overrides the JMS
>> binding default one when both modules are used. Would you use that for
>> adding the ActiveMQ specific code?
>>
>>    ...ant
>>
> Ant,
>
> That misses the point somewhat.  My goal here is to enable JMS to run when
> using OSGi.  So an "ActiveMQ" module does not seem appropriate to me.  The
> fact that the initial version of OSGi enabled code uses ActiveMQ when
> running under OSGi is simply a first step - I don't see why the OSGi code
> should not use other JMS providers (assuming they run under OSGi too)
>
>
> Yours,  Mike.
>
>

Ok, would it help to rename the module to binding-jms-runtime-osgi?

The changes you've just done have put a hard dependency on ActiveMQ
into the JMS binding. Thats not right, and if its really necessary
then it needs to be in a separate module just has been done with
numerous other modules in Tuscany.

   ...ant

Re: [DISCUSS] Enabling binding.jms to run under OSGi

Posted by Mike Edwards <mi...@gmail.com>.
>
> I've added a new module, binding-jms-runtime-activemq, which has a new
> ActiveMQ specific JMSResourceFactory impl that overrides the JMS
> binding default one when both modules are used. Would you use that for
> adding the ActiveMQ specific code?
>
>     ...ant
>
Ant,

That misses the point somewhat.  My goal here is to enable JMS to run when using OSGi.  So an 
"ActiveMQ" module does not seem appropriate to me.  The fact that the initial version of OSGi 
enabled code uses ActiveMQ when running under OSGi is simply a first step - I don't see why the OSGi 
code should not use other JMS providers (assuming they run under OSGi too)


Yours,  Mike.


Re: [DISCUSS] Enabling binding.jms to run under OSGi

Posted by ant elder <an...@gmail.com>.
On Fri, Dec 10, 2010 at 10:13 AM, ant elder <an...@gmail.com> wrote:
> On Fri, Dec 10, 2010 at 10:00 AM, Mike Edwards
> <mi...@gmail.com> wrote:
>>> Mike,
>>>
>>> The only Tuscany user I know of who uses OSGi and the JMS binding does
>>> it by having their own custom JMSResourceFactory impl. If its a
>>> problem I'd be happy to help add a new module to plug in a custom
>>> JMSResourceFactory as that seems a much better approach than adding
>>> ActiveMQ specific code to the current module.
>>>
>>> Another approach that might be worth looking at to help get started
>>> would be to use a JMS broker running as a separate process to the OSGi
>>> container. That way to start with you just have to deal with getting
>>> Tuscany running in OSGi without needing to deal with how to get JMS
>>> working in OSGi. There's an itest that shows doing that:
>>> testing/itest/jms/externalBroker. You still have the issue of loading
>>> the InitialContextFactory class, but if the approach suggested by
>>> Ramond works then it sounds like thats solvable too.
>>>
>>>    ...ant
>>>
>> Ant,
>>
>> Perhaps you're right and ultimately we shall need to create a whole new
>> module binding-jms-runtime-osgi (or something like that).
>>
>> However, I'm not sure that we yet know what needs to be in that module -
>> we're just getting this working under OSGi for the first time and I can't
>> predict what might need tweaking/changing.
>>
>> So for the moment, I'll commit an initial set of changes that do get things
>> working under OSGi while still getting us a clean build when not running
>> under OSGi.  We can iterate away from that.
>> The amount of changed code is not large.
>>
>>
>> Yours,  Mike.
>>
>
> Ok fine, i'll help by putting that into a separate ActiveMQ specific
> module then.
>
>   ...ant
>

I've added a new module, binding-jms-runtime-activemq, which has a new
ActiveMQ specific JMSResourceFactory impl that overrides the JMS
binding default one when both modules are used. Would you use that for
adding the ActiveMQ specific code?

   ...ant

Re: [DISCUSS] Enabling binding.jms to run under OSGi

Posted by ant elder <an...@gmail.com>.
On Fri, Dec 10, 2010 at 10:00 AM, Mike Edwards
<mi...@gmail.com> wrote:
>> Mike,
>>
>> The only Tuscany user I know of who uses OSGi and the JMS binding does
>> it by having their own custom JMSResourceFactory impl. If its a
>> problem I'd be happy to help add a new module to plug in a custom
>> JMSResourceFactory as that seems a much better approach than adding
>> ActiveMQ specific code to the current module.
>>
>> Another approach that might be worth looking at to help get started
>> would be to use a JMS broker running as a separate process to the OSGi
>> container. That way to start with you just have to deal with getting
>> Tuscany running in OSGi without needing to deal with how to get JMS
>> working in OSGi. There's an itest that shows doing that:
>> testing/itest/jms/externalBroker. You still have the issue of loading
>> the InitialContextFactory class, but if the approach suggested by
>> Ramond works then it sounds like thats solvable too.
>>
>>    ...ant
>>
> Ant,
>
> Perhaps you're right and ultimately we shall need to create a whole new
> module binding-jms-runtime-osgi (or something like that).
>
> However, I'm not sure that we yet know what needs to be in that module -
> we're just getting this working under OSGi for the first time and I can't
> predict what might need tweaking/changing.
>
> So for the moment, I'll commit an initial set of changes that do get things
> working under OSGi while still getting us a clean build when not running
> under OSGi.  We can iterate away from that.
> The amount of changed code is not large.
>
>
> Yours,  Mike.
>

Ok fine, i'll help by putting that into a separate ActiveMQ specific
module then.

   ...ant

Re: [DISCUSS] Enabling binding.jms to run under OSGi

Posted by Mike Edwards <mi...@gmail.com>.
> Mike,
>
> The only Tuscany user I know of who uses OSGi and the JMS binding does
> it by having their own custom JMSResourceFactory impl. If its a
> problem I'd be happy to help add a new module to plug in a custom
> JMSResourceFactory as that seems a much better approach than adding
> ActiveMQ specific code to the current module.
>
> Another approach that might be worth looking at to help get started
> would be to use a JMS broker running as a separate process to the OSGi
> container. That way to start with you just have to deal with getting
> Tuscany running in OSGi without needing to deal with how to get JMS
> working in OSGi. There's an itest that shows doing that:
> testing/itest/jms/externalBroker. You still have the issue of loading
> the InitialContextFactory class, but if the approach suggested by
> Ramond works then it sounds like thats solvable too.
>
>     ...ant
>
Ant,

Perhaps you're right and ultimately we shall need to create a whole new module 
binding-jms-runtime-osgi (or something like that).

However, I'm not sure that we yet know what needs to be in that module - we're just getting this 
working under OSGi for the first time and I can't predict what might need tweaking/changing.

So for the moment, I'll commit an initial set of changes that do get things working under OSGi while 
still getting us a clean build when not running under OSGi.  We can iterate away from that.
The amount of changed code is not large.


Yours,  Mike.

Re: [DISCUSS] Enabling binding.jms to run under OSGi

Posted by ant elder <an...@gmail.com>.
On Fri, Dec 10, 2010 at 6:56 AM, Mike Edwards
<mi...@gmail.com> wrote:
> Ant,
>
> Comments inline:
>>
>> I'd guess that the Tuscany JMS binding __does__ already work under
>> OSGi, but the problem is how do you configure an OSGi container to
>> provided a JNDI environment.
>
> The Tuscany JMS binding does NOT work under OSGi.  I don't find this
> surprising since it's clearly never until now been tested in the OSGi
> environment.  But it isn't just a question of getting JNDI to work.
>
> However, the issue of getting JNDI to work under OSGi is a serious one, much
> debated.
>
>>
>> We use ActiveMQ for the testcases but the JMS binding uses just
>> standard JavaEE APIs and JNDI lookups so it works with any JavaEE JNDI
>> environment. Along with standalone ActiveMQ Tuscany also works with
>> Tomcat, WebSphere, JBoss, Glassfish, - or any JavaEE compliant
>> AppServer - and it uses the AppServer's defined JMS resources. We have
>> users using that capability and its function i think we should try
>> hard to keep working.
>
> Agreed - but we also have users who run under OSGi - clearly so far they
> have either not been using JMS or they've had to re-engineer our code.
>
>>
>> That code in (1) would fail if ActiveMQ isn't available so it would
>> need to handle the class not being found or else be in a separate
>> module. The Tuscany JMSResourceFactory is one of the JMS binding plug
>> points so it could easily be a new separate module for an ActiveMQ
>> specific JMSResourceFactory.
>
> I want to get something that works now.  A separate module is a possibility
> for the future, but I don't want to go down that road yet.  Code that
> attempts to load the ActiveMQ class and handles any failure sounds fine to
> me as a solid first step. I users want OSGi + non-ActiveMQ JMS then I am
> sure they will shout for it & we can accommodate it.
>
>>
>> I do wonder though if there are more standard ways to do JNDI in OSGi,
>> other enterprise OSGi things must already have a way of doing it. I
>> don't know anything about it but a google turns up:
>> http://incubator.apache.org/aries/jndiproject.html
>
> The trouble with this is that the OSGi EEG has only recently defined their
> spec for JNDI under OSGi and you're very limited wrt OSGi runtimes that
> implement that spec (and a host of other EEG defined specs).  Aries is one
> of the few.  I'm not convinced that I want to tie Tuscany OSGi support to
> Aries just yet.
>
>>
>>    ...ant
>>
>
>

Mike,

The only Tuscany user I know of who uses OSGi and the JMS binding does
it by having their own custom JMSResourceFactory impl. If its a
problem I'd be happy to help add a new module to plug in a custom
JMSResourceFactory as that seems a much better approach than adding
ActiveMQ specific code to the current module.

Another approach that might be worth looking at to help get started
would be to use a JMS broker running as a separate process to the OSGi
container. That way to start with you just have to deal with getting
Tuscany running in OSGi without needing to deal with how to get JMS
working in OSGi. There's an itest that shows doing that:
testing/itest/jms/externalBroker. You still have the issue of loading
the InitialContextFactory class, but if the approach suggested by
Ramond works then it sounds like thats solvable too.

   ...ant

Re: [DISCUSS] Enabling binding.jms to run under OSGi

Posted by Mike Edwards <mi...@gmail.com>.
Ant,

Comments inline:
>
> I'd guess that the Tuscany JMS binding __does__ already work under
> OSGi, but the problem is how do you configure an OSGi container to
> provided a JNDI environment.

The Tuscany JMS binding does NOT work under OSGi.  I don't find this surprising since it's clearly 
never until now been tested in the OSGi environment.  But it isn't just a question of getting JNDI 
to work.

However, the issue of getting JNDI to work under OSGi is a serious one, much debated.

>
> We use ActiveMQ for the testcases but the JMS binding uses just
> standard JavaEE APIs and JNDI lookups so it works with any JavaEE JNDI
> environment. Along with standalone ActiveMQ Tuscany also works with
> Tomcat, WebSphere, JBoss, Glassfish, - or any JavaEE compliant
> AppServer - and it uses the AppServer's defined JMS resources. We have
> users using that capability and its function i think we should try
> hard to keep working.

Agreed - but we also have users who run under OSGi - clearly so far they have either not been using 
JMS or they've had to re-engineer our code.

>
> That code in (1) would fail if ActiveMQ isn't available so it would
> need to handle the class not being found or else be in a separate
> module. The Tuscany JMSResourceFactory is one of the JMS binding plug
> points so it could easily be a new separate module for an ActiveMQ
> specific JMSResourceFactory.

I want to get something that works now.  A separate module is a possibility for the future, but I 
don't want to go down that road yet.  Code that attempts to load the ActiveMQ class and handles any 
failure sounds fine to me as a solid first step. I users want OSGi + non-ActiveMQ JMS then I am sure 
they will shout for it & we can accommodate it.

>
> I do wonder though if there are more standard ways to do JNDI in OSGi,
> other enterprise OSGi things must already have a way of doing it. I
> don't know anything about it but a google turns up:
> http://incubator.apache.org/aries/jndiproject.html

The trouble with this is that the OSGi EEG has only recently defined their spec for JNDI under OSGi 
and you're very limited wrt OSGi runtimes that implement that spec (and a host of other EEG defined 
specs).  Aries is one of the few.  I'm not convinced that I want to tie Tuscany OSGi support to 
Aries just yet.

>
>     ...ant
>


Re: [DISCUSS] Enabling binding.jms to run under OSGi

Posted by ant elder <an...@gmail.com>.
On Thu, Dec 9, 2010 at 4:19 PM, Mike Edwards
<mi...@gmail.com> wrote:
> 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.
>

I'd guess that the Tuscany JMS binding __does__ already work under
OSGi, but the problem is how do you configure an OSGi container to
provided a JNDI environment.

We use ActiveMQ for the testcases but the JMS binding uses just
standard JavaEE APIs and JNDI lookups so it works with any JavaEE JNDI
environment. Along with standalone ActiveMQ Tuscany also works with
Tomcat, WebSphere, JBoss, Glassfish, - or any JavaEE compliant
AppServer - and it uses the AppServer's defined JMS resources. We have
users using that capability and its function i think we should try
hard to keep working.

That code in (1) would fail if ActiveMQ isn't available so it would
need to handle the class not being found or else be in a separate
module. The Tuscany JMSResourceFactory is one of the JMS binding plug
points so it could easily be a new separate module for an ActiveMQ
specific JMSResourceFactory.

I do wonder though if there are more standard ways to do JNDI in OSGi,
other enterprise OSGi things must already have a way of doing it. I
don't know anything about it but a google turns up:
http://incubator.apache.org/aries/jndiproject.html

   ...ant

Re: [DISCUSS] Enabling binding.jms to run under OSGi

Posted by Simon Laws <si...@googlemail.com>.
On Fri, Dec 10, 2010 at 9:08 AM, Mike Edwards
<mi...@gmail.com> wrote:
> On 09/12/2010 19:02, Mike Edwards wrote:
>>
>> On 09/12/2010 17:37, Raymond Feng wrote:
>>>
>>> Hi,
>>>
>>> Maybe you can try this:
>>>
>>> ServiceDiscovery.getServiceDeclaration("/"
>>>
>>> +contextFactoryClassName+".class").loadClass(contextFactoryClassName).getClassLoader();
>>>
>>> getServiceDeclaration() finds the OSGi entry for the class file.
>>>
>>> Thanks,
>>> Raymond
>>
>> Raymond,
>>
>> Thanks for the suggestion, which I take to be a way of getting away from
>> making the
>> binding-jms-runtime module formally depend on the ActiveMQ InitialContext
>> class.
>>
>> I then assume that the code would have to go fetch the
>> contectFactoryClassName by reading the
>> properties file itself (ie the same one that the InitialContext JNDI code
>> reads when it creates the
>> InitialContext)? It does not do this today, but clearly it could be made
>> to do this.
>>
>> One other question is how efficient this approach would be - since the
>> ActiveMQ
>> InitialContextFactory class is NOT defined as a META-IF/services service,
>> does this mean that the
>> getServiceDeclaration() method above would necessarily go search ALL of
>> the bundles loaded, or is it
>> cleverer than that?
>>
>>
>> Yours, Mike.
>
> Raymond,
>
> An update.
>
> The code above does not work.  It does not find the InitialContextFactory.
>
> I think this is simply because the InitialContextFactory is not declared in
> META-INF/services.  The loading process for this stuff does not follow that
> pattern.
>
>
> Yours,  Mike.
>

If we find that, after suitable experimentation with the various
suggestions here, we have to have ActiveMQ specific code then having
it in an ActiveMQ specific module would seem to follow the pattern
we've used for other extensions.

Simon

-- 
Apache Tuscany committer: tuscany.apache.org
Co-author of a book about Tuscany and SCA: tuscanyinaction.com

Re: [DISCUSS] Enabling binding.jms to run under OSGi

Posted by Mike Edwards <mi...@gmail.com>.
On 09/12/2010 19:02, Mike Edwards wrote:
> On 09/12/2010 17:37, Raymond Feng wrote:
>> Hi,
>>
>> Maybe you can try this:
>>
>> ServiceDiscovery.getServiceDeclaration("/"
>> +contextFactoryClassName+".class").loadClass(contextFactoryClassName).getClassLoader();
>>
>> getServiceDeclaration() finds the OSGi entry for the class file.
>>
>> Thanks,
>> Raymond
> Raymond,
>
> Thanks for the suggestion, which I take to be a way of getting away from making the
> binding-jms-runtime module formally depend on the ActiveMQ InitialContext class.
>
> I then assume that the code would have to go fetch the contectFactoryClassName by reading the
> properties file itself (ie the same one that the InitialContext JNDI code reads when it creates the
> InitialContext)? It does not do this today, but clearly it could be made to do this.
>
> One other question is how efficient this approach would be - since the ActiveMQ
> InitialContextFactory class is NOT defined as a META-IF/services service, does this mean that the
> getServiceDeclaration() method above would necessarily go search ALL of the bundles loaded, or is it
> cleverer than that?
>
>
> Yours, Mike.
Raymond,

An update.

The code above does not work.  It does not find the InitialContextFactory.

I think this is simply because the InitialContextFactory is not declared in META-INF/services.  The 
loading process for this stuff does not follow that pattern.


Yours,  Mike.

Re: [DISCUSS] Enabling binding.jms to run under OSGi

Posted by Mike Edwards <mi...@gmail.com>.
On 09/12/2010 17:37, Raymond Feng wrote:
> Hi,
>
> Maybe you can try this:
>
> ServiceDiscovery.getServiceDeclaration("/"
> +contextFactoryClassName+".class").loadClass(contextFactoryClassName).getClassLoader();
>
> getServiceDeclaration() finds the OSGi entry for the class file.
>
> Thanks,
> Raymond
Raymond,

Thanks for the suggestion, which I take to be a way of getting away from making the 
binding-jms-runtime module formally depend on the ActiveMQ InitialContext class.

I then assume that the code would have to go fetch the contectFactoryClassName by reading the 
properties file itself (ie the same one that the InitialContext JNDI code reads when it creates the 
InitialContext)?  It does not do this today, but clearly it could be made to do this.

One other question is how efficient this approach would be - since the ActiveMQ 
InitialContextFactory class is NOT defined as a META-IF/services service, does this mean that the
getServiceDeclaration() method above would necessarily go search ALL of the bundles loaded, or is it 
cleverer than that?


Yours,  Mike.

Re: [DISCUSS] Enabling binding.jms to run under OSGi

Posted by Raymond Feng <cy...@gmail.com>.
Hi,

Maybe you can try this:

ServiceDiscovery.getServiceDeclaration("/" +contextFactoryClassName+".class").loadClass(contextFactoryClassName).getClassLoader();

getServiceDeclaration() finds the OSGi entry for the class file.

Thanks,
Raymond
________________________________________________________________ 
Raymond Feng
rfeng@apache.org
Apache Tuscany PMC member and committer: tuscany.apache.org
Co-author of Tuscany SCA In Action book: www.tuscanyinaction.com
Personal Web Site: www.enjoyjava.com
________________________________________________________________

On Dec 9, 2010, at 8:19 AM, Mike Edwards wrote:

> 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.