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" <[email protected]>
Sent: Tuesday, August 04, 2009 2:36 PM
To: <[email protected]>
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$appclassloa...@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" <[email protected]>
Sent: Tuesday, August 04, 2009 5:59 AM
To: "tuscany-dev" <[email protected]>
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.