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 2009/08/04 14:59:22 UTC

[2.x] Classloading Failures running under OSGi with recent code

Folks,

In the past 2 days, I have run into classloading failures with both the BPEL runtime module and with 
the Axis2 WS Binding module.

Since these failures did not occur in code previously, I assume that there has been some significant 
change in the handling of classloaders in the 2.x stream recently.  I'd be grateful if someone could 
explain what changes have been made.  I'd also like to pose the question as to why the failures have 
not been picked up by any testcases?

The problem appears to be with 3rd party code that use the Thread Context ClassLoader to load 
classes.  The symptom is that we get class not found errors since under OSGi the bulk of our code is 
loaded with OSGi classloaders and the TCCL in the recent builds seems to be the app class loader.

I fixed the BPEL code by forcing the TCCL to be the OSGI Bundle ClassLoader used for loading the 
BPEL runtime module classes, in EmbeddedODEServer.init().

I fixed the Axis client code by a similar means of forcing the TCCL to be the OSGi Bundle 
ClassLoader, in Axis2ServiceClient.createServiceClient().


Yours,  Mike.

Re: [2.x] Classloading Failures running under OSGi with recent code

Posted by Raymond Feng <en...@gmail.com>.
Let's assume the legacy code use XYZFactory.newInstance() method (without 
passing in an explicit class loader) to discover the service provider, for 
example, XMLInputFactory.newInstance(). Most of the factories use the 
following code:

        // First try the Context ClassLoader
        ClassLoader cl = ss.getContextClassLoader();
        if (cl != null) {
            is = ss.getResourceAsStream(cl, serviceId);

            // If no provider found then try the current ClassLoader
            if (is == null) {
                cl = FactoryFinder.class.getClassLoader();
                is = ss.getResourceAsStream(cl, serviceId);
            }
        } else {
            // No Context ClassLoader, try the current ClassLoader
            cl = FactoryFinder.class.getClassLoader();
            is = ss.getResourceAsStream(cl, serviceId);
        }

Two classloaders are involved here: TCCL and the classloader for the service 
interface (FactoryFinder.class.getClassLoader()).

In an OSGi environment, TCCL is not reliable. For Equinox, it uses a 
ContextFinder to find the closest class that is loaded by an OSGi bundle 
from the stack.

Let's now look at the three cases as you pointed out. You are missing 
another player where the XYZFactory.newInstance is called. The following 
analysis assumes XYZFactory.newInstance is called in Bundle X. Please note 
all Tuscany's own bundles use an OSGi aware service discovery  instead of 
XYZFactory.newInstance().

> 1) API is in Bundle A and Provider is in Bundle B, both bundles being 
> "bundle-ized" by Tuscany code
>
If the TCCL in Bundle X is not set or it cannot find the 
META-INF/services/<SPI> resource, A can find the META-INF/services/<SPI> via 
the gateway bundle and A can also load the provider class as A has 
"DynamicImport-Package: *" and B exports the provider class. If TCCL is X's 
classloader and X is generated by Tuscany too, it can see the provider in B 
too.

> 2) API is in the JDK (eg javax.xml.xpath) and Provider is in Bundle C, 
> where C is being "bundle-ized" by Tuscany code
Without help from the TCCL, JDK cannot find the provider in bundle C. Then 
the default provider from the JDK is used. We can set up the TCCL to be the 
classloader of Bundle X or tuscany-extensibility-equinox 
(ServiceDiscovery.getInstance().getContextClassLoader()).

>
> 3) API is in Bundle D, which already has an OSGi MANIFEST.MF and Provider 
> is in Bundle E, which also already has an OSGi MANIFEST.MF (ie both are 
> already bundles)

If both bundles are non-Tuscany bundles, D either has its own OSGi-friendly 
way to discover the provider in E, for example, using OSGi service registry 
or a similar mechanism as Tuscany does in EquinoxServiceDiscover. If D is 
not handling that by itself, we will have to set up the TCCL as 2).

