Space: Apache Tuscany Docs 2.x 
(https://cwiki.apache.org/confluence/display/TUSCANYxDOCx2x)
Page: Classloading 
(https://cwiki.apache.org/confluence/display/TUSCANYxDOCx2x/Classloading)


Edited by kelvin goodson:
---------------------------------------------------------------------
Need to detail the various ways the Tuscany runtime loads classes and the 
issues involved. Here are some notes to kick of this document

h1. Classloading Objectives

The runtime must work in both OSGi and non-OSGI environments. I.e. we can't 
rely on the OSGi service registry for extensibility
The runtime must not be generally environment specific. I.e. no buddy 
classloading
...

h1. General Patterns

h2. Extension loading - JSE

tuscany-extensibility
Tuscany finds extensions by looking for META-INF/services files on the 
classpath.

h2. Extension loading - OSGi

tuscany-extensibility-equinox
It's a bit more complicated here. The extensibility-equinox bundle is given the 
entire OSGi context at start up and from there is looks in all of the loaded 
bundles looking for META-INF/services files. It caches them against the bundle 
in which they are found.

The tuscany-extensibility-equinox bundle also has a dynamic import

{code}
DynamicImport-Package: org.apache.tuscany.sca.extensibility.equinox,
 javax.transaction;version="1.1",
 javax.transaction.xa;version="1.1",
{code}

Which allows it to generally load any classes in the runtime

h2. Split Packages - JSE

We don't take any special account of this in JSE (?)
We avoid split packages across the JARs we create as it messes OSGi up.

h2. Split Packages - OSGI

We avoid split packages across the bundles we create
They may exist in third party bundles (or jars that we turn into bundles) so we 
need a way round it

The Tuscany eclipse plugin is used to generate bundles manifest for jars which 
don't have them. This is done automatically with all packages exported (?) and 
the resulting bundle it in the distribution modules directory in the following 
form

{code}
bundle-name
  META-INF
     MANIFEST.MF
  bundle-name.jar
{code}

The MANIFEST.MF is generated and will have a bundle classpath pointing to the 
jar (which doesn't itself have a manifest

The runtime (node-launcher-equinox) has code to load these directories as 
bundles.

There is a way of overriding these automatically generated bundles so that 
split packages (or any other manifest problems) can be worked round. Generate 
the manifest manually and put it in

{code}
distribution/all/manifests
{code}

Update distribution/pom.xml to configure the Tuscany version of the maven 
bundle plugin to apply this manifest

{noformat}
            <plugin>
                <groupId>org.apache.tuscany.maven.plugins</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <version>1.0.6</version>
                <executions>
                    <execution>
                        <id>distribution-modules</id>
                        <phase>generate-resources</phase>
                        <goals>
                             <goal>generate-modules</goal>
                        </goals>
                        <configuration>
                             <targetDirectory>target/modules</targetDirectory>
                             
<useDistributionName>${useDistributionName}</useDistributionName>
                             
<generateAggregatedBundle>${generateAggregatedBundle}</generateAggregatedBundle>
                             <generateManifestJar>true</generateManifestJar>
                             <artifactManifests>
                                 <artifactManifest>
                                     
<groupId>org.apache.ws.commons.axiom</groupId>
                                     <artifactId>axiom-api</artifactId>
                                     <version>1.2.8</version>
                                     
<manifestFile>${basedir}/manifests/axiom-api-1.2.8.MF</manifestFile>
                                 </artifactManifest>
                                 <artifactManifest>
                                     <groupId>org.apache.woden</groupId>
                                     <artifactId>woden-impl-dom</artifactId>
                                     <version>1.0M8</version>
                                     
<manifestFile>${basedir}/manifests/woden-impl-dom-1.0M8.MF</manifestFile>
                                 </artifactManifest>
                                 <!--artifactManifest>
                                     <groupId>org.apache.tuscany.sdo</groupId>
                                     
<artifactId>tuscany-sdo-api-r2.1</artifactId>
                                     <version>1.1.1</version>
                                     
<manifestFile>${basedir}/manifests/tuscany-sdo-api-r2.1-1.1.1.MF</manifestFile>
                                 </artifactManifest-->
                                 <!-- artifactAggregations (below) is the right 
approach to solving the split
                                      package between axis-kernel and 
axis2-transport-http however the Tuscany
                                      runtime doesn't take any notice of it so 
using a fragment at the moment -->
                                 <artifactManifest>
                                     <groupId>org.apache.axis2</groupId>
                                     <artifactId>axis2-kernel</artifactId>
                                     <version>1.5.1</version>
                                     
<manifestFile>${basedir}/manifests/axis2-kernel-1.5.1.MF</manifestFile>
                                 </artifactManifest>
                                 <artifactManifest>
                                     <groupId>org.apache.axis2</groupId>
                                     
<artifactId>axis2-transport-http</artifactId>
                                     <version>1.5.1</version>
                                     
<manifestFile>${basedir}/manifests/axis2-transport-http-1.5.1.MF</manifestFile>
                                 </artifactManifest>
                                 <artifactManifest>
                                     <groupId>org.apache.axis2</groupId>
                                     <artifactId>*</artifactId>
                                     <version>*</version>
                                 </artifactManifest>
                             </artifactManifests>
                             <!--artifactAggregations>
                                  <artifactAggregation>
                                      
<symbolicName>org.apache.tuscany.sca.axis2-kernel</symbolicName>
                                      <version>1.5.1</version>
                                      <artifactMembers>
                                          <artifactMember>
                                              
<groupId>org.apache.axis2</groupId>
                                              
<artifactId>axis2-kernel</artifactId>
                                              <version>1.5.1</version>
                                          </artifactMember>
                                          <artifactMember>
                                              
<groupId>org.apache.axis2</groupId>
                                              
<artifactId>axis2-transport-http</artifactId>
                                              <version>1.5.1</version>
                                          </artifactMember>
                                      </artifactMembers>
                                  </artifactAggregation>
                              </artifactAggregations-->
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                   <dependency>
                      <groupId>org.eclipse</groupId>
                      <artifactId>osgi</artifactId>
                      <version>3.3.0-v20070530</version>
                   </dependency>
                </dependencies>
            </plugin>
{noformat}

You'll note that there is an artifact aggregation element that doesn't work at 
the moment. This should aggregate the two bundles together so that a split 
package isn't an issue. As this doesn't work at the moment another way to 
achieve the same result is to make one package a fragement of the other by 
configuring separate manifests manually.

NOTE\!\!\!\!\! you also need to put the manually generated manifest in 
node-launcher-equinox\src\main\resources\org\apache\tuscany\sca\node\equinox\launcher
 otherwise you'll spend a lot of time trying to get this to work. (we need to 
fix this\!)

h2. Third-party libraries - JSE

TBD

h2. Third-party libraries - OSGI

Third-party libraries often rely on TCCL to load implementation classes in an 
extensible way. For example, the SDO API loads the HelperContext implementation 
in this way. In an OSGi environment there will not be a static dependency 
between the api bundle and the impl bundle so we need to fake it. Typically we 
do this by setting up the TCCL appropriately before the library us called.

See ClassLoaderContext which help us to set up a multi-classloader 
configurations.

Typically in OSGi one of the classloaders we pass in here will be the 
extensibiliy-equinox bundle classloader (the ServiceDiscoverer) as this bundles 
has a dynamic import which allows it to load any class in the runtime.


h2. Tuscany Node API - JSE

TBD

h2. Tuscany Node API - OSGi

There are a small number of Tuscany Jars you need to use in the app launcher in 
the OSGi environment

tuscany-sca-api
tuscany-node-api
tuscany-node-launcher-equinox

The node API has to load the node implementation and has a dynamic import in 
its manifest

DynamicImport-Package: 
org.apache.tuscany.sca.node.impl,org.apache.tuscany.sca.extensibility



h2. SCA Client API - JSE

Factory finder impl is injected into the API class by the implementation

h2. SCA Client API - OSGi

NodeFactory maintains a NodeProxy inner class that supports cross-classloader 
calls. The calling client api will have been loaded by the app classloader but 
the underlying node will have been loaded by a bundle classloader. We need to 
bridge that gap.

h2. Contribution Class Loading

The ClassLoaderModelResolver (CLMR) specializes java.net.URL.URLClassLoader and 
implements o.a.t.s....ModelResolver. Each contribution&nbsp;is associated with 
a single CLMR . On construction the CLMR is endowed with a set of URLs that 
allow it to find all classes in it's contribution via the URLClassLoader 
behaviour.

*T{*}he itest project import-export-tests has a class TestTestCase with method 
testOneNode which demonstrates a&nbsp;more complex scenario&nbsp;where a cross 
contribution import/export of a java package exists between the contributions. 
&nbsp;In this example a node is created using 2 composite URIs for 
contributions ... "../exports/target/classes", "../imports/target/classes". An 
imported class is resolved using the CLMR of the exporting contribution. 
&nbsp;The exporter's CLMR is made available to the importing CLMR by deployment 
\[1\] code which traverses all contributions, identifying cross contribution 
dependencies (see buildDependencies at \[1\])&nbsp;&nbsp;and using the set of 
remaining contributions to resolve the import, potentially more than once.

[[1] http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java?view=markup&pathrev=948564|http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java?view=markup&pathrev=948564]


&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;

&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp;

Change your notification preferences: 
https://cwiki.apache.org/confluence/users/viewnotifications.action

Reply via email to