Thanks,
Raymond
--------------------------------------------------
From: "Mike Edwards" <mi...@gmail.com>
Sent: Friday, August 07, 2009 12:36 PM
To: <de...@tuscany.apache.org>
Subject: Re: [2.x] Classloading Failures running under OSGi with recent code

> Raymond,
>
> Is there a fuller explanation of how your new design will work?
>
> In particular, I'd like to understand how this will work for API/Provider 
> combinations using the META-INF\services pattern where:
>
> 1) API is in Bundle A and Provider is in Bundle B, both bundles being 
> "bundle-ized" by Tuscany code
>
> 2) API is in the JDK (eg javax.xml.xpath) and Provider is in Bundle C, 
> where C is being "bundle-ized" by Tuscany code
>
> 3) API is in Bundle D, which already has an OSGi MANIFEST.MF and Provider 
> is in Bundle E, which also already has an OSGi MANIFEST.MF (ie both are 
> already bundles)
>
>
> Yours,  Mike.
>
> PS One of the recent code changes (and I have not pinpointed which one(s)) 
> have caused implementation-bpel-runtime to stop working because the Saxon 
> provider for javax.xml.xpath.XPathFactory is no longer being loaded...  I 
> believe that it is following pattern 1) above...
>
> Raymond Feng wrote:
>> More comments inline.
>>
>> Thanks,
>> Raymond
>> --------------------------------------------------
>> From: "Mike Edwards" <mi...@gmail.com>
>> Sent: Tuesday, August 04, 2009 2:36 PM
>> To: <de...@tuscany.apache.org>
>> Subject: Re: [2.x] Classloading Failures running under OSGi with recent 
>> code
>>
>>> Raymond,
>>>
>>> Comments inline.
>>>
>>> Raymond Feng wrote:
>>>> Hi,
>>>>
>>>> There might be a few changes that expose the issue:
>>>>
>>>> 1) I recently added some code to create a "gateway" bundle that uses 
>>>> the "Require-Bundle" to aggregate split packages including 
>>>> "META-INF.services".
>>>
>>> Not sure that I follow the scenario that you're trying to deal with 
>>> here. What does META-INF/services have to do with split packages?
>>
>> To make the service provider pattern working with 3rd party jars, we need 
>> to support:
>>
>> ClassLoader.getResources("META-INF/services/<...>")
>>
>> In OSGi, it means that the META-INF.services package is exported by the 
>> bundle that owns the META-INF/services/<...>. But typically there are 
>> more than one jar that contains the META-INF/services. The 
>> META-INF.services becomes a split package.
>>
>> Let's say Bundle A and Bundle B contain META-INF/services/<...>, then set 
>> up A and B with:
>>
>> Export-Package: META-INF.services;partial=true;mandatory:=partial
>>
>> This creates a conditional export for Import-Package with a mandatory 
>> attribute partial=true. Require-Bundle ignores the "mandatory" directive. 
>> So we create a Bundle C so that:
>>
>> Require-Bundle: A,B
>> Export-Package: META-INF.services
>>
>> C sees the META-INF.services from A and B and reexports it. Now C exports 
>> META-INF.services as the aggregation of META-INF.services from A and B.
>>
>>>
>>>> 2) The bundle class loader for tuscany-extensibility-equinox (which has 
>>>> DynamicImport-Package: *) is used as the parent classloader of the 
>>>> non-OSGi contributions.
>>>> 3) The org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceProvider now 
>>>> uses the following classloaders in order:
>>>>     * The tuscany-binding-ws-axis2 bundle classloader
>>>>     * The axis2 bundle classloader
>>>>     * The tuscany-extensibility-equinox bundle classloader
>>>>     * The TCCL
>>>>
>>>
>>> Why do you need 4 classloaders?
>>
>> This is nasty hack. The TCCL needs to access classes from:
>> a) The axis2 bundle
>> b) The tuscany-binding-ws-axis2 bundle (we contribute a set of 
>> MessageReceiver classes into the axis2.xml)
>> c) Other 3rd party jars (this can be redundant if axis2 bundle has 
>> DynamicImport-Package *)
>>
>> We could remove the current TCCL.
>>
>>>
>>>> I could see the OSGi launcher failure for otest that complains about 
>>>> ClassNotFoundException for SOAP11Factory and SOAP12Factory. This is a 
>>>> known issue and we override the MF in producing the distribution.
>>>
>>> The fix you have above for Axis2ServiceProvider works fine for services 
>>> exposed using binding.ws. Unfortunately, it does not handle references 
>>> that use binding.ws - these require a classloading fix in 
>>> Axis2ServiceClient.
>>
>> You are right. It needs to have the same fix as for the service side.
>>
>>>
>>>>
>>>> I just added the same customization for the launcher under [1]. With 
>>>> this change, I can run the otests under OSGi.
>>>>
>>>> What led you to believe that the classloader is the application 
>>>> classloader? Is it the output message as follows?
>>>>
>>>> SCA Node API ClassLoader: sun.misc.Launcher$AppClassLoader@11b86e7
>>>>
>>>> This is a false alarm as the printout is on a proxy of the Node in the 
>>>> application classloader. The real node is loaded by OSGi as we can see 
>>>> from the debugger.
>>>
>>> Debugging the "ClassNotFound" exception for one of the Tuscany classes 
>>> related to Axis (one of our Message handlers) showed me that the App 
>>> class loader was being used.  Turned out the Axis code was getting this 
>>> from the TCCL.  So my fix replaces the TCCL in Axis2ServiceClient.
>>>
>>>>
>>>> Can you point to me the failing test cases you ran into? If the fix in 
>>>> [1] doesn't help, I can further debug.
>>>
>>> Can you explain what this fix does?
>>
>> This fixes the MANIFEST.MF for axiom-api-1.2.7 which is missing a few 
>> import packages to SOAP11Factory and SOAP12Factory in the equinox 
>> launcher.
>>
>>>
>>> The testcases I've been using are the OASIS ones:
>>>
>>> ASM_9003_TestCase
>>> ASM_12005_TestCase
>>>
>>>>
>>>> [1] http://svn.apache.org/viewvc?rev=800929&view=rev
>>>>
>>>> Thanks,
>>>> Raymond
>>>> --------------------------------------------------
>>>> From: "Mike Edwards" <mi...@gmail.com>
>>>> Sent: Tuesday, August 04, 2009 5:59 AM
>>>> To: "tuscany-dev" <de...@tuscany.apache.org>
>>>> Subject: [2.x] Classloading Failures running under OSGi with recent 
>>>> code
>>>>
>>>>> Folks,
>>>>>
>>>>> In the past 2 days, I have run into classloading failures with both 
>>>>> the BPEL runtime module and with the Axis2 WS Binding module.
>>>>>
>>>>> Since these failures did not occur in code previously, I assume that 
>>>>> there has been some significant change in the handling of classloaders 
>>>>> in the 2.x stream recently.  I'd be grateful if someone could explain 
>>>>> what changes have been made.  I'd also like to pose the question as to 
>>>>> why the failures have not been picked up by any testcases?
>>>>>
>>>>> The problem appears to be with 3rd party code that use the Thread 
>>>>> Context ClassLoader to load classes.  The symptom is that we get class 
>>>>> not found errors since under OSGi the bulk of our code is loaded with 
>>>>> OSGi classloaders and the TCCL in the recent builds seems to be the 
>>>>> app class loader.
>>>>>
>>>>> I fixed the BPEL code by forcing the TCCL to be the OSGI Bundle 
>>>>> ClassLoader used for loading the BPEL runtime module classes, in 
>>>>> EmbeddedODEServer.init().
>>>>>
>>>>> I fixed the Axis client code by a similar means of forcing the TCCL to 
>>>>> be the OSGi Bundle ClassLoader, in 
>>>>> Axis2ServiceClient.createServiceClient().
>>>>>
>>>>>
>>>>> Yours,  Mike.
>>>>
>>>>
>>>
>>
> 

Re: [2.x] Classloading Failures running under OSGi with recent code

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

Is there a fuller explanation of how your new design will work?

In particular, I'd like to understand how this will work for API/Provider combinations using the 
META-INF\services pattern where:

1) API is in Bundle A and Provider is in Bundle B, both bundles being "bundle-ized" by Tuscany code

2) API is in the JDK (eg javax.xml.xpath) and Provider is in Bundle C, where C is being 
"bundle-ized" by Tuscany code

3) API is in Bundle D, which already has an OSGi MANIFEST.MF and Provider is in Bundle E, which also 
already has an OSGi MANIFEST.MF (ie both are already bundles)


Yours,  Mike.

PS One of the recent code changes (and I have not pinpointed which one(s)) have caused 
implementation-bpel-runtime to stop working because the Saxon provider for 
javax.xml.xpath.XPathFactory is no longer being loaded...  I believe that it is following pattern 1) 
above...

Raymond Feng wrote:
> More comments inline.
> 
> Thanks,
> Raymond
> --------------------------------------------------
> From: "Mike Edwards" <mi...@gmail.com>
> Sent: Tuesday, August 04, 2009 2:36 PM
> To: <de...@tuscany.apache.org>
> Subject: Re: [2.x] Classloading Failures running under OSGi with recent 
> code
> 
>> Raymond,
>>
>> Comments inline.
>>
>> Raymond Feng wrote:
>>> Hi,
>>>
>>> There might be a few changes that expose the issue:
>>>
>>> 1) I recently added some code to create a "gateway" bundle that uses 
>>> the "Require-Bundle" to aggregate split packages including 
>>> "META-INF.services".
>>
>> Not sure that I follow the scenario that you're trying to deal with 
>> here. What does META-INF/services have to do with split packages?
> 
> To make the service provider pattern working with 3rd party jars, we 
> need to support:
> 
> ClassLoader.getResources("META-INF/services/<...>")
> 
> In OSGi, it means that the META-INF.services package is exported by the 
> bundle that owns the META-INF/services/<...>. But typically there are 
> more than one jar that contains the META-INF/services. The 
> META-INF.services becomes a split package.
> 
> Let's say Bundle A and Bundle B contain META-INF/services/<...>, then 
> set up A and B with:
> 
> Export-Package: META-INF.services;partial=true;mandatory:=partial
> 
> This creates a conditional export for Import-Package with a mandatory 
> attribute partial=true. Require-Bundle ignores the "mandatory" 
> directive. So we create a Bundle C so that:
> 
> Require-Bundle: A,B
> Export-Package: META-INF.services
> 
> C sees the META-INF.services from A and B and reexports it. Now C 
> exports META-INF.services as the aggregation of META-INF.services from A 
> and B.
> 
>>
>>> 2) The bundle class loader for tuscany-extensibility-equinox (which 
>>> has DynamicImport-Package: *) is used as the parent classloader of 
>>> the non-OSGi contributions.
>>> 3) The org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceProvider 
>>> now uses the following classloaders in order:
>>>     * The tuscany-binding-ws-axis2 bundle classloader
>>>     * The axis2 bundle classloader
>>>     * The tuscany-extensibility-equinox bundle classloader
>>>     * The TCCL
>>>
>>
>> Why do you need 4 classloaders?
> 
> This is nasty hack. The TCCL needs to access classes from:
> a) The axis2 bundle
> b) The tuscany-binding-ws-axis2 bundle (we contribute a set of 
> MessageReceiver classes into the axis2.xml)
> c) Other 3rd party jars (this can be redundant if axis2 bundle has 
> DynamicImport-Package *)
> 
> We could remove the current TCCL.
> 
>>
>>> I could see the OSGi launcher failure for otest that complains about 
>>> ClassNotFoundException for SOAP11Factory and SOAP12Factory. This is a 
>>> known issue and we override the MF in producing the distribution.
>>
>> The fix you have above for Axis2ServiceProvider works fine for 
>> services exposed using binding.ws. Unfortunately, it does not handle 
>> references that use binding.ws - these require a classloading fix in 
>> Axis2ServiceClient.
> 
> You are right. It needs to have the same fix as for the service side.
> 
>>
>>>
>>> I just added the same customization for the launcher under [1]. With 
>>> this change, I can run the otests under OSGi.
>>>
>>> What led you to believe that the classloader is the application 
>>> classloader? Is it the output message as follows?
>>>
>>> SCA Node API ClassLoader: sun.misc.Launcher$AppClassLoader@11b86e7
>>>
>>> This is a false alarm as the printout is on a proxy of the Node in 
>>> the application classloader. The real node is loaded by OSGi as we 
>>> can see from the debugger.
>>
>> Debugging the "ClassNotFound" exception for one of the Tuscany classes 
>> related to Axis (one of our Message handlers) showed me that the App 
>> class loader was being used.  Turned out the Axis code was getting 
>> this from the TCCL.  So my fix replaces the TCCL in Axis2ServiceClient.
>>
>>>
>>> Can you point to me the failing test cases you ran into? If the fix 
>>> in [1] doesn't help, I can further debug.
>>
>> Can you explain what this fix does?
> 
> This fixes the MANIFEST.MF for axiom-api-1.2.7 which is missing a few 
> import packages to SOAP11Factory and SOAP12Factory in the equinox launcher.
> 
>>
>> The testcases I've been using are the OASIS ones:
>>
>> ASM_9003_TestCase
>> ASM_12005_TestCase
>>
>>>
>>> [1] http://svn.apache.org/viewvc?rev=800929&view=rev
>>>
>>> Thanks,
>>> Raymond
>>> --------------------------------------------------
>>> From: "Mike Edwards" <mi...@gmail.com>
>>> Sent: Tuesday, August 04, 2009 5:59 AM
>>> To: "tuscany-dev" <de...@tuscany.apache.org>
>>> Subject: [2.x] Classloading Failures running under OSGi with recent code
>>>
>>>> Folks,
>>>>
>>>> In the past 2 days, I have run into classloading failures with both 
>>>> the BPEL runtime module and with the Axis2 WS Binding module.
>>>>
>>>> Since these failures did not occur in code previously, I assume that 
>>>> there has been some significant change in the handling of 
>>>> classloaders in the 2.x stream recently.  I'd be grateful if someone 
>>>> could explain what changes have been made.  I'd also like to pose 
>>>> the question as to why the failures have not been picked up by any 
>>>> testcases?
>>>>
>>>> The problem appears to be with 3rd party code that use the Thread 
>>>> Context ClassLoader to load classes.  The symptom is that we get 
>>>> class not found errors since under OSGi the bulk of our code is 
>>>> loaded with OSGi classloaders and the TCCL in the recent builds 
>>>> seems to be the app class loader.
>>>>
>>>> I fixed the BPEL code by forcing the TCCL to be the OSGI Bundle 
>>>> ClassLoader used for loading the BPEL runtime module classes, in 
>>>> EmbeddedODEServer.init().
>>>>
>>>> I fixed the Axis client code by a similar means of forcing the TCCL 
>>>> to be the OSGi Bundle ClassLoader, in 
>>>> Axis2ServiceClient.createServiceClient().
>>>>
>>>>
>>>> Yours,  Mike.
>>>
>>>
>>
> 


Re: [2.x] Classloading Failures running under OSGi with recent code

Posted by Raymond Feng <en...@gmail.com>.
More comments inline.

Thanks,
Raymond
--------------------------------------------------
From: "Mike Edwards" <mi...@gmail.com>
Sent: Tuesday, August 04, 2009 2:36 PM
To: <de...@tuscany.apache.org>
Subject: Re: [2.x] Classloading Failures running under OSGi with recent code

> Raymond,
>
> Comments inline.
>
> Raymond Feng wrote:
>> Hi,
>>
>> There might be a few changes that expose the issue:
>>
>> 1) I recently added some code to create a "gateway" bundle that uses the 
>> "Require-Bundle" to aggregate split packages including 
>> "META-INF.services".
>
> Not sure that I follow the scenario that you're trying to deal with here. 
> What does META-INF/services have to do with split packages?

To make the service provider pattern working with 3rd party jars, we need to 
support:

ClassLoader.getResources("META-INF/services/<...>")

In OSGi, it means that the META-INF.services package is exported by the 
bundle that owns the META-INF/services/<...>. But typically there are more 
than one jar that contains the META-INF/services. The META-INF.services 
becomes a split package.

Let's say Bundle A and Bundle B contain META-INF/services/<...>, then set up 
A and B with:

Export-Package: META-INF.services;partial=true;mandatory:=partial

This creates a conditional export for Import-Package with a mandatory 
attribute partial=true. Require-Bundle ignores the "mandatory" directive. So 
we create a Bundle C so that:

Require-Bundle: A,B
Export-Package: META-INF.services

C sees the META-INF.services from A and B and reexports it. Now C exports 
META-INF.services as the aggregation of META-INF.services from A and B.

>
>> 2) The bundle class loader for tuscany-extensibility-equinox (which has 
>> DynamicImport-Package: *) is used as the parent classloader of the 
>> non-OSGi contributions.
>> 3) The org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceProvider now 
>> uses the following classloaders in order:
>>     * The tuscany-binding-ws-axis2 bundle classloader
>>     * The axis2 bundle classloader
>>     * The tuscany-extensibility-equinox bundle classloader
>>     * The TCCL
>>
>
> Why do you need 4 classloaders?

This is nasty hack. The TCCL needs to access classes from:
a) The axis2 bundle
b) The tuscany-binding-ws-axis2 bundle (we contribute a set of 
MessageReceiver classes into the axis2.xml)
c) Other 3rd party jars (this can be redundant if axis2 bundle has 
DynamicImport-Package *)

We could remove the current TCCL.

>
>> I could see the OSGi launcher failure for otest that complains about 
>> ClassNotFoundException for SOAP11Factory and SOAP12Factory. This is a 
>> known issue and we override the MF in producing the distribution.
>
> The fix you have above for Axis2ServiceProvider works fine for services 
> exposed using binding.ws. Unfortunately, it does not handle references 
> that use binding.ws - these require a classloading fix in 
> Axis2ServiceClient.

You are right. It needs to have the same fix as for the service side.

>
>>
>> I just added the same customization for the launcher under [1]. With this 
>> change, I can run the otests under OSGi.
>>
>> What led you to believe that the classloader is the application 
>> classloader? Is it the output message as follows?
>>
>> SCA Node API ClassLoader: sun.misc.Launcher$AppClassLoader@11b86e7
>>
>> This is a false alarm as the printout is on a proxy of the Node in the 
>> application classloader. The real node is loaded by OSGi as we can see 
>> from the debugger.
>
> Debugging the "ClassNotFound" exception for one of the Tuscany classes 
> related to Axis (one of our Message handlers) showed me that the App class 
> loader was being used.  Turned out the Axis code was getting this from the 
> TCCL.  So my fix replaces the TCCL in Axis2ServiceClient.
>
>>
>> Can you point to me the failing test cases you ran into? If the fix in 
>> [1] doesn't help, I can further debug.
>
> Can you explain what this fix does?

This fixes the MANIFEST.MF for axiom-api-1.2.7 which is missing a few import 
packages to SOAP11Factory and SOAP12Factory in the equinox launcher.

>
> The testcases I've been using are the OASIS ones:
>
> ASM_9003_TestCase
> ASM_12005_TestCase
>
>>
>> [1] http://svn.apache.org/viewvc?rev=800929&view=rev
>>
>> Thanks,
>> Raymond
>> --------------------------------------------------
>> From: "Mike Edwards" <mi...@gmail.com>
>> Sent: Tuesday, August 04, 2009 5:59 AM
>> To: "tuscany-dev" <de...@tuscany.apache.org>
>> Subject: [2.x] Classloading Failures running under OSGi with recent code
>>
>>> Folks,
>>>
>>> In the past 2 days, I have run into classloading failures with both the 
>>> BPEL runtime module and with the Axis2 WS Binding module.
>>>
>>> Since these failures did not occur in code previously, I assume that 
>>> there has been some significant change in the handling of classloaders 
>>> in the 2.x stream recently.  I'd be grateful if someone could explain 
>>> what changes have been made.  I'd also like to pose the question as to 
>>> why the failures have not been picked up by any testcases?
>>>
>>> The problem appears to be with 3rd party code that use the Thread 
>>> Context ClassLoader to load classes.  The symptom is that we get class 
>>> not found errors since under OSGi the bulk of our code is loaded with 
>>> OSGi classloaders and the TCCL in the recent builds seems to be the app 
>>> class loader.
>>>
>>> I fixed the BPEL code by forcing the TCCL to be the OSGI Bundle 
>>> ClassLoader used for loading the BPEL runtime module classes, in 
>>> EmbeddedODEServer.init().
>>>
>>> I fixed the Axis client code by a similar means of forcing the TCCL to 
>>> be the OSGi Bundle ClassLoader, in 
>>> Axis2ServiceClient.createServiceClient().
>>>
>>>
>>> Yours,  Mike.
>>
>>
> 

Re: [2.x] Classloading Failures running under OSGi with recent code

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

Comments inline.

Raymond Feng wrote:
> Hi,
> 
> There might be a few changes that expose the issue:
> 
> 1) I recently added some code to create a "gateway" bundle that uses the 
> "Require-Bundle" to aggregate split packages including "META-INF.services".

Not sure that I follow the scenario that you're trying to deal with here.  What does 
META-INF/services have to do with split packages?

> 2) The bundle class loader for tuscany-extensibility-equinox (which has 
> DynamicImport-Package: *) is used as the parent classloader of the 
> non-OSGi contributions.
> 3) The org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceProvider now 
> uses the following classloaders in order:
>     * The tuscany-binding-ws-axis2 bundle classloader
>     * The axis2 bundle classloader
>     * The tuscany-extensibility-equinox bundle classloader
>     * The TCCL
> 

Why do you need 4 classloaders?

> I could see the OSGi launcher failure for otest that complains about 
> ClassNotFoundException for SOAP11Factory and SOAP12Factory. This is a 
> known issue and we override the MF in producing the distribution.

The fix you have above for Axis2ServiceProvider works fine for services exposed using binding.ws. 
Unfortunately, it does not handle references that use binding.ws - these require a classloading fix 
in Axis2ServiceClient.

> 
> I just added the same customization for the launcher under [1]. With 
> this change, I can run the otests under OSGi.
> 
> What led you to believe that the classloader is the application 
> classloader? Is it the output message as follows?
> 
> SCA Node API ClassLoader: sun.misc.Launcher$AppClassLoader@11b86e7
> 
> This is a false alarm as the printout is on a proxy of the Node in the 
> application classloader. The real node is loaded by OSGi as we can see 
> from the debugger.

Debugging the "ClassNotFound" exception for one of the Tuscany classes related to Axis (one of our 
Message handlers) showed me that the App class loader was being used.  Turned out the Axis code was 
getting this from the TCCL.  So my fix replaces the TCCL in Axis2ServiceClient.

> 
> Can you point to me the failing test cases you ran into? If the fix in 
> [1] doesn't help, I can further debug.

Can you explain what this fix does?

The testcases I've been using are the OASIS ones:

ASM_9003_TestCase
ASM_12005_TestCase

> 
> [1] http://svn.apache.org/viewvc?rev=800929&view=rev
> 
> Thanks,
> Raymond
> --------------------------------------------------
> From: "Mike Edwards" <mi...@gmail.com>
> Sent: Tuesday, August 04, 2009 5:59 AM
> To: "tuscany-dev" <de...@tuscany.apache.org>
> Subject: [2.x] Classloading Failures running under OSGi with recent code
> 
>> Folks,
>>
>> In the past 2 days, I have run into classloading failures with both 
>> the BPEL runtime module and with the Axis2 WS Binding module.
>>
>> Since these failures did not occur in code previously, I assume that 
>> there has been some significant change in the handling of classloaders 
>> in the 2.x stream recently.  I'd be grateful if someone could explain 
>> what changes have been made.  I'd also like to pose the question as to 
>> why the failures have not been picked up by any testcases?
>>
>> The problem appears to be with 3rd party code that use the Thread 
>> Context ClassLoader to load classes.  The symptom is that we get class 
>> not found errors since under OSGi the bulk of our code is loaded with 
>> OSGi classloaders and the TCCL in the recent builds seems to be the 
>> app class loader.
>>
>> I fixed the BPEL code by forcing the TCCL to be the OSGI Bundle 
>> ClassLoader used for loading the BPEL runtime module classes, in 
>> EmbeddedODEServer.init().
>>
>> I fixed the Axis client code by a similar means of forcing the TCCL to 
>> be the OSGi Bundle ClassLoader, in 
>> Axis2ServiceClient.createServiceClient().
>>
>>
>> Yours,  Mike. 
> 
> 


Re: [2.x] Classloading Failures running under OSGi with recent code

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

There might be a few changes that expose the issue:

1) I recently added some code to create a "gateway" bundle that uses the 
"Require-Bundle" to aggregate split packages including "META-INF.services".
2) The bundle class loader for tuscany-extensibility-equinox (which has 
DynamicImport-Package: *) is used as the parent classloader of the non-OSGi 
contributions.
3) The org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceProvider now uses 
the following classloaders in order:
     * The tuscany-binding-ws-axis2 bundle classloader
     * The axis2 bundle classloader
     * The tuscany-extensibility-equinox bundle classloader
     * The TCCL

I could see the OSGi launcher failure for otest that complains about 
ClassNotFoundException for SOAP11Factory and SOAP12Factory. This is a known 
issue and we override the MF in producing the distribution.

I just added the same customization for the launcher under [1]. With this 
change, I can run the otests under OSGi.

What led you to believe that the classloader is the application classloader? 
Is it the output message as follows?

SCA Node API ClassLoader: sun.misc.Launcher$AppClassLoader@11b86e7

This is a false alarm as the printout is on a proxy of the Node in the 
application classloader. The real node is loaded by OSGi as we can see from 
the debugger.

Can you point to me the failing test cases you ran into? If the fix in [1] 
doesn't help, I can further debug.

[1] http://svn.apache.org/viewvc?rev=800929&view=rev

Thanks,
Raymond
--------------------------------------------------
From: "Mike Edwards" <mi...@gmail.com>
Sent: Tuesday, August 04, 2009 5:59 AM
To: "tuscany-dev" <de...@tuscany.apache.org>
Subject: [2.x] Classloading Failures running under OSGi with recent code

> Folks,
>
> In the past 2 days, I have run into classloading failures with both the 
> BPEL runtime module and with the Axis2 WS Binding module.
>
> Since these failures did not occur in code previously, I assume that there 
> has been some significant change in the handling of classloaders in the 
> 2.x stream recently.  I'd be grateful if someone could explain what 
> changes have been made.  I'd also like to pose the question as to why the 
> failures have not been picked up by any testcases?
>
> The problem appears to be with 3rd party code that use the Thread Context 
> ClassLoader to load classes.  The symptom is that we get class not found 
> errors since under OSGi the bulk of our code is loaded with OSGi 
> classloaders and the TCCL in the recent builds seems to be the app class 
> loader.
>
> I fixed the BPEL code by forcing the TCCL to be the OSGI Bundle 
> ClassLoader used for loading the BPEL runtime module classes, in 
> EmbeddedODEServer.init().
>
> I fixed the Axis client code by a similar means of forcing the TCCL to be 
> the OSGi Bundle ClassLoader, in Axis2ServiceClient.createServiceClient().
>
>
> Yours,  Mike.