Re: Classloading in Tuscany
*Classloading in Tuscany - Tuscany Extension Classloading* *Current implementation* Details on the Tuscany extension architecture are described here: http://cwiki.apache.org/confluence/display/TUSCANY/SCA+Java+Extension+Development+Guide This extension architecture is based on standard J2SE Jar Service Provider, where service provider configuration files are provided in META-INF/services. Tuscany Runtime reads these configuration files and loads the service implementation classes provided by the extensions. Here is an example of the implementation of this architecture in Tuscany: org.apache.tuscany.sca.core.DefaultExtensionPointRegistry:: *public T T getExtensionPoint(ClassT extensionPointType) { . ClassLoader classLoader = extensionPointType.getClassLoader(); if (classLoader == null) { classLoader = Thread.currentThread().getContextClassLoader(); } ListString classNames = ServiceConfigurationUtil.getServiceClassNames(classLoader, extensionPointType.getName()); if (!classNames.isEmpty()) { Class? extensionPointClass = Class.forName(classNames.iterator().next(), true, classLoader); . } * The code snippet above is one of the examples of the use of this architecture. The code uses a single classloader, which is the classloader of the interface extensionPointType (or the thread context classloader if extensionPointType was loaded by the primordial classloader). The code assumes that the service configuration file, the service implementation class and the service interface are visible from classLoader. And this classloader is obtained through the interface, which is typically an SPI. As a result the SPI classloader needs visibility of all configuration files and implementation classes loaded through this mechanism. Since extension modules are loaded using this architecture by searching for o.a.t.s.c.ModuleActivator in META-INF/services, SPI classloader requires visibility of all extensions. *Requirements* Tuscany extension architecture based on Jar Service Provider should be retained to enable Tuscany Runtime and SPI to find extensions without requiring changes to the way in which extension classes are specified. Lazy loading of extensions should continue to work, so Tuscany SPI and Runtime modules should be able to locate extensions, rather than extensions registering themselves. In a multi-classloader framework, SPI/Runtime classloader should not require visibility of extension classes or extension configuration files. *Proposed changes* Replace ServiceConfigurationUtil with a ServiceDiscovery SPI which finds services from all registered classloaders. The SPI classloader will be automatically registered (and hence no registration is necessary when Tuscany is run using a single-classloader). ServiceDiscovery will be a singleton class providing the functionality in ServiceConfigurationUtil (using new methods which work in a multi-classloader runtime) and a new service registration method: void registerClassLoader(ClassLoader classLoader) This method will be used by OSGi bundle activator to register bundle classloaders when Tuscany is run under OSGi as multiple bundles. It will also be used to test a multi-classloader framework without OSGi, after all the classloading changes required to support multiple classloaders in Tuscany are completed. Instead of using the interface classloader, the configuration files provided by extensions will be found from all registered classloaders. The implementation class specified in the configuration file will always be loaded using the classloader which loaded the configuration file. To enable individual extensions to be packaged as separate OSGi bundles, configuration files should be located in the same maven module as the implementation class wherever possible (org.apache.tuscany.sca.work.WorkScheduler in core-spi is one example where the file needs to be moved to core along with the implementation class, there may be others). Since a service implementation may be reachable from multiple classloaders, sets should be used instead of lists in the service discovery code, where multiple service implementations are read, to ensure that each class is processed only once. Thank you... Regards, Rajini
Re: Classloading in Tuscany
Hi, Please see my comments inline. Thanks, Raymond - Original Message - From: Rajini Sivaram [EMAIL PROTECTED] To: tuscany-dev@ws.apache.org Sent: Friday, October 26, 2007 5:00 AM Subject: Re: Classloading in Tuscany *Classloading in Tuscany - Tuscany Extension Classloading* *Current implementation* Details on the Tuscany extension architecture are described here: http://cwiki.apache.org/confluence/display/TUSCANY/SCA+Java+Extension+Development+Guide This extension architecture is based on standard J2SE Jar Service Provider, where service provider configuration files are provided in META-INF/services. Tuscany Runtime reads these configuration files and loads the service implementation classes provided by the extensions. Here is an example of the implementation of this architecture in Tuscany: org.apache.tuscany.sca.core.DefaultExtensionPointRegistry:: *public T T getExtensionPoint(ClassT extensionPointType) { . ClassLoader classLoader = extensionPointType.getClassLoader(); if (classLoader == null) { classLoader = Thread.currentThread().getContextClassLoader(); } ListString classNames = ServiceConfigurationUtil.getServiceClassNames(classLoader, extensionPointType.getName()); if (!classNames.isEmpty()) { Class? extensionPointClass = Class.forName(classNames.iterator().next(), true, classLoader); . } * The code snippet above is one of the examples of the use of this architecture. The code uses a single classloader, which is the classloader of the interface extensionPointType (or the thread context classloader if extensionPointType was loaded by the primordial classloader). The code assumes that the service configuration file, the service implementation class and the service interface are visible from classLoader. And this classloader is obtained through the interface, which is typically an SPI. As a result the SPI classloader needs visibility of all configuration files and implementation classes loaded through this mechanism. Since extension modules are loaded using this architecture by searching for o.a.t.s.c.ModuleActivator in META-INF/services, SPI classloader requires visibility of all extensions. *Requirements* Tuscany extension architecture based on Jar Service Provider should be retained to enable Tuscany Runtime and SPI to find extensions without requiring changes to the way in which extension classes are specified. Lazy loading of extensions should continue to work, so Tuscany SPI and Runtime modules should be able to locate extensions, rather than extensions registering themselves. In a multi-classloader framework, SPI/Runtime classloader should not require visibility of extension classes or extension configuration files. *Proposed changes* Replace ServiceConfigurationUtil with a ServiceDiscovery SPI which finds services from all registered classloaders. The SPI classloader will be automatically registered (and hence no registration is necessary when Tuscany is run using a single-classloader). ServiceDiscovery will be a singleton class providing the functionality in ServiceConfigurationUtil (using new methods which work in a multi-classloader runtime) and a new service registration method: I won't call it as a singleton. It should be one instance per SCA Node. void registerClassLoader(ClassLoader classLoader) This method will be used by OSGi bundle activator to register bundle classloaders when Tuscany is run under OSGi as multiple bundles. It will also be used to test a multi-classloader framework without OSGi, after all the classloading changes required to support multiple classloaders in Tuscany are completed. Two questions: 1) What's going to happen if the OSGi bundles are loaded lazily (Eclipse supports it)? In such cases, the bundle activator will not be triggered until as a class in the bundle is accessed. 2) Should we register the classloader only if the MATA-INF/services are present? Instead of using the interface classloader, the configuration files provided by extensions will be found from all registered classloaders. The implementation class specified in the configuration file will always be loaded using the classloader which loaded the configuration file. To enable individual extensions to be packaged as separate OSGi bundles, configuration files should be located in the same maven module as the implementation class wherever possible (org.apache.tuscany.sca.work.WorkScheduler in core-spi is one example where the file needs to be moved to core along with the implementation class, there may be others). +1. Since a service implementation may be reachable from multiple classloaders, sets should be used instead of lists in the service discovery code, where multiple service implementations are read, to ensure that each class is processed only once. I think we just have to make sure the URLs of the service provider files
Re: Classloading in Tuscany
Raymond, Thank you for your comments. My comments inline. On 10/26/07, Raymond Feng [EMAIL PROTECTED] wrote: Hi, Please see my comments inline. Thanks, Raymond - Original Message - From: Rajini Sivaram [EMAIL PROTECTED] To: tuscany-dev@ws.apache.org Sent: Friday, October 26, 2007 5:00 AM Subject: Re: Classloading in Tuscany *Classloading in Tuscany - Tuscany Extension Classloading* *Current implementation* Details on the Tuscany extension architecture are described here: http://cwiki.apache.org/confluence/display/TUSCANY/SCA+Java+Extension+Development+Guide This extension architecture is based on standard J2SE Jar Service Provider, where service provider configuration files are provided in META-INF/services. Tuscany Runtime reads these configuration files and loads the service implementation classes provided by the extensions. Here is an example of the implementation of this architecture in Tuscany: org.apache.tuscany.sca.core.DefaultExtensionPointRegistry:: *public T T getExtensionPoint(ClassT extensionPointType) { . ClassLoader classLoader = extensionPointType.getClassLoader(); if (classLoader == null) { classLoader = Thread.currentThread().getContextClassLoader(); } ListString classNames = ServiceConfigurationUtil.getServiceClassNames(classLoader, extensionPointType.getName()); if (!classNames.isEmpty()) { Class? extensionPointClass = Class.forName(classNames.iterator().next(), true, classLoader); . } * The code snippet above is one of the examples of the use of this architecture. The code uses a single classloader, which is the classloader of the interface extensionPointType (or the thread context classloader if extensionPointType was loaded by the primordial classloader). The code assumes that the service configuration file, the service implementation class and the service interface are visible from classLoader. And this classloader is obtained through the interface, which is typically an SPI. As a result the SPI classloader needs visibility of all configuration files and implementation classes loaded through this mechanism. Since extension modules are loaded using this architecture by searching for o.a.t.s.c.ModuleActivator in META-INF/services, SPI classloader requires visibility of all extensions. *Requirements* Tuscany extension architecture based on Jar Service Provider should be retained to enable Tuscany Runtime and SPI to find extensions without requiring changes to the way in which extension classes are specified. Lazy loading of extensions should continue to work, so Tuscany SPI and Runtime modules should be able to locate extensions, rather than extensions registering themselves. In a multi-classloader framework, SPI/Runtime classloader should not require visibility of extension classes or extension configuration files. *Proposed changes* Replace ServiceConfigurationUtil with a ServiceDiscovery SPI which finds services from all registered classloaders. The SPI classloader will be automatically registered (and hence no registration is necessary when Tuscany is run using a single-classloader). ServiceDiscovery will be a singleton class providing the functionality in ServiceConfigurationUtil (using new methods which work in a multi-classloader runtime) and a new service registration method: I won't call it as a singleton. It should be one instance per SCA Node. I am not sure I understand the difference in terms of code. When I said singleton, I meant a static instance, so I have one instance of the ServiceDiscovery class per classloader that ServiceDiscovery is loaded from (ok, the term singleton is misleading). Since ServiceDiscovery will be part of Tuscany SPI, any Tuscany SPI/Runtime code using this SPI classloader will find the same set of registered classloaders. By saying that it should be one instance per SCA Node, did you mean that (1) there could be another SCA node using a different classloader for the SPI, and hence a different set of registered classloaders, or (2) that there can be multiple SCA nodes using the same SPI classloader, but want to use different extension classloaders? The first case is fine. I am not sure how the second could be implemented without passing node information around. void registerClassLoader(ClassLoader classLoader) This method will be used by OSGi bundle activator to register bundle classloaders when Tuscany is run under OSGi as multiple bundles. It will also be used to test a multi-classloader framework without OSGi, after all the classloading changes required to support multiple classloaders in Tuscany are completed. Two questions: 1) What's going to happen if the OSGi bundles are loaded lazily (Eclipse supports it)? In such cases, the bundle activator
Re: Classloading in Tuscany
Sebastien, Comments inline. On 10/25/07, Jean-Sebastien Delfino [EMAIL PROTECTED] wrote: Some comments and use cases. Rajini Sivaram wrote: The bundles that I have at the moment are: 1. org.apache.tuscany.sca.api.jar 14,942 bytes 2. org.apache.tuscany.sca.tuscany.corespi.jar 370,228 bytes 3. org.apache.tuscany.sca.tuscany.runtime.jar 571,159 bytes 4. org.apache.tuscany.sca.tuscany.extensions.jar 996,238 bytes 5. org.apache.tuscany.sca.tuscany.dependencies.jar 43,928,926 bytes The dependencies bundle seems pretty big :) From a packaging point of view, it doesn't make sense to split Tuscany, Why doesn't it make sense? (more below about scenarios and requirements) I was talking in relative terms, and purely in terms of the size of the bundles. The whole of Tuscany is only about 2MB, while the 3rd party code is nearly 44MB, so it kind of makes sense to concentrate on splitting the 3rd party code rather than Tuscany. I think the value in splitting Tuscany is more in terms of running multiple versions of Tuscany bundles (under OSGi) rather than reducing the total size of the bundles required in any particular scenario. Unless there are use cases which require only a very small part of the 44MB of 3rd party code, making 900k of extensions look big (your last use case may be one, so I take my statement back). and it makes a lot more sense to split the 3rd party code. Did you mean split the 3rd party code from the rest of Tuscany as one monster 40Mb bundle? or split that monster bundle in a set of smaller bundles? I would like to split the monster bundle into as many chunks as is manageable. I dont want to sound like I am doing a sales pitch for OSGi, but I am not sure there is a cleaner or easier way to sort out versioning issues that Tuscany would face if different versions of 3rd party libraries were used, compared to running Tuscany under OSGi. An OSGi runtime would enable different versions of 3rd party libraries, different versions of Tuscany runtime and different versions of Tuscany extensions to coexist in a single VM with very little extra effort. Implementing something similar with a classloader architecture outside of OSGi would be significantly more complex (and will eventually reinvent OSGi). OK, I like OSGi too :) My previous question about requirements was an attempt to step back from the technology details and generate some discussion around the bundle use cases. Let me try to help and list the use cases I can think of, and how they relate to the bundles you've listed. - I develop a business application, and I'm using the SCA APIs, I don't want any dependency on a particular runtime or whatever version of it. -- happy with oat.sca.api! - I developing an extension, using the Tuscany SPI, and running with the Tuscany runtime -- happy with oat.corespi -- would be happy too if oat.core.spi and oat.runtime were a single bundle as long as the runtime packages are not exported. I guess any single project that wants to run something is going to have a dependency on oat.runtime anyway to be able to start the runtime, right? As an extension developer, you should only import packages that are published as SPIs. It shouldn't matter whether the runtime bundle exported packages (for instance to split the runtime itself into multiple bundles). - I'm developing an extension which depends on a 3rd party dependency from oat.dependencies -- not happy with a 40Mb bundle -- what'll happen if I have two copies of Axis2's Axiom in 2 bundles? can I still pass an axiom element between 2 extensions using these 2 copies? I guess not... Now I think you are asking for too much. Presumably you have two different versions of Axiom in the two bundles. You can have extensionA(Axiom v1) and extensionB(Axiom v2) coexist as long as they dont want to pass axiom elements between them. And you can have extensionA(Axiom v1) and extension B(Axiom v1) coexist and pass axiom elements between them, and these can coexist which extensionC(Axiom v2) and extensionD(Axiom v2) which pass axiom elements between C and D. - I just developed version v4.0.3 of implementation-java, which requires xml-api v47.12, unfortunately incompatible with the xml-api version in Tuscany v4.0.2. -- can we walk through the steps to upgrade my bundle-ized Tuscany v4.0.2 working with my implementation-java v4.0.3? At the moment, I doubt this will be possible (I think you are deliberately trying to make my life difficult). I can give you an alternative scenario that is similar, but is more achievable. If you have developed v4.0.3 of binding-ws-axis2, which requires a new version of Axis2, which is incompatible with the version of Axis2 used in Tuscany v4.0.2, you should be able to upgrade Tuscany 4.0.2 to work with binding-ws-axis2 v4.0.3. I think you will run into problems if you upgraded implementation-java to a
Re: Classloading in Tuscany
On 10/25/07, Rajini Sivaram [EMAIL PROTECTED] wrote: snip This does imply splitting both Tuscany extension bundle and the big 3rd party bundle, into smaller chunks. Because of its size, I am more inclined to split the 3rd party bundle into smaller bundles first (though I have no idea where to start with this huge big list of jar files). I can help with that, after doing lots of releases i've a good understanding of what each jar is for and what uses it. How about starting with whatever bundle make up is easiest for you and then we can juggle things around to get to something everyone is happy with. ...ant
Re: Classloading in Tuscany
Thank you, Ant. That will be very helpful. Let me finish off the classloading changes first, and I will get back to you (hopefully sometime next week). Thank you... Regards, Rajini On 10/25/07, ant elder [EMAIL PROTECTED] wrote: On 10/25/07, Rajini Sivaram [EMAIL PROTECTED] wrote: snip This does imply splitting both Tuscany extension bundle and the big 3rd party bundle, into smaller chunks. Because of its size, I am more inclined to split the 3rd party bundle into smaller bundles first (though I have no idea where to start with this huge big list of jar files). I can help with that, after doing lots of releases i've a good understanding of what each jar is for and what uses it. How about starting with whatever bundle make up is easiest for you and then we can juggle things around to get to something everyone is happy with. ...ant
Re: Classloading in Tuscany
Simon, Comments inline... On 10/22/07, Simon Nash [EMAIL PROTECTED] wrote: Thanks for all your work on progressing this. Comments inline. Simon Rajini Sivaram wrote: *An overview of the proposed classloader design for Tuscany* Thank you for all your emails. Based on your feedback, I would like to propose a new classloader architecture for Tuscany. I have created new bundles in OSGi to reflect the kind of classloader-based isolation that we may like to have, and if acceptable, I will add support to provide this without OSGi. Simon didn't like the word modules being used to describe the level of granularity for classloaders since that clashes with maven modules which are more fine-grained. So I think in spite of the confusion that it may create, I will use bundle to refer to a list of modules that we want to treat as a collection, where each bundle can have an associated classloader. When running under OSGi, each bundle will correspond to one OSGi bundle. We have the following bundles in Tuscany - the names in brackets refer to maven module names 1. SCA API (sca-api) 2. Tuscany SPI (core-spi, assembly, contribution, policy, interface, interface-java, interface-wsdl, databinding) Some of the above maven modules contain implementation code as well as SPI code. For example, in the assembly module, Service.java is an SPI and ServiceImpl.java is an implementation class. Yes, unfortunately many of these implementation classes are used outside of the SPI modules. At the moment the core-spi bundle that I use to run Tuscany under OSGi is forced to export all the packages from these modules, rather than just the SPI. eg. ComponentImpl from the assembly module along with SPI forms the base class of RuntimeComponentImpl in Runtime. ComponentTypeImpl from the assembly module is used by many extensions. 3. Tuscany Runtime ( assembly-xml, assembly-xsd, contribution-impl, contribution-java, contribution-namespace, core, core-databinding, definitions, domain, domain-api, domain-impl, extension-helper, host-embedded, interface-java-xml, interface-wsdl-xml, java2wsdl, node, node-impl, osgi-runtime, policy-security, policy-xml, topology, topology-xml, wsdl2java, binding-sca, binding-sca-xml) 4. Tuscany Extensions (binding-*. implementation-*, host-*, databinding-*, contribution-osgi) 5. 3rd Party Libraries (Axis2 etc) 6. Application contributions By default, Tuscany will continue to run using a single classloader with all required classes on the CLASSPATH. But it will also be possible to run Tuscany using five different classloaders for the five bundles. Applications will always be run using separate classloaders, created by Tuscany. All existing samples and itests will continue to run using a single classloader. But a new set of tests will be added for classloading which checks if Tuscany runs with multiple classloaders and verifies that all the isolation requirements are met. There are 6 bundles listed above, but this paragraph refers to five bundles. Did you mean to say six bundles here? Sorry, I meant 5 Tuscany bundles plus n application bundles. Based on the notes, I think the desired classloading hierarchy for Tuscany is: http://cwiki.apache.org/confluence/download/attachments/68801/desired-classloader.png The solid lines show parent-child relationship used for standard Java classloader delegation, providing static visibility. The dotted lines show dependencies which are more targetted, and preferably avoided where possible. 3rd party code could potentially be split across multiple classloaders, and these could be inserted anywhere in the hierarchy as long as SPI, Runtime and Extensions can see the code they require. Tuscany modules will continue to expect to see these dependencies from the classloader of the module (from Tuscany runtime and Tuscany extensions). I have generated a few dependency diagrams for Tuscany modules, and these dont exactly match the requirements that have been specified in the notes. In particular, it seems to me that the line between Tuscany-SPI and Tuscany Runtime is rather blurred (or I haven't understood the separation correctly). The dependency diagram for the whole of Tuscany/modules is : http://cwiki.apache.org/confluence/download/attachments/68801/tuscany-dependencies.png The modules are listed in four columns, the first one is SCA-API and Tuscany SPI, where the dependencies coming in from the right are expected, and there are no dependencies going to the right. The second column is Tuscany Runtime, and the third and fourth ones show the extensions. Sorry, the diagram is a bit blurred, but if you download it and zoom in, you can see the arrows going into the runtime column from
Re: Classloading in Tuscany
Sebastien, Comments inline. On 10/22/07, Jean-Sebastien Delfino [EMAIL PROTECTED] wrote: I have two questions. [snip] Rajini Sivaram wrote: We have the following bundles in Tuscany - the names in brackets refer to maven module names 1. SCA API (sca-api) 2. Tuscany SPI (core-spi, assembly, contribution, policy, interface, interface-java, interface-wsdl, databinding) 3. Tuscany Runtime ( assembly-xml, assembly-xsd, contribution-impl, contribution-java, contribution-namespace, core, core-databinding, definitions, domain, domain-api, domain-impl, extension-helper, host-embedded, interface-java-xml, interface-wsdl-xml, java2wsdl, node, node-impl, osgi-runtime, policy-security, policy-xml, topology, topology-xml, wsdl2java, binding-sca, binding-sca-xml) 4. Tuscany Extensions (binding-*. implementation-*, host-*, databinding-*, contribution-osgi) 5. 3rd Party Libraries (Axis2 etc) 6. Application contributions Do you know give the approx size of each bundle? The bundles that I have at the moment are: 1. org.apache.tuscany.sca.api.jar 14,942 bytes 2. org.apache.tuscany.sca.tuscany.corespi.jar 370,228 bytes 3. org.apache.tuscany.sca.tuscany.runtime.jar 571,159 bytes 4. org.apache.tuscany.sca.tuscany.extensions.jar 996,238 bytes 5. org.apache.tuscany.sca.tuscany.dependencies.jar 43,928,926 bytes From a packaging point of view, it doesn't make sense to split Tuscany, and it makes a lot more sense to split the 3rd party code. [snip] Based on the notes, I think the desired classloading hierarchy for Tuscany is: http://cwiki.apache.org/confluence/download/attachments/68801/desired-classloader.png You said desired classloading, can you help me understand the use cases that this structure will help with? I'm asking because I'm surprised to see the whole world in a single 3rd party libraries bundle, which I think is where we're going to see version conflicts. I'm also not sure about what steps I'd have to follow if I wanted to add a new extension to Tuscany with additional 3rd party libraries. I dont want to sound like I am doing a sales pitch for OSGi, but I am not sure there is a cleaner or easier way to sort out versioning issues that Tuscany would face if different versions of 3rd party libraries were used, compared to running Tuscany under OSGi. An OSGi runtime would enable different versions of 3rd party libraries, different versions of Tuscany runtime and different versions of Tuscany extensions to coexist in a single VM with very little extra effort. Implementing something similar with a classloader architecture outside of OSGi would be significantly more complex (and will eventually reinvent OSGi). The desired classloading hierarchy is based on Raymond's graph and the notes from Simon Nash and Simon Laws about static visibility (and non-visibility) from classes in the different bundles. It is the best you can get with a single-parent Java delegation model without running into ClassCastExceptions. If the 3rd party code is split into multiple classloaders, you would invariably need multi-parent or OSGi style classloading. You are absolutely right, apart from cleaning up Tuscany modularization, there would be no perceivable difference from enabling a multi-classloader framework for the Tuscany runtime (ignoring application classloading for the moment), when Tuscany is run outside of OSGi. In fact, I imagine the multi-classloader framework would probably never be used except for testing. So why go to all this trouble? In my opinion, the advantages of enabling a multi-classloader framework in Tuscany are: 1. Application contribution isolation based on the SCA contribution spec, regardless of whether the contribution is an OSGi bundle or not. 2. Enable Tuscany to be split into multiple bundles to enable Tuscany to run under OSGi with full modularity and versioning (rather than as a single bundle containing all of Tuscany and its dependencies) 3. Enable the use of a classloader hierarchy which matches everyone's understanding of Tuscany modularization, and adding tests which verify that this level of modularity is maintained. Raymond's graph and the other notes give an almost identical picture of the dependency relationship across bundles in Tuscany. But this does not match the current implementation, and the ad-hoc use of thread context classloaders and the sprinkling of someClass.getClassLoader() used in Class.forName/ClassLoader.loadClass throughout Tuscany make it difficult to modify the classloader hierarchy without pervasive code changes. With the proposed changes, there would be a clearer definition of class visibility across bundles. If there is a requirement to add new extensions with different versions of 3rd party libraries, but
Re: Classloading in Tuscany
On 10/23/07, Rajini Sivaram [EMAIL PROTECTED] wrote: Sebastien, Comments inline. On 10/22/07, Jean-Sebastien Delfino [EMAIL PROTECTED] wrote: I have two questions. [snip] Rajini Sivaram wrote: We have the following bundles in Tuscany - the names in brackets refer to maven module names 1. SCA API (sca-api) 2. Tuscany SPI (core-spi, assembly, contribution, policy, interface, interface-java, interface-wsdl, databinding) 3. Tuscany Runtime ( assembly-xml, assembly-xsd, contribution-impl, contribution-java, contribution-namespace, core, core-databinding, definitions, domain, domain-api, domain-impl, extension-helper, host-embedded, interface-java-xml, interface-wsdl-xml, java2wsdl, node, node-impl, osgi-runtime, policy-security, policy-xml, topology, topology-xml, wsdl2java, binding-sca, binding-sca-xml) 4. Tuscany Extensions (binding-*. implementation-*, host-*, databinding-*, contribution-osgi) 5. 3rd Party Libraries (Axis2 etc) 6. Application contributions Do you know give the approx size of each bundle? The bundles that I have at the moment are: 1. org.apache.tuscany.sca.api.jar 14,942 bytes 2. org.apache.tuscany.sca.tuscany.corespi.jar 370,228 bytes 3. org.apache.tuscany.sca.tuscany.runtime.jar 571,159 bytes 4. org.apache.tuscany.sca.tuscany.extensions.jar 996,238 bytes 5. org.apache.tuscany.sca.tuscany.dependencies.jar 43,928,926 bytes From a packaging point of view, it doesn't make sense to split Tuscany, and it makes a lot more sense to split the 3rd party code. [snip] Based on the notes, I think the desired classloading hierarchy for Tuscany is: http://cwiki.apache.org/confluence/download/attachments/68801/desired-classloader.png You said desired classloading, can you help me understand the use cases that this structure will help with? I'm asking because I'm surprised to see the whole world in a single 3rd party libraries bundle, which I think is where we're going to see version conflicts. I'm also not sure about what steps I'd have to follow if I wanted to add a new extension to Tuscany with additional 3rd party libraries. I dont want to sound like I am doing a sales pitch for OSGi, but I am not sure there is a cleaner or easier way to sort out versioning issues that Tuscany would face if different versions of 3rd party libraries were used, compared to running Tuscany under OSGi. An OSGi runtime would enable different versions of 3rd party libraries, different versions of Tuscany runtime and different versions of Tuscany extensions to coexist in a single VM with very little extra effort. Implementing something similar with a classloader architecture outside of OSGi would be significantly more complex (and will eventually reinvent OSGi). The desired classloading hierarchy is based on Raymond's graph and the notes from Simon Nash and Simon Laws about static visibility (and non-visibility) from classes in the different bundles. It is the best you can get with a single-parent Java delegation model without running into ClassCastExceptions. If the 3rd party code is split into multiple classloaders, you would invariably need multi-parent or OSGi style classloading. You are absolutely right, apart from cleaning up Tuscany modularization, there would be no perceivable difference from enabling a multi-classloader framework for the Tuscany runtime (ignoring application classloading for the moment), when Tuscany is run outside of OSGi. In fact, I imagine the multi-classloader framework would probably never be used except for testing. So why go to all this trouble? In my opinion, the advantages of enabling a multi-classloader framework in Tuscany are: 1. Application contribution isolation based on the SCA contribution spec, regardless of whether the contribution is an OSGi bundle or not. 2. Enable Tuscany to be split into multiple bundles to enable Tuscany to run under OSGi with full modularity and versioning (rather than as a single bundle containing all of Tuscany and its dependencies) 3. Enable the use of a classloader hierarchy which matches everyone's understanding of Tuscany modularization, and adding tests which verify that this level of modularity is maintained. Raymond's graph and the other notes give an almost identical picture of the dependency relationship across bundles in Tuscany. But this does not match the current implementation, and the ad-hoc use of thread context classloaders and the sprinkling of someClass.getClassLoader() used in Class.forName/ClassLoader.loadClass throughout Tuscany make it difficult to modify the classloader hierarchy without pervasive code changes. With the proposed changes, there would
Re: Classloading in Tuscany
This note is getting a bit long now. I added two comments inline and cut out some of the previous discussion. Simon Rajini Sivaram wrote: Simon, Comments inline... (cut) maven module names 1. SCA API (sca-api) 2. Tuscany SPI (core-spi, assembly, contribution, policy, interface, interface-java, interface-wsdl, databinding) Some of the above maven modules contain implementation code as well as SPI code. For example, in the assembly module, Service.java is an SPI and ServiceImpl.java is an implementation class. Yes, unfortunately many of these implementation classes are used outside of the SPI modules. At the moment the core-spi bundle that I use to run Tuscany under OSGi is forced to export all the packages from these modules, rather than just the SPI. eg. ComponentImpl from the assembly module along with SPI forms the base class of RuntimeComponentImpl in Runtime. ComponentTypeImpl from the assembly module is used by many extensions. For impl classes that are intended as extension points, we do have an approach used in some places where an empty SPI class extends the impl class and other modules extend the SPI class. Perhaps we could change all these places to use that approach. (cut) http://cwiki.apache.org/confluence/download/attachments/68801/tuscany-binding-ws-axis2-dependencies.png http://cwiki.apache.org/confluence/download/attachments/68801/tuscany-implementation-spring-dependencies.png These dependency diagrams show that either the extension modules are dependent on the Tuscany Runtime or I have the wrong list of modules for Core-SPI and Runtime. I looked at one of these dependencies. It's a helper class in implementation-java-xml that looks like it should be an SPI. There may be many others as well. In particular, I am sure that all the domain/node related code are in the wrong place, and I will sort those out later. We should go through all these uses and decide if they are correct. If they are, we should move these impl classes to the SPI, or create new SPI classes that provide the same functionality. Simon - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Classloading in Tuscany
Simon, Shall I work on the classloading changes with the extension classloader as a child of Tuscany Runtime (rather than the SPI), and look at separating the Runtime and SPI properly later? I would like to keep Core-SPI and Runtime as two different bundles, so that when running under OSGi, the dependencies will be specified explicitly (making it slightly simpler to remove the dependencies later on). The alternative is to clean up the SPI first before working on the classloader changes. What do you think? Thank you... Regards, Rajini On 10/23/07, Simon Nash [EMAIL PROTECTED] wrote: This note is getting a bit long now. I added two comments inline and cut out some of the previous discussion. Simon Rajini Sivaram wrote: Simon, Comments inline... (cut) maven module names 1. SCA API (sca-api) 2. Tuscany SPI (core-spi, assembly, contribution, policy, interface, interface-java, interface-wsdl, databinding) Some of the above maven modules contain implementation code as well as SPI code. For example, in the assembly module, Service.java is an SPI and ServiceImpl.java is an implementation class. Yes, unfortunately many of these implementation classes are used outside of the SPI modules. At the moment the core-spi bundle that I use to run Tuscany under OSGi is forced to export all the packages from these modules, rather than just the SPI. eg. ComponentImpl from the assembly module along with SPI forms the base class of RuntimeComponentImpl in Runtime. ComponentTypeImpl from the assembly module is used by many extensions. For impl classes that are intended as extension points, we do have an approach used in some places where an empty SPI class extends the impl class and other modules extend the SPI class. Perhaps we could change all these places to use that approach. (cut) http://cwiki.apache.org/confluence/download/attachments/68801/tuscany-binding-ws-axis2-dependencies.png http://cwiki.apache.org/confluence/download/attachments/68801/tuscany-implementation-spring-dependencies.png These dependency diagrams show that either the extension modules are dependent on the Tuscany Runtime or I have the wrong list of modules for Core-SPI and Runtime. I looked at one of these dependencies. It's a helper class in implementation-java-xml that looks like it should be an SPI. There may be many others as well. In particular, I am sure that all the domain/node related code are in the wrong place, and I will sort those out later. We should go through all these uses and decide if they are correct. If they are, we should move these impl classes to the SPI, or create new SPI classes that provide the same functionality. Simon - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Classloading in Tuscany
*Classloading in Tuscany - Application contribution classloaders* *Current implementation* Application classes from contributions are loaded by Tuscany in ClassReferenceModelResolver. At the moment, this uses the thread context classloader, which is typically set as the Java application classloader (based on CLASSPATH). So contribution classes are only loaded if found on the classpath. And there is no restriction on visibility across application contributions (the import/export statements in sca-contribution.xml have no effect on class visibility). *Requirement for application classloading* SCA specification requires contribution import/exports to be explicitly specified in sca-contribution.xml. There is no parent-child relationship between contributions, so the class-space visible to an application contribution consists of all the classes in the contribution plus all its imported packages (similar to OSGi bundles). SCA contributions can refer to classes that are not contained in SCA contributions - so unlike OSGi bundles, SCA contributions require access to classes specified on CLASSPATH. It should be possible for application classes in one contribution to refer to classes in other contributions, without resorting to dynamic classloading. Dynamic classloading will automatically work using the contribution classloader once the static visibility is sorted out. *Proposed changes* SCA contribution import/export spec cannot be implemented using a standard Java parent-child classloader delegation model. But SCA contribution import/export spec is a subset of OSGi package import/export (wiring of import/export is more complex in OSGi since it includes versions and other attributes). Hence an OSGi-style classloader is ideal for Tuscany to enforce SCA contribution spec. Each contribution will have an associated classloader. This will be an subclass of URLClassLoader, and will have the Java application classloader based on CLASSPATH as its parent (the parent classloader will be obtained from the thread context). The defining classloader for any application class will be the classloader corresponding to the SCA contribution containing the class. ContributionClassLoader.findClass will search the contribution for the class, and if not found, it will search other classloaders of other contributions wired using SCA import/export. Like OSGi, an overlapping class space will be defined for each contribution which consists of the classes in the contribution and imported packages from other contributions. Unlike the other proposed classloading changes which retain the ability to use a single classloader, this change will remove the option of loading applications using a common thread context or application classloader. *Testing* 1. Verify that existing tests and samples work without change. 2. Verify that imported packages are visible from contributions (both static and dynamic loading). 3. Verify that packages which are not explicitly imported from another contribution are not visible. 4. Verify that contribution classes can be loaded even if they are not on CLASSPATH *Questions* 1. It is necessary to have separate classloaders for contributions to enforce the SCA contribution spec. But for application isolation, it is sufficient o have one classloader per contribution? What is an APPLICATION in Tuscany? Should the isolation be at the composite level rather than contribution level? 2. Is there a better way for Tuscany contributions to specify external dependencies instead of using CLASSPATH? The downside of having Java application classloader as the parent of contribution classloaders is that there can potentially be two classes with the same qualified name reachable from the contribution classloader if all contributions were added to the CLASSPATH. This is not really a problem as long as imports/exports are properly specified for contributions, but it can result in ClassCastException or NoClassDefFoundError if unimported classes from other contributions are accessed by adding them to CLASSPATH. 3. Should there be a configuration option to override this and use a single thread context classloader that retains the current semantics? Does Tuscany have any means of setting system-wide configuration options? Thank you... Regards, Rajini
Re: Classloading in Tuscany
Simon, I would like to retain two bundles and hence two separate classloaders for SPI and Runtime under OSGi. I will use a single classloader for SPI and Runtime outside of OSGi. Thank you... Regards, Rajini On 10/23/07, Simon Nash [EMAIL PROTECTED] wrote: Rajini Sivaram wrote: Simon, Shall I work on the classloading changes with the extension classloader as a child of Tuscany Runtime (rather than the SPI), and look at separating the Runtime and SPI properly later? I would like to keep Core-SPI and Runtime as two different bundles, so that when running under OSGi, the dependencies will be specified explicitly (making it slightly simpler to remove the dependencies later on). The picture you posted in http://cwiki.apache.org/confluence/download/attachments/68801/proposed-classloader.png for your initial implementation proposal has the extension classloader as a child of the Tuscany runtime classloader, and the runtime classloader as a child of the Tuscany SPI classloader. When running outside of the OSGi environment, I don't think it is worth having separate classloaders for Tuscany runtime and Tuscany SPI in the initial implementation, until we have resolved the separation issues. If you want to keep these separate as OSGi bundles, and run them under separate OSGi classloaders in the OSGi environment, I'm OK with that. Are you proposing that there would be separate classloaders for SPI and runtime when running under OSGi, but only one classloader for both of these when running outside OSGi? Or are you proposing that in both cases there would be two separate classloaders? I'm sorry that I have not quite understood what you are proposing here. The alternative is to clean up the SPI first before working on the classloader changes. What do you think? I think you should start on the new classloader structure now, as Ant has said. The SPI cleanup is likely to be quite a lot of work, so it makes more sense to do that as a second round. Simon Thank you... Regards, Rajini On 10/23/07, Simon Nash [EMAIL PROTECTED] wrote: This note is getting a bit long now. I added two comments inline and cut out some of the previous discussion. Simon Rajini Sivaram wrote: Simon, Comments inline... (cut) maven module names 1. SCA API (sca-api) 2. Tuscany SPI (core-spi, assembly, contribution, policy, interface, interface-java, interface-wsdl, databinding) Some of the above maven modules contain implementation code as well as SPI code. For example, in the assembly module, Service.java is an SPI and ServiceImpl.java is an implementation class. Yes, unfortunately many of these implementation classes are used outside of the SPI modules. At the moment the core-spi bundle that I use to run Tuscany under OSGi is forced to export all the packages from these modules, rather than just the SPI. eg. ComponentImpl from the assembly module along with SPI forms the base class of RuntimeComponentImpl in Runtime. ComponentTypeImpl from the assembly module is used by many extensions. For impl classes that are intended as extension points, we do have an approach used in some places where an empty SPI class extends the impl class and other modules extend the SPI class. Perhaps we could change all these places to use that approach. (cut) http://cwiki.apache.org/confluence/download/attachments/68801/tuscany-binding-ws-axis2-dependencies.png http://cwiki.apache.org/confluence/download/attachments/68801/tuscany-implementation-spring-dependencies.png These dependency diagrams show that either the extension modules are dependent on the Tuscany Runtime or I have the wrong list of modules for Core-SPI and Runtime. I looked at one of these dependencies. It's a helper class in implementation-java-xml that looks like it should be an SPI. There may be many others as well. In particular, I am sure that all the domain/node related code are in the wrong place, and I will sort those out later. We should go through all these uses and decide if they are correct. If they are, we should move these impl classes to the SPI, or create new SPI classes that provide the same functionality. Simon - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Classloading in Tuscany
Sounds good. My answers to your questions are below. Simon Rajini Sivaram wrote: *Classloading in Tuscany - Application contribution classloaders* *Current implementation* Application classes from contributions are loaded by Tuscany in ClassReferenceModelResolver. At the moment, this uses the thread context classloader, which is typically set as the Java application classloader (based on CLASSPATH). So contribution classes are only loaded if found on the classpath. And there is no restriction on visibility across application contributions (the import/export statements in sca-contribution.xml have no effect on class visibility). *Requirement for application classloading* SCA specification requires contribution import/exports to be explicitly specified in sca-contribution.xml. There is no parent-child relationship between contributions, so the class-space visible to an application contribution consists of all the classes in the contribution plus all its imported packages (similar to OSGi bundles). SCA contributions can refer to classes that are not contained in SCA contributions - so unlike OSGi bundles, SCA contributions require access to classes specified on CLASSPATH. It should be possible for application classes in one contribution to refer to classes in other contributions, without resorting to dynamic classloading. Dynamic classloading will automatically work using the contribution classloader once the static visibility is sorted out. *Proposed changes* SCA contribution import/export spec cannot be implemented using a standard Java parent-child classloader delegation model. But SCA contribution import/export spec is a subset of OSGi package import/export (wiring of import/export is more complex in OSGi since it includes versions and other attributes). Hence an OSGi-style classloader is ideal for Tuscany to enforce SCA contribution spec. Each contribution will have an associated classloader. This will be an subclass of URLClassLoader, and will have the Java application classloader based on CLASSPATH as its parent (the parent classloader will be obtained from the thread context). The defining classloader for any application class will be the classloader corresponding to the SCA contribution containing the class. ContributionClassLoader.findClass will search the contribution for the class, and if not found, it will search other classloaders of other contributions wired using SCA import/export. Like OSGi, an overlapping class space will be defined for each contribution which consists of the classes in the contribution and imported packages from other contributions. Unlike the other proposed classloading changes which retain the ability to use a single classloader, this change will remove the option of loading applications using a common thread context or application classloader. *Testing* 1. Verify that existing tests and samples work without change. 2. Verify that imported packages are visible from contributions (both static and dynamic loading). 3. Verify that packages which are not explicitly imported from another contribution are not visible. 4. Verify that contribution classes can be loaded even if they are not on CLASSPATH *Questions* 1. It is necessary to have separate classloaders for contributions to enforce the SCA contribution spec. But for application isolation, it is sufficient o have one classloader per contribution? What is an APPLICATION in Tuscany? Should the isolation be at the composite level rather than contribution level? Doing the isolation at the contribution level sounds fine. 2. Is there a better way for Tuscany contributions to specify external dependencies instead of using CLASSPATH? The downside of having Java application classloader as the parent of contribution classloaders is that there can potentially be two classes with the same qualified name reachable from the contribution classloader if all contributions were added to the CLASSPATH. This is not really a problem as long as imports/exports are properly specified for contributions, but it can result in ClassCastException or NoClassDefFoundError if unimported classes from other contributions are accessed by adding them to CLASSPATH. This seems OK. 3. Should there be a configuration option to override this and use a single thread context classloader that retains the current semantics? Does Tuscany have any means of setting system-wide configuration options? More options add more complexity. Let's keep this simple and go with the new approach only unless there's a use case that requires the other setting. Simon Thank you... Regards, Rajini - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Classloading in Tuscany
Sebastien, I think we could implement the following classloading changes to Tuscany (in this order). I will post a more detailed proposal (along with some questions) based on the feedback. 1. Application classloading - move from a single thread context based classloader to OSGi-style multiple-classloader framework 2. Tuscany runtime classloading framework - enable the use of multiple classloaders, with an API in host-embedded or the new domain APIs to specify multiple runtime/extension classloaders 3. Reimplement Tuscany runtime extension mechanism so that SPI classloader does not require visibility of extension modules. 4. Remove the use of thread context classloader inside Tuscany - use specific classloaders based on what is being loaded. Thread context classloader will be the parent of all classloaders used in Tuscany to enable applications as well as 3rd party code to continue to use it. 5. Enable extensions to be packaged as separate OSGi bundles with separate classloaders, but with OSGi-defined package dependencies across extension modules. Default classloading for Tuscany runtime+extensions (CLASSPATH based single Java application classloader) will continue to be used for all existing tests and samples, but new tests will be added to test classloader-based isolation. Thank you... Regards, Rajini On 10/19/07, Jean-Sebastien Delfino [EMAIL PROTECTED] wrote: I wanted to summarize this thread as it has been pretty popular - I guess we all know what a classloader is and are happy to talk about it :) - but I am getting lost in the various exchanges. Could anybody please help provide 2 or 3 short sentences summarizing the first 2 or 3 steps that are going to be implemented? Thanks... Simon Laws wrote: On 10/18/07, Mike Edwards [EMAIL PROTECTED] wrote: Folks, Comments inline Simon Laws wrote: Hi Rajini Re. 4 on Simon's list. Maybe it is useful to more clearly distinguish between those Tuscany modules that are expect to be loaded statically, assembly, core, etc and those that expected to be loaded dynamically, binding.?, implementation.? etc. I find the term module a little unsatisfactory. Raymond, in his diagram, used Tuscany core and Tuscany extension and in a previous post used Tuscany runtime and Tuscany extension. I prefer the latter pair just because we have a maven module called core. +1 This leads to a 4a and 4b based on Raymond's post/diagram 4a Tuscany extension module code shouldn't be able to see other extension modules (not sure what the dotted line on the diagram implies but I expect that it's to do with modules like binding-ws-axis2 and binding-ws interacting) or application code or Tuscany runtime code other than via the SPI. Hmm, first, this ain't the case today and it will need some thought. The Java extensions do share code and it would be crazy for them not to share the code. So, Spring uses stuff out of the base Java extension - and I am sure that other Java type extensions would want to do the same. In an OSGi world, it would be fine to express the dependency in a simple way. For non-OSGi I'm not sure of the best route. I suspect that other extension types may want to share stuff as well. Agreed. Hence I pointed out the relationship between binding-ws-axis2 and binding-ws. There are loose groups of software spread across multiple maven modules that just represent modularization of the software for clarity and reuse purposes. Then there are the modules that are intended to be loaded as extensions. Not all maven modules are create equal :-) The non OSGi world is managed by the dependencies that appear in out maven pom files. Without this dependency tree you just have to know that, for example, binding-ws has to be on the classpath when you also include binding-ws-xml which is in turn a dependency of binding-ws-axis2. Nothing too unusual there until you start talking about having separate class loaders for each extension as has been discussed previously in this thread. You really need to understand what an extension is, i.e. it is unlikely to be a single maven module. 4b Tuscany runtime code shouldn't be able to see Tuscany extension code or application code. That sounds a bit odd. Perhaps I've not got the right end of the stick, but the some code - either core and or extensions has to get very intimate with the application code. Introspection, instantiation, injection - all has to be done either by core code or extension code. Perhaps I've not understood the separation you're looking for? This should say shouldn't be able to statically see... I had imagined that these are all of the implementation modules that sit behind the SPI Then, from reading your comments, we have to be clearer about what the SPI is providing an
Re: Classloading in Tuscany
Rajini Sivaram wrote: Sebastien, I think we could implement the following classloading changes to Tuscany (in this order). I will post a more detailed proposal (along with some questions) based on the feedback. 1. Application classloading - move from a single thread context based classloader to OSGi-style multiple-classloader framework Am I correct in thinking that the intention is to enable this but not require it? Move suggests it might be required. 2. Tuscany runtime classloading framework - enable the use of multiple classloaders, with an API in host-embedded or the new domain APIs to specify multiple runtime/extension classloaders I'd need to see more details on this before I can comment. I'm wondering how much of the Tuscany runtime's classloading mechanism for its own classes should be controllable by external APIs. 3. Reimplement Tuscany runtime extension mechanism so that SPI classloader does not require visibility of extension modules. Sounds good. 4. Remove the use of thread context classloader inside Tuscany - use specific classloaders based on what is being loaded. Thread context classloader will be the parent of all classloaders used in Tuscany to enable applications as well as 3rd party code to continue to use it. Can you give a bit more detail about the scenarios in which this parenting is needed? Is it needed to make Tuscany classloading work correctly, or to make third party code classloading work correctly? 5. Enable extensions to be packaged as separate OSGi bundles with separate classloaders, but with OSGi-defined package dependencies across extension modules. Sounds good. Default classloading for Tuscany runtime+extensions (CLASSPATH based single Java application classloader) will continue to be used for all existing tests and samples, but new tests will be added to test classloader-based isolation. Sounds good as a first step. Simon Thank you... Regards, Rajini On 10/19/07, Jean-Sebastien Delfino [EMAIL PROTECTED] wrote: I wanted to summarize this thread as it has been pretty popular - I guess we all know what a classloader is and are happy to talk about it :) - but I am getting lost in the various exchanges. Could anybody please help provide 2 or 3 short sentences summarizing the first 2 or 3 steps that are going to be implemented? Thanks... Simon Laws wrote: On 10/18/07, Mike Edwards [EMAIL PROTECTED] wrote: Folks, Comments inline Simon Laws wrote: Hi Rajini Re. 4 on Simon's list. Maybe it is useful to more clearly distinguish between those Tuscany modules that are expect to be loaded statically, assembly, core, etc and those that expected to be loaded dynamically, binding.?, implementation.? etc. I find the term module a little unsatisfactory. Raymond, in his diagram, used Tuscany core and Tuscany extension and in a previous post used Tuscany runtime and Tuscany extension. I prefer the latter pair just because we have a maven module called core. +1 This leads to a 4a and 4b based on Raymond's post/diagram 4a Tuscany extension module code shouldn't be able to see other extension modules (not sure what the dotted line on the diagram implies but I expect that it's to do with modules like binding-ws-axis2 and binding-ws interacting) or application code or Tuscany runtime code other than via the SPI. Hmm, first, this ain't the case today and it will need some thought. The Java extensions do share code and it would be crazy for them not to share the code. So, Spring uses stuff out of the base Java extension - and I am sure that other Java type extensions would want to do the same. In an OSGi world, it would be fine to express the dependency in a simple way. For non-OSGi I'm not sure of the best route. I suspect that other extension types may want to share stuff as well. Agreed. Hence I pointed out the relationship between binding-ws-axis2 and binding-ws. There are loose groups of software spread across multiple maven modules that just represent modularization of the software for clarity and reuse purposes. Then there are the modules that are intended to be loaded as extensions. Not all maven modules are create equal :-) The non OSGi world is managed by the dependencies that appear in out maven pom files. Without this dependency tree you just have to know that, for example, binding-ws has to be on the classpath when you also include binding-ws-xml which is in turn a dependency of binding-ws-axis2. Nothing too unusual there until you start talking about having separate class loaders for each extension as has been discussed previously in this thread. You really need to understand what an extension is, i.e. it is unlikely to be a single maven module. 4b Tuscany runtime code shouldn't be able to see Tuscany extension code or application code. That sounds a bit odd. Perhaps I've not got the
Re: Classloading in Tuscany
*An overview of the proposed classloader design for Tuscany* Thank you for all your emails. Based on your feedback, I would like to propose a new classloader architecture for Tuscany. I have created new bundles in OSGi to reflect the kind of classloader-based isolation that we may like to have, and if acceptable, I will add support to provide this without OSGi. Simon didn't like the word modules being used to describe the level of granularity for classloaders since that clashes with maven modules which are more fine-grained. So I think in spite of the confusion that it may create, I will use bundle to refer to a list of modules that we want to treat as a collection, where each bundle can have an associated classloader. When running under OSGi, each bundle will correspond to one OSGi bundle. We have the following bundles in Tuscany - the names in brackets refer to maven module names 1. SCA API (sca-api) 2. Tuscany SPI (core-spi, assembly, contribution, policy, interface, interface-java, interface-wsdl, databinding) 3. Tuscany Runtime ( assembly-xml, assembly-xsd, contribution-impl, contribution-java, contribution-namespace, core, core-databinding, definitions, domain, domain-api, domain-impl, extension-helper, host-embedded, interface-java-xml, interface-wsdl-xml, java2wsdl, node, node-impl, osgi-runtime, policy-security, policy-xml, topology, topology-xml, wsdl2java, binding-sca, binding-sca-xml) 4. Tuscany Extensions (binding-*. implementation-*, host-*, databinding-*, contribution-osgi) 5. 3rd Party Libraries (Axis2 etc) 6. Application contributions By default, Tuscany will continue to run using a single classloader with all required classes on the CLASSPATH. But it will also be possible to run Tuscany using five different classloaders for the five bundles. Applications will always be run using separate classloaders, created by Tuscany. All existing samples and itests will continue to run using a single classloader. But a new set of tests will be added for classloading which checks if Tuscany runs with multiple classloaders and verifies that all the isolation requirements are met. Based on the notes, I think the desired classloading hierarchy for Tuscany is: http://cwiki.apache.org/confluence/download/attachments/68801/desired-classloader.png The solid lines show parent-child relationship used for standard Java classloader delegation, providing static visibility. The dotted lines show dependencies which are more targetted, and preferably avoided where possible. 3rd party code could potentially be split across multiple classloaders, and these could be inserted anywhere in the hierarchy as long as SPI, Runtime and Extensions can see the code they require. Tuscany modules will continue to expect to see these dependencies from the classloader of the module (from Tuscany runtime and Tuscany extensions). I have generated a few dependency diagrams for Tuscany modules, and these dont exactly match the requirements that have been specified in the notes. In particular, it seems to me that the line between Tuscany-SPI and Tuscany Runtime is rather blurred (or I haven't understood the separation correctly). The dependency diagram for the whole of Tuscany/modules is : http://cwiki.apache.org/confluence/download/attachments/68801/tuscany-dependencies.png The modules are listed in four columns, the first one is SCA-API and Tuscany SPI, where the dependencies coming in from the right are expected, and there are no dependencies going to the right. The second column is Tuscany Runtime, and the third and fourth ones show the extensions. Sorry, the diagram is a bit blurred, but if you download it and zoom in, you can see the arrows going into the runtime column from the extensions. And there are many of them. To give a better idea of the kind of dependencies in Tuscany, I have created two separate dependency diagrams for binding-ws-axis2 and implementation-spring: http://cwiki.apache.org/confluence/download/attachments/68801/tuscany-binding-ws-axis2-dependencies.png http://cwiki.apache.org/confluence/download/attachments/68801/tuscany-implementation-spring-dependencies.png These dependency diagrams show that either the extension modules are dependent on the Tuscany Runtime or I have the wrong list of modules for Core-SPI and Runtime. Based on the dependencies that we have today, I would like to propose the following classloader hierarchy for the initial implementation: http://cwiki.apache.org/confluence/download/attachments/68801/proposed-classloader.png I am assuming that Tuscany Extension modules will not be run under multiple classloaders, except using OSGi (where cross-module dependencies can be specified at the package level). The dependencies across extension modules are actually not bad at all, they form clusters (java based implementations at the top of the third column, webservices
Re: Classloading in Tuscany
Simon, Comments inline. Thank you... Regards, Rajini On 10/22/07, Simon Nash [EMAIL PROTECTED] wrote: Rajini Sivaram wrote: Sebastien, I think we could implement the following classloading changes to Tuscany (in this order). I will post a more detailed proposal (along with some questions) based on the feedback. 1. Application classloading - move from a single thread context based classloader to OSGi-style multiple-classloader framework Am I correct in thinking that the intention is to enable this but not require it? Move suggests it might be required. I will submit detailed proposals for each of the changes. My intention was to modify contribution classloading in Tuscany, so that Tuscany created separate classloaders for the contributions. After the changes, it will no longer be possible to run multiple contributions in a single classloader. This is different from the proposed changes for Tuscany runtime classloading which was enabling the use of multiple classloaders, without requiring them. 2. Tuscany runtime classloading framework - enable the use of multiple classloaders, with an API in host-embedded or the new domain APIs to specify multiple runtime/extension classloaders I'd need to see more details on this before I can comment. I'm wondering how much of the Tuscany runtime's classloading mechanism for its own classes should be controllable by external APIs. It is not necessary to externalize the API, it could be an SPI used purely for testing. The externally visible use of the multi-classloader framework could be purely under OSGi (where classloaders will be registered by bundle activators and no additional API is required). At the moment, to create an EmbeddedSCADomain, there is an API which specifies the runtimeClassLoader: public EmbeddedSCADomain(ClassLoader runtimeClassLoader, String domainURI) This is specifying the classloader where all Tuscany related classes can be found. What I would like (at least for testing) is something like: public EmbeddedSCADomain(ClassLoader runtimeClassLoader, ClassLoader[] extensionClassLoaders, Class, String domainURI) 3. Reimplement Tuscany runtime extension mechanism so that SPI classloader does not require visibility of extension modules. Sounds good. 4. Remove the use of thread context classloader inside Tuscany - use specific classloaders based on what is being loaded. Thread context classloader will be the parent of all classloaders used in Tuscany to enable applications as well as 3rd party code to continue to use it. Can you give a bit more detail about the scenarios in which this parenting is needed? Is it needed to make Tuscany classloading work correctly, or to make third party code classloading work correctly? The goal of this work is to remove the use of thread context classloaders in Tuscany so that Tuscany itself does not load any classes using it. But many 3rd party libraries which Tuscany depends on, use the thread context classloader. eg. javax.xml.stream uses thread context classloader to find XMLOutputFactory/XMLInputFactory implementation classes (requiring 3rd party code to be available through the thread context classloader), and Axis2 uses thread context classloader to find Tuscany's message receivers like org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceInOutSyncMessageReceiver(requiring Tuscany extensions to be available through the thread context classloader). Applications or third party libraries used by applications could also have a dependency on the context classloader. 5. Enable extensions to be packaged as separate OSGi bundles with separate classloaders, but with OSGi-defined package dependencies across extension modules. Sounds good. Default classloading for Tuscany runtime+extensions (CLASSPATH based single Java application classloader) will continue to be used for all existing tests and samples, but new tests will be added to test classloader-based isolation. Sounds good as a first step. Simon Thank you... Regards, Rajini On 10/19/07, Jean-Sebastien Delfino [EMAIL PROTECTED] wrote: I wanted to summarize this thread as it has been pretty popular - I guess we all know what a classloader is and are happy to talk about it :) - but I am getting lost in the various exchanges. Could anybody please help provide 2 or 3 short sentences summarizing the first 2 or 3 steps that are going to be implemented? Thanks... Simon Laws wrote: On 10/18/07, Mike Edwards [EMAIL PROTECTED] wrote: Folks, Comments inline Simon Laws wrote: Hi Rajini Re. 4 on Simon's list. Maybe it is useful to more clearly distinguish between those Tuscany modules that are expect to be loaded statically, assembly, core, etc and those that expected to be loaded dynamically, binding.?, implementation.? etc. I find the term module a little unsatisfactory.
Re: Classloading in Tuscany
Thanks for these clarifications. One question inline below. Simon Rajini Sivaram wrote: Simon, Comments inline. Thank you... Regards, Rajini On 10/22/07, Simon Nash [EMAIL PROTECTED] wrote: Rajini Sivaram wrote: Sebastien, I think we could implement the following classloading changes to Tuscany (in this order). I will post a more detailed proposal (along with some questions) based on the feedback. 1. Application classloading - move from a single thread context based classloader to OSGi-style multiple-classloader framework Am I correct in thinking that the intention is to enable this but not require it? Move suggests it might be required. I will submit detailed proposals for each of the changes. My intention was to modify contribution classloading in Tuscany, so that Tuscany created separate classloaders for the contributions. After the changes, it will no longer be possible to run multiple contributions in a single classloader. This is different from the proposed changes for Tuscany runtime classloading which was enabling the use of multiple classloaders, without requiring them. 2. Tuscany runtime classloading framework - enable the use of multiple classloaders, with an API in host-embedded or the new domain APIs to specify multiple runtime/extension classloaders I'd need to see more details on this before I can comment. I'm wondering how much of the Tuscany runtime's classloading mechanism for its own classes should be controllable by external APIs. It is not necessary to externalize the API, it could be an SPI used purely for testing. The externally visible use of the multi-classloader framework could be purely under OSGi (where classloaders will be registered by bundle activators and no additional API is required). At the moment, to create an EmbeddedSCADomain, there is an API which specifies the runtimeClassLoader: public EmbeddedSCADomain(ClassLoader runtimeClassLoader, String domainURI) This is specifying the classloader where all Tuscany related classes can be found. What I would like (at least for testing) is something like: public EmbeddedSCADomain(ClassLoader runtimeClassLoader, ClassLoader[] extensionClassLoaders, Class, String domainURI) 3. Reimplement Tuscany runtime extension mechanism so that SPI classloader does not require visibility of extension modules. Sounds good. 4. Remove the use of thread context classloader inside Tuscany - use specific classloaders based on what is being loaded. Thread context classloader will be the parent of all classloaders used in Tuscany to enable applications as well as 3rd party code to continue to use it. Can you give a bit more detail about the scenarios in which this parenting is needed? Is it needed to make Tuscany classloading work correctly, or to make third party code classloading work correctly? The goal of this work is to remove the use of thread context classloaders in Tuscany so that Tuscany itself does not load any classes using it. But many 3rd party libraries which Tuscany depends on, use the thread context classloader. eg. javax.xml.stream uses thread context classloader to find XMLOutputFactory/XMLInputFactory implementation classes (requiring 3rd party code to be available through the thread context classloader), and Axis2 uses thread context classloader to find Tuscany's message receivers like org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceInOutSyncMessageReceiver(requiring Tuscany extensions to be available through the thread context classloader). Applications or third party libraries used by applications could also have a dependency on the context classloader. How does having the thread context classloader as the parent of Tuscany's classloaders help with this? If the third party code uses the thread context classloader, it won't see any Tuscany classloaders that are children of the thread context classloader. Simon 5. Enable extensions to be packaged as separate OSGi bundles with separate classloaders, but with OSGi-defined package dependencies across extension modules. Sounds good. Default classloading for Tuscany runtime+extensions (CLASSPATH based single Java application classloader) will continue to be used for all existing tests and samples, but new tests will be added to test classloader-based isolation. Sounds good as a first step. Simon Thank you... Regards, Rajini On 10/19/07, Jean-Sebastien Delfino [EMAIL PROTECTED] wrote: I wanted to summarize this thread as it has been pretty popular - I guess we all know what a classloader is and are happy to talk about it :) - but I am getting lost in the various exchanges. Could anybody please help provide 2 or 3 short sentences summarizing the first 2 or 3 steps that are going to be implemented? Thanks... Simon Laws wrote: On 10/18/07, Mike Edwards [EMAIL PROTECTED] wrote: Folks, Comments inline Simon Laws wrote: Hi
Re: Classloading in Tuscany
Thanks for all your work on progressing this. Comments inline. Simon Rajini Sivaram wrote: *An overview of the proposed classloader design for Tuscany* Thank you for all your emails. Based on your feedback, I would like to propose a new classloader architecture for Tuscany. I have created new bundles in OSGi to reflect the kind of classloader-based isolation that we may like to have, and if acceptable, I will add support to provide this without OSGi. Simon didn't like the word modules being used to describe the level of granularity for classloaders since that clashes with maven modules which are more fine-grained. So I think in spite of the confusion that it may create, I will use bundle to refer to a list of modules that we want to treat as a collection, where each bundle can have an associated classloader. When running under OSGi, each bundle will correspond to one OSGi bundle. We have the following bundles in Tuscany - the names in brackets refer to maven module names 1. SCA API (sca-api) 2. Tuscany SPI (core-spi, assembly, contribution, policy, interface, interface-java, interface-wsdl, databinding) Some of the above maven modules contain implementation code as well as SPI code. For example, in the assembly module, Service.java is an SPI and ServiceImpl.java is an implementation class. 3. Tuscany Runtime ( assembly-xml, assembly-xsd, contribution-impl, contribution-java, contribution-namespace, core, core-databinding, definitions, domain, domain-api, domain-impl, extension-helper, host-embedded, interface-java-xml, interface-wsdl-xml, java2wsdl, node, node-impl, osgi-runtime, policy-security, policy-xml, topology, topology-xml, wsdl2java, binding-sca, binding-sca-xml) 4. Tuscany Extensions (binding-*. implementation-*, host-*, databinding-*, contribution-osgi) 5. 3rd Party Libraries (Axis2 etc) 6. Application contributions By default, Tuscany will continue to run using a single classloader with all required classes on the CLASSPATH. But it will also be possible to run Tuscany using five different classloaders for the five bundles. Applications will always be run using separate classloaders, created by Tuscany. All existing samples and itests will continue to run using a single classloader. But a new set of tests will be added for classloading which checks if Tuscany runs with multiple classloaders and verifies that all the isolation requirements are met. There are 6 bundles listed above, but this paragraph refers to five bundles. Did you mean to say six bundles here? Based on the notes, I think the desired classloading hierarchy for Tuscany is: http://cwiki.apache.org/confluence/download/attachments/68801/desired-classloader.png The solid lines show parent-child relationship used for standard Java classloader delegation, providing static visibility. The dotted lines show dependencies which are more targetted, and preferably avoided where possible. 3rd party code could potentially be split across multiple classloaders, and these could be inserted anywhere in the hierarchy as long as SPI, Runtime and Extensions can see the code they require. Tuscany modules will continue to expect to see these dependencies from the classloader of the module (from Tuscany runtime and Tuscany extensions). I have generated a few dependency diagrams for Tuscany modules, and these dont exactly match the requirements that have been specified in the notes. In particular, it seems to me that the line between Tuscany-SPI and Tuscany Runtime is rather blurred (or I haven't understood the separation correctly). The dependency diagram for the whole of Tuscany/modules is : http://cwiki.apache.org/confluence/download/attachments/68801/tuscany-dependencies.png The modules are listed in four columns, the first one is SCA-API and Tuscany SPI, where the dependencies coming in from the right are expected, and there are no dependencies going to the right. The second column is Tuscany Runtime, and the third and fourth ones show the extensions. Sorry, the diagram is a bit blurred, but if you download it and zoom in, you can see the arrows going into the runtime column from the extensions. And there are many of them. This seems be the opposite case of my comment above. Some of the runtime code is exposing classes that are used as pseudo-SPIs by other code. One of the huge benefits of this exercise is that it is exposing these cases so that we can look at them and decide what we should do about them. To give a better idea of the kind of dependencies in Tuscany, I have created two separate dependency diagrams for binding-ws-axis2 and implementation-spring: http://cwiki.apache.org/confluence/download/attachments/68801/tuscany-binding-ws-axis2-dependencies.png http://cwiki.apache.org/confluence/download/attachments/68801/tuscany-implementation-spring-dependencies.png These dependency diagrams show
Re: Classloading in Tuscany
On 10/22/07, Simon Nash [EMAIL PROTECTED] wrote: Thanks for these clarifications. One question inline below. Simon Rajini Sivaram wrote: Simon, Comments inline. Thank you... Regards, Rajini On 10/22/07, Simon Nash [EMAIL PROTECTED] wrote: Rajini Sivaram wrote: Sebastien, I think we could implement the following classloading changes to Tuscany (in this order). I will post a more detailed proposal (along with some questions) based on the feedback. 1. Application classloading - move from a single thread context based classloader to OSGi-style multiple-classloader framework Am I correct in thinking that the intention is to enable this but not require it? Move suggests it might be required. I will submit detailed proposals for each of the changes. My intention was to modify contribution classloading in Tuscany, so that Tuscany created separate classloaders for the contributions. After the changes, it will no longer be possible to run multiple contributions in a single classloader. This is different from the proposed changes for Tuscany runtime classloading which was enabling the use of multiple classloaders, without requiring them. 2. Tuscany runtime classloading framework - enable the use of multiple classloaders, with an API in host-embedded or the new domain APIs to specify multiple runtime/extension classloaders I'd need to see more details on this before I can comment. I'm wondering how much of the Tuscany runtime's classloading mechanism for its own classes should be controllable by external APIs. It is not necessary to externalize the API, it could be an SPI used purely for testing. The externally visible use of the multi-classloader framework could be purely under OSGi (where classloaders will be registered by bundle activators and no additional API is required). At the moment, to create an EmbeddedSCADomain, there is an API which specifies the runtimeClassLoader: public EmbeddedSCADomain(ClassLoader runtimeClassLoader, String domainURI) This is specifying the classloader where all Tuscany related classes can be found. What I would like (at least for testing) is something like: public EmbeddedSCADomain(ClassLoader runtimeClassLoader, ClassLoader[] extensionClassLoaders, Class, String domainURI) 3. Reimplement Tuscany runtime extension mechanism so that SPI classloader does not require visibility of extension modules. Sounds good. 4. Remove the use of thread context classloader inside Tuscany - use specific classloaders based on what is being loaded. Thread context classloader will be the parent of all classloaders used in Tuscany to enable applications as well as 3rd party code to continue to use it. Can you give a bit more detail about the scenarios in which this parenting is needed? Is it needed to make Tuscany classloading work correctly, or to make third party code classloading work correctly? The goal of this work is to remove the use of thread context classloaders in Tuscany so that Tuscany itself does not load any classes using it. But many 3rd party libraries which Tuscany depends on, use the thread context classloader. eg. javax.xml.stream uses thread context classloader to find XMLOutputFactory/XMLInputFactory implementation classes (requiring 3rd party code to be available through the thread context classloader), and Axis2 uses thread context classloader to find Tuscany's message receivers like org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceInOutSyncMessageReceiver (requiring Tuscany extensions to be available through the thread context classloader). Applications or third party libraries used by applications could also have a dependency on the context classloader. How does having the thread context classloader as the parent of Tuscany's classloaders help with this? If the third party code uses the thread context classloader, it won't see any Tuscany classloaders that are children of the thread context classloader. I just read through what I wrote originally, and my last reply which was sort of unrelated to that statement, and realized why I have caused the confusion. The only classloaders I want to create from within Tuscany are contribution classloaders. I would expect contributions to have access to classes defined within the contribution, other explicitly imported classes from other contributions and other 3rd party code which may not be inside an SCA contribution (this is different from OSGi where all classes are exported by some bundle). At the moment, applications can refer to any class in CLASSPATH. I wanted to continue to support this. In my original statement, what I meant was that the parent of application classloaders created by Tuscany would be the Java application classloader based on CLASSPATH. In the
Re: Classloading in Tuscany
I have two questions. [snip] Rajini Sivaram wrote: We have the following bundles in Tuscany - the names in brackets refer to maven module names 1. SCA API (sca-api) 2. Tuscany SPI (core-spi, assembly, contribution, policy, interface, interface-java, interface-wsdl, databinding) 3. Tuscany Runtime ( assembly-xml, assembly-xsd, contribution-impl, contribution-java, contribution-namespace, core, core-databinding, definitions, domain, domain-api, domain-impl, extension-helper, host-embedded, interface-java-xml, interface-wsdl-xml, java2wsdl, node, node-impl, osgi-runtime, policy-security, policy-xml, topology, topology-xml, wsdl2java, binding-sca, binding-sca-xml) 4. Tuscany Extensions (binding-*. implementation-*, host-*, databinding-*, contribution-osgi) 5. 3rd Party Libraries (Axis2 etc) 6. Application contributions Do you know give the approx size of each bundle? [snip] Based on the notes, I think the desired classloading hierarchy for Tuscany is: http://cwiki.apache.org/confluence/download/attachments/68801/desired-classloader.png You said desired classloading, can you help me understand the use cases that this structure will help with? I'm asking because I'm surprised to see the whole world in a single 3rd party libraries bundle, which I think is where we're going to see version conflicts. I'm also not sure about what steps I'd have to follow if I wanted to add a new extension to Tuscany with additional 3rd party libraries. Thanks -- Jean-Sebastien - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Classloading in Tuscany
Simon, Thank you for your note. Yes, you are right, we should have a separate classloader for the SPI with its own visibility rules. In terms of static dependencies (these are shown in Raymond's graph), Tuscany modules are fairly neatly separated out. These are the compile-time dependencies in pom.xml, and Eclipse would throw up if there were any cyclic dependencies. From your list, 1. is currently not true, but can be easily fixed. 2., 3. and 5. are true. 4. is only partially true, because there are many dependencies across modules - for instance, implementation.spring and implementation.osgi use code from implementation.java. But for dynamic classloading, the dependencies are not so straightforward, and any classloader-based isolation has to handle either dynamic visibility or access to classloaders which have the visibility. An example of the difference between static and dynamic dependencies is 3. Tuscany SPIs dont need static access to Tuscany runtime code, but there is code in tuscany-core-spi which loads classes from the runtime modules. Here is an example: * DefaultExtensionPointRegistry.getExtensionPoint(ClassT extensionPointType): * *Class? extensionPointClass = Class.forName(classNames.iterator().next(), **true**, classLoader);* **Here, the classloader used is the classloader of extensionPointType which is from the SPI. But the class being loaded is from a runtime module. This type of dynamic classloading is used in many places in Tuscany, and they work at the moment because all modules including the SPI are loaded using a single classloader. In this case, SPI doesn't need to see the classes from the runtime module, but it needs to know how to obtain the classloader which can see those classes. Thank you... Regards, Rajini On 10/17/07, Simon Nash [EMAIL PROTECTED] wrote: I'm just catching up with this very interesting thread. Comments inline. Rajini Sivaram wrote: Sebastien, I have the second path - (multiple application loaders, one runtime loader) working in my sandbox. I need to write some tests and run all the existing tests before I submit the patch. This works without OSGi, and is a very minor change. For the first path, I am still running under OSGi. At the moment I have four different scenarios (they are all running tests using Axis2 binding to support distributed-OSGi): 1. One Tuscany bundle containing Tuscany + dependencies (one classloader for all the jars referred to in tuscany-sca-manifest.jar ). This works and corresponds to CL1 application loader, CL2 runtime loader. 2. Two Tuscany bundles, one containing Tuscany, another containing all 3rd party dependencies(Axis2 etc.). This also works and corresponds to CL1 application loader, and CL2 Tuscany, CL3 3rd party code. 3. Split Tuscany bundles into multiple bundles, one bundle for 3rd party (splitting CL2 into multiple loaders from 2.) 4. Split 3rd party into multiple bundles, one bundle for Tuscany (splitting CL3 into multiple loaders from 2.) 3. and 4. dont work yet. From your note (and Raymond's), I think I should have another scenario before 3. which splits Tuscany into API and runtime. I think that should work without much trouble (ie, CL1 application loader, CL2 Tuscany API loader, CL3 Tuscany runtime loader, CL4 3rd party loader). Where do the SPIs fit into this? They aren't really part of the API loader, because aplication code shouldn't see them. The aren't really part of the runtime loader, because they need to be exposed between different runtime modules, but the runtime code shouldn't be exposed. I think Raymond's graph of dependencies was helpful in laying out the visbility relationships. There's also a counterpoint for what things should NOT be visible. In the following, see means that it's statically referenceable using the same classloader. 1. Application code shouldn't be able to see non-imported contributions, Tuscany SPIs, or Tuscany runtime code. 2. Tuscany APIs shouldn't be able to see anything else. 3. Tuscany SPIs shouldn't be able to see Tuscany runtime code or application code. 4. Tuscany runtime code shouldn't be able to see Tuscany runtime code in other modules, or application code. 5. 3rd party code (not written with knowledge of Tuscany) shouldn't be able to see Tuscany runtime code, Tuscany SPIs, Tuscany APIs, or application code. Simon The tests for multiple application loaders (second path in your note) will be non-OSGi tests - Tuscany OSGi contributions are already tested with multiple bundles and hence multiple classloaders. For the first path, I haven't really considered testing without OSGi - I would probably still continue to work with OSGi to isolate the issues, but try and introduce tests later which run without OSGi. Thank you... Regards, Rajini On 10/16/07, Jean-Sebastien Delfino [EMAIL
Re: Classloading in Tuscany
Rajini Sivaram wrote: Simon, Thank you for your note. Yes, you are right, we should have a separate classloader for the SPI with its own visibility rules. In terms of static dependencies (these are shown in Raymond's graph), Tuscany modules are fairly neatly separated out. These are the compile-time dependencies in pom.xml, and Eclipse would throw up if there were any cyclic dependencies. From your list, 1. is currently not true, but can be easily fixed. 2., 3. and 5. are true. 4. is only partially true, because there are many dependencies across modules - for instance, implementation.spring and implementation.osgi use code from implementation.java. I stated this as an extreme position to see what the reaction would be :-) I would be OK with extending this to provide static visibility between Tuscany modules. If we allow this, I'd be inclined to go for a single shared classloader for all Tuscany modules, not a set of dependency relationships enforced by separate classloaders as can be done using fine-grained OSGi modularity. But for dynamic classloading, the dependencies are not so straightforward, and any classloader-based isolation has to handle either dynamic visibility or access to classloaders which have the visibility. An example of the difference between static and dynamic dependencies is 3. Tuscany SPIs dont need static access to Tuscany runtime code, but there is code in tuscany-core-spi which loads classes from the runtime modules. Here is an example: * DefaultExtensionPointRegistry.getExtensionPoint(ClassT extensionPointType): * *Class? extensionPointClass = Class.forName(classNames.iterator().next(), **true**, classLoader);* **Here, the classloader used is the classloader of extensionPointType which is from the SPI. But the class being loaded is from a runtime module. This type of dynamic classloading is used in many places in Tuscany, and they work at the moment because all modules including the SPI are loaded using a single classloader. In this case, SPI doesn't need to see the classes from the runtime module, but it needs to know how to obtain the classloader which can see those classes. I think this is fine, and a necessary escape from the static visibility constraints. The mechanism to get the dynamic classloader can be controlled so that it is only allowed for code that needs access to it. Simon Thank you... Regards, Rajini On 10/17/07, Simon Nash [EMAIL PROTECTED] wrote: I'm just catching up with this very interesting thread. Comments inline. Rajini Sivaram wrote: Sebastien, I have the second path - (multiple application loaders, one runtime loader) working in my sandbox. I need to write some tests and run all the existing tests before I submit the patch. This works without OSGi, and is a very minor change. For the first path, I am still running under OSGi. At the moment I have four different scenarios (they are all running tests using Axis2 binding to support distributed-OSGi): 1. One Tuscany bundle containing Tuscany + dependencies (one classloader for all the jars referred to in tuscany-sca-manifest.jar ). This works and corresponds to CL1 application loader, CL2 runtime loader. 2. Two Tuscany bundles, one containing Tuscany, another containing all 3rd party dependencies(Axis2 etc.). This also works and corresponds to CL1 application loader, and CL2 Tuscany, CL3 3rd party code. 3. Split Tuscany bundles into multiple bundles, one bundle for 3rd party (splitting CL2 into multiple loaders from 2.) 4. Split 3rd party into multiple bundles, one bundle for Tuscany (splitting CL3 into multiple loaders from 2.) 3. and 4. dont work yet. From your note (and Raymond's), I think I should have another scenario before 3. which splits Tuscany into API and runtime. I think that should work without much trouble (ie, CL1 application loader, CL2 Tuscany API loader, CL3 Tuscany runtime loader, CL4 3rd party loader). Where do the SPIs fit into this? They aren't really part of the API loader, because aplication code shouldn't see them. The aren't really part of the runtime loader, because they need to be exposed between different runtime modules, but the runtime code shouldn't be exposed. I think Raymond's graph of dependencies was helpful in laying out the visbility relationships. There's also a counterpoint for what things should NOT be visible. In the following, see means that it's statically referenceable using the same classloader. 1. Application code shouldn't be able to see non-imported contributions, Tuscany SPIs, or Tuscany runtime code. 2. Tuscany APIs shouldn't be able to see anything else. 3. Tuscany SPIs shouldn't be able to see Tuscany runtime code or application code. 4. Tuscany runtime code shouldn't be able to see Tuscany runtime code in other modules, or application code. 5. 3rd party code (not written with knowledge of Tuscany) shouldn't be able to see Tuscany
Re: Classloading in Tuscany
On 10/18/07, Rajini Sivaram [EMAIL PROTECTED] wrote: Simon, Thank you for your note. Yes, you are right, we should have a separate classloader for the SPI with its own visibility rules. In terms of static dependencies (these are shown in Raymond's graph), Tuscany modules are fairly neatly separated out. These are the compile-time dependencies in pom.xml, and Eclipse would throw up if there were any cyclic dependencies. From your list, 1. is currently not true, but can be easily fixed. 2., 3. and 5. are true. 4. is only partially true, because there are many dependencies across modules - for instance, implementation.spring and implementation.osgi use code from implementation.java. But for dynamic classloading, the dependencies are not so straightforward, and any classloader-based isolation has to handle either dynamic visibility or access to classloaders which have the visibility. An example of the difference between static and dynamic dependencies is 3. Tuscany SPIs dont need static access to Tuscany runtime code, but there is code in tuscany-core-spi which loads classes from the runtime modules. Here is an example: * DefaultExtensionPointRegistry.getExtensionPoint(ClassT extensionPointType): * *Class? extensionPointClass = Class.forName(classNames.iterator().next(), **true**, classLoader);* **Here, the classloader used is the classloader of extensionPointType which is from the SPI. But the class being loaded is from a runtime module. This type of dynamic classloading is used in many places in Tuscany, and they work at the moment because all modules including the SPI are loaded using a single classloader. In this case, SPI doesn't need to see the classes from the runtime module, but it needs to know how to obtain the classloader which can see those classes. Thank you... Regards, Rajini On 10/17/07, Simon Nash [EMAIL PROTECTED] wrote: I'm just catching up with this very interesting thread. Comments inline. Rajini Sivaram wrote: Sebastien, I have the second path - (multiple application loaders, one runtime loader) working in my sandbox. I need to write some tests and run all the existing tests before I submit the patch. This works without OSGi, and is a very minor change. For the first path, I am still running under OSGi. At the moment I have four different scenarios (they are all running tests using Axis2 binding to support distributed-OSGi): 1. One Tuscany bundle containing Tuscany + dependencies (one classloader for all the jars referred to in tuscany-sca-manifest.jar ). This works and corresponds to CL1 application loader, CL2 runtime loader. 2. Two Tuscany bundles, one containing Tuscany, another containing all 3rd party dependencies(Axis2 etc.). This also works and corresponds to CL1 application loader, and CL2 Tuscany, CL3 3rd party code. 3. Split Tuscany bundles into multiple bundles, one bundle for 3rd party (splitting CL2 into multiple loaders from 2.) 4. Split 3rd party into multiple bundles, one bundle for Tuscany (splitting CL3 into multiple loaders from 2.) 3. and 4. dont work yet. From your note (and Raymond's), I think I should have another scenario before 3. which splits Tuscany into API and runtime. I think that should work without much trouble (ie, CL1 application loader, CL2 Tuscany API loader, CL3 Tuscany runtime loader, CL4 3rd party loader). Where do the SPIs fit into this? They aren't really part of the API loader, because aplication code shouldn't see them. The aren't really part of the runtime loader, because they need to be exposed between different runtime modules, but the runtime code shouldn't be exposed. I think Raymond's graph of dependencies was helpful in laying out the visbility relationships. There's also a counterpoint for what things should NOT be visible. In the following, see means that it's statically referenceable using the same classloader. 1. Application code shouldn't be able to see non-imported contributions, Tuscany SPIs, or Tuscany runtime code. 2. Tuscany APIs shouldn't be able to see anything else. 3. Tuscany SPIs shouldn't be able to see Tuscany runtime code or application code. 4. Tuscany runtime code shouldn't be able to see Tuscany runtime code in other modules, or application code. 5. 3rd party code (not written with knowledge of Tuscany) shouldn't be able to see Tuscany runtime code, Tuscany SPIs, Tuscany APIs, or application code. Simon The tests for multiple application loaders (second path in your note) will be non-OSGi tests - Tuscany OSGi contributions are already tested with multiple bundles and hence multiple classloaders. For the first path, I haven't really considered testing without OSGi - I would probably still continue to work with OSGi to
Re: Classloading in Tuscany
Simon, At the moment my SPI bundle contains tuscany-core-spi, tuscany-contribution, tuscany-policy, tuscany-interface and tuscany-assembly. From Simon Nash's note, I assumed that SPI meant tuscany-core-spi and used that project + its dependencies. I am ignoring host-embedded classes at the moment, and I will try and fit those in once your reorganized code is in place. I am working with 1.0 release since that was the most stable code I could find when I started, but I think I should move to the latest code soon. Once I get the SPI bundle sorted, I will see if I can split the rest of Tuscany into a runtime and extensions (two bundles). Thank you... Regards, Rajini On 10/18/07, Simon Laws [EMAIL PROTECTED] wrote: On 10/18/07, Rajini Sivaram [EMAIL PROTECTED] wrote: Simon, Thank you for your note. Yes, you are right, we should have a separate classloader for the SPI with its own visibility rules. In terms of static dependencies (these are shown in Raymond's graph), Tuscany modules are fairly neatly separated out. These are the compile-time dependencies in pom.xml, and Eclipse would throw up if there were any cyclic dependencies. From your list, 1. is currently not true, but can be easily fixed. 2., 3. and 5. are true. 4. is only partially true, because there are many dependencies across modules - for instance, implementation.springand implementation.osgi use code from implementation.java. But for dynamic classloading, the dependencies are not so straightforward, and any classloader-based isolation has to handle either dynamic visibility or access to classloaders which have the visibility. An example of the difference between static and dynamic dependencies is 3. Tuscany SPIs dont need static access to Tuscany runtime code, but there is code in tuscany-core-spi which loads classes from the runtime modules. Here is an example: * DefaultExtensionPointRegistry.getExtensionPoint(ClassT extensionPointType): * *Class? extensionPointClass = Class.forName(classNames.iterator().next(), **true**, classLoader);* **Here, the classloader used is the classloader of extensionPointType which is from the SPI. But the class being loaded is from a runtime module. This type of dynamic classloading is used in many places in Tuscany, and they work at the moment because all modules including the SPI are loaded using a single classloader. In this case, SPI doesn't need to see the classes from the runtime module, but it needs to know how to obtain the classloader which can see those classes. Thank you... Regards, Rajini On 10/17/07, Simon Nash [EMAIL PROTECTED] wrote: I'm just catching up with this very interesting thread. Comments inline. Rajini Sivaram wrote: Sebastien, I have the second path - (multiple application loaders, one runtime loader) working in my sandbox. I need to write some tests and run all the existing tests before I submit the patch. This works without OSGi, and is a very minor change. For the first path, I am still running under OSGi. At the moment I have four different scenarios (they are all running tests using Axis2 binding to support distributed-OSGi): 1. One Tuscany bundle containing Tuscany + dependencies (one classloader for all the jars referred to in tuscany-sca-manifest.jar ). This works and corresponds to CL1 application loader, CL2 runtime loader. 2. Two Tuscany bundles, one containing Tuscany, another containing all 3rd party dependencies(Axis2 etc.). This also works and corresponds to CL1 application loader, and CL2 Tuscany, CL3 3rd party code. 3. Split Tuscany bundles into multiple bundles, one bundle for 3rd party (splitting CL2 into multiple loaders from 2.) 4. Split 3rd party into multiple bundles, one bundle for Tuscany (splitting CL3 into multiple loaders from 2.) 3. and 4. dont work yet. From your note (and Raymond's), I think I should have another scenario before 3. which splits Tuscany into API and runtime. I think that should work without much trouble (ie, CL1 application loader, CL2 Tuscany API loader, CL3 Tuscany runtime loader, CL4 3rd party loader). Where do the SPIs fit into this? They aren't really part of the API loader, because aplication code shouldn't see them. The aren't really part of the runtime loader, because they need to be exposed between different runtime modules, but the runtime code shouldn't be exposed. I think Raymond's graph of dependencies was helpful in laying out the visbility relationships. There's also a counterpoint for what things should NOT be visible. In the following, see means that it's statically referenceable using the same classloader. 1. Application code shouldn't be able to see non-imported
Re: Classloading in Tuscany
Folks, Comments inline Simon Laws wrote: Hi Rajini Re. 4 on Simon's list. Maybe it is useful to more clearly distinguish between those Tuscany modules that are expect to be loaded statically, assembly, core, etc and those that expected to be loaded dynamically, binding.?, implementation.? etc. I find the term module a little unsatisfactory. Raymond, in his diagram, used Tuscany core and Tuscany extension and in a previous post used Tuscany runtime and Tuscany extension. I prefer the latter pair just because we have a maven module called core. +1 This leads to a 4a and 4b based on Raymond's post/diagram 4a Tuscany extension module code shouldn't be able to see other extension modules (not sure what the dotted line on the diagram implies but I expect that it's to do with modules like binding-ws-axis2 and binding-ws interacting) or application code or Tuscany runtime code other than via the SPI. Hmm, first, this ain't the case today and it will need some thought. The Java extensions do share code and it would be crazy for them not to share the code. So, Spring uses stuff out of the base Java extension - and I am sure that other Java type extensions would want to do the same. In an OSGi world, it would be fine to express the dependency in a simple way. For non-OSGi I'm not sure of the best route. I suspect that other extension types may want to share stuff as well. 4b Tuscany runtime code shouldn't be able to see Tuscany extension code or application code. That sounds a bit odd. Perhaps I've not got the right end of the stick, but the some code - either core and or extensions has to get very intimate with the application code. Introspection, instantiation, injection - all has to be done either by core code or extension code. Perhaps I've not understood the separation you're looking for? Then, from reading your comments, we have to be clearer about what the SPI is providing an interface to because it current includes interfaces to the underlying runtime modules but also the host-embedded classes which strike me as being more API than SPI. We are reorganizing the domain/node interfaces at the moment so hopefully we can clear this last point up as part of that. Regards Simon - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Classloading in Tuscany
On 10/18/07, Mike Edwards [EMAIL PROTECTED] wrote: Folks, Comments inline Simon Laws wrote: Hi Rajini Re. 4 on Simon's list. Maybe it is useful to more clearly distinguish between those Tuscany modules that are expect to be loaded statically, assembly, core, etc and those that expected to be loaded dynamically, binding.?, implementation.? etc. I find the term module a little unsatisfactory. Raymond, in his diagram, used Tuscany core and Tuscany extension and in a previous post used Tuscany runtime and Tuscany extension. I prefer the latter pair just because we have a maven module called core. +1 This leads to a 4a and 4b based on Raymond's post/diagram 4a Tuscany extension module code shouldn't be able to see other extension modules (not sure what the dotted line on the diagram implies but I expect that it's to do with modules like binding-ws-axis2 and binding-ws interacting) or application code or Tuscany runtime code other than via the SPI. Hmm, first, this ain't the case today and it will need some thought. The Java extensions do share code and it would be crazy for them not to share the code. So, Spring uses stuff out of the base Java extension - and I am sure that other Java type extensions would want to do the same. In an OSGi world, it would be fine to express the dependency in a simple way. For non-OSGi I'm not sure of the best route. I suspect that other extension types may want to share stuff as well. Agreed. Hence I pointed out the relationship between binding-ws-axis2 and binding-ws. There are loose groups of software spread across multiple maven modules that just represent modularization of the software for clarity and reuse purposes. Then there are the modules that are intended to be loaded as extensions. Not all maven modules are create equal :-) The non OSGi world is managed by the dependencies that appear in out maven pom files. Without this dependency tree you just have to know that, for example, binding-ws has to be on the classpath when you also include binding-ws-xml which is in turn a dependency of binding-ws-axis2. Nothing too unusual there until you start talking about having separate class loaders for each extension as has been discussed previously in this thread. You really need to understand what an extension is, i.e. it is unlikely to be a single maven module. 4b Tuscany runtime code shouldn't be able to see Tuscany extension code or application code. That sounds a bit odd. Perhaps I've not got the right end of the stick, but the some code - either core and or extensions has to get very intimate with the application code. Introspection, instantiation, injection - all has to be done either by core code or extension code. Perhaps I've not understood the separation you're looking for? This should say shouldn't be able to statically see... I had imagined that these are all of the implementation modules that sit behind the SPI Then, from reading your comments, we have to be clearer about what the SPI is providing an interface to because it current includes interfaces to the underlying runtime modules but also the host-embedded classes which strike me as being more API than SPI. We are reorganizing the domain/node interfaces at the moment so hopefully we can clear this last point up as part of that. Regards Simon - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Classloading in Tuscany
Sebastien, I have the second path - (multiple application loaders, one runtime loader) working in my sandbox. I need to write some tests and run all the existing tests before I submit the patch. This works without OSGi, and is a very minor change. For the first path, I am still running under OSGi. At the moment I have four different scenarios (they are all running tests using Axis2 binding to support distributed-OSGi): 1. One Tuscany bundle containing Tuscany + dependencies (one classloader for all the jars referred to in tuscany-sca-manifest.jar). This works and corresponds to CL1 application loader, CL2 runtime loader. 2. Two Tuscany bundles, one containing Tuscany, another containing all 3rd party dependencies(Axis2 etc.). This also works and corresponds to CL1 application loader, and CL2 Tuscany, CL3 3rd party code. 3. Split Tuscany bundles into multiple bundles, one bundle for 3rd party (splitting CL2 into multiple loaders from 2.) 4. Split 3rd party into multiple bundles, one bundle for Tuscany (splitting CL3 into multiple loaders from 2.) 3. and 4. dont work yet. From your note (and Raymond's), I think I should have another scenario before 3. which splits Tuscany into API and runtime. I think that should work without much trouble (ie, CL1 application loader, CL2 Tuscany API loader, CL3 Tuscany runtime loader, CL4 3rd party loader). The tests for multiple application loaders (second path in your note) will be non-OSGi tests - Tuscany OSGi contributions are already tested with multiple bundles and hence multiple classloaders. For the first path, I haven't really considered testing without OSGi - I would probably still continue to work with OSGi to isolate the issues, but try and introduce tests later which run without OSGi. Thank you... Regards, Rajini On 10/16/07, Jean-Sebastien Delfino [EMAIL PROTECTED] wrote: Rajini Sivaram wrote: Raymond, Thank you for your reply (and the diagram). The biggest advantage of migrating to an OSGi classloader scheme would be that apart from module isolation, OSGi would also provide module versioning, enabling multiple versions of SCA runtime to exist within a single VM. OSGi would also enable Tuscany modules to be dynamically installed, started and uninstalled. The use of multi-parent classloaders to load modules in Tuscany would require the same amount of code changes as migrating to OSGi, but it would be much harder to implement versioning and dynamic replacement of modules (which come for free with OSGi). The desired visibility of classes that you have listed correspond to the static dependencies that currently exist in the code. The actual visibility that exists today includes arrows from the core modules to extensions, forming a cycle. It is this visibility that is used to locate and start modules dynamically in Tuscany today. There is also an arrow from the Axis library to binding.ws.axis2, through the thread context classloader, and even though not particularly desirable, it is not avoidable. Thank you... Regards, Rajini How about going step by step and: 1. try to bootstrap the tuscany runtime with two classloaders: CL1 application code, CL2 runtime 2. extend to CL1 application code, CL2 Tuscany and SCA APIs, CL3 runtime 3. split the runtime in multiple CLs and on a separate path: 1. try to bootstrap the tuscany runtime with two classloaders: CL1 application code, CL2 runtime 2. split the application code in multiple CLs We could create integration tests for these configurations (not necessarily using OSGi, as these can be built with just plain classloaders IMO), and it would help us identify bad classloader usages, fix them, and detect+prevent classloader issues over time. Thoughts? -- Jean-Sebastien - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Classloading in Tuscany
I'm just catching up with this very interesting thread. Comments inline. Rajini Sivaram wrote: Sebastien, I have the second path - (multiple application loaders, one runtime loader) working in my sandbox. I need to write some tests and run all the existing tests before I submit the patch. This works without OSGi, and is a very minor change. For the first path, I am still running under OSGi. At the moment I have four different scenarios (they are all running tests using Axis2 binding to support distributed-OSGi): 1. One Tuscany bundle containing Tuscany + dependencies (one classloader for all the jars referred to in tuscany-sca-manifest.jar). This works and corresponds to CL1 application loader, CL2 runtime loader. 2. Two Tuscany bundles, one containing Tuscany, another containing all 3rd party dependencies(Axis2 etc.). This also works and corresponds to CL1 application loader, and CL2 Tuscany, CL3 3rd party code. 3. Split Tuscany bundles into multiple bundles, one bundle for 3rd party (splitting CL2 into multiple loaders from 2.) 4. Split 3rd party into multiple bundles, one bundle for Tuscany (splitting CL3 into multiple loaders from 2.) 3. and 4. dont work yet. From your note (and Raymond's), I think I should have another scenario before 3. which splits Tuscany into API and runtime. I think that should work without much trouble (ie, CL1 application loader, CL2 Tuscany API loader, CL3 Tuscany runtime loader, CL4 3rd party loader). Where do the SPIs fit into this? They aren't really part of the API loader, because aplication code shouldn't see them. The aren't really part of the runtime loader, because they need to be exposed between different runtime modules, but the runtime code shouldn't be exposed. I think Raymond's graph of dependencies was helpful in laying out the visbility relationships. There's also a counterpoint for what things should NOT be visible. In the following, see means that it's statically referenceable using the same classloader. 1. Application code shouldn't be able to see non-imported contributions, Tuscany SPIs, or Tuscany runtime code. 2. Tuscany APIs shouldn't be able to see anything else. 3. Tuscany SPIs shouldn't be able to see Tuscany runtime code or application code. 4. Tuscany runtime code shouldn't be able to see Tuscany runtime code in other modules, or application code. 5. 3rd party code (not written with knowledge of Tuscany) shouldn't be able to see Tuscany runtime code, Tuscany SPIs, Tuscany APIs, or application code. Simon The tests for multiple application loaders (second path in your note) will be non-OSGi tests - Tuscany OSGi contributions are already tested with multiple bundles and hence multiple classloaders. For the first path, I haven't really considered testing without OSGi - I would probably still continue to work with OSGi to isolate the issues, but try and introduce tests later which run without OSGi. Thank you... Regards, Rajini On 10/16/07, Jean-Sebastien Delfino [EMAIL PROTECTED] wrote: Rajini Sivaram wrote: Raymond, Thank you for your reply (and the diagram). The biggest advantage of migrating to an OSGi classloader scheme would be that apart from module isolation, OSGi would also provide module versioning, enabling multiple versions of SCA runtime to exist within a single VM. OSGi would also enable Tuscany modules to be dynamically installed, started and uninstalled. The use of multi-parent classloaders to load modules in Tuscany would require the same amount of code changes as migrating to OSGi, but it would be much harder to implement versioning and dynamic replacement of modules (which come for free with OSGi). The desired visibility of classes that you have listed correspond to the static dependencies that currently exist in the code. The actual visibility that exists today includes arrows from the core modules to extensions, forming a cycle. It is this visibility that is used to locate and start modules dynamically in Tuscany today. There is also an arrow from the Axis library to binding.ws.axis2, through the thread context classloader, and even though not particularly desirable, it is not avoidable. Thank you... Regards, Rajini How about going step by step and: 1. try to bootstrap the tuscany runtime with two classloaders: CL1 application code, CL2 runtime 2. extend to CL1 application code, CL2 Tuscany and SCA APIs, CL3 runtime 3. split the runtime in multiple CLs and on a separate path: 1. try to bootstrap the tuscany runtime with two classloaders: CL1 application code, CL2 runtime 2. split the application code in multiple CLs We could create integration tests for these configurations (not necessarily using OSGi, as these can be built with just plain classloaders IMO), and it would help us identify bad classloader usages, fix them, and detect+prevent classloader issues over time. Thoughts? -- Jean-Sebastien
Re: Classloading in Tuscany
Raymond, Thank you for your reply (and the diagram). The biggest advantage of migrating to an OSGi classloader scheme would be that apart from module isolation, OSGi would also provide module versioning, enabling multiple versions of SCA runtime to exist within a single VM. OSGi would also enable Tuscany modules to be dynamically installed, started and uninstalled. The use of multi-parent classloaders to load modules in Tuscany would require the same amount of code changes as migrating to OSGi, but it would be much harder to implement versioning and dynamic replacement of modules (which come for free with OSGi). The desired visibility of classes that you have listed correspond to the static dependencies that currently exist in the code. The actual visibility that exists today includes arrows from the core modules to extensions, forming a cycle. It is this visibility that is used to locate and start modules dynamically in Tuscany today. There is also an arrow from the Axis library to binding.ws.axis2, through the thread context classloader, and even though not particularly desirable, it is not avoidable. Thank you... Regards, Rajini On 10/15/07, Raymond Feng [EMAIL PROTECTED] wrote: Hi, Rajini. Thank you for the detailed writeup. I copied your note into the following wiki page so we can capture the design points. http://cwiki.apache.org/confluence/display/TUSCANYWIKI/Classloading+in+Tuscany+SCA+Java I found it a bit difficult to reply in long e-mails so I decide to attack the problem from a slightly different angle. A) What's the purpose of classloading scheme? I think it's used to provide sharing and isolation of java classes. B) What are the players? 1. SCA/Tuscany APIs (and potentially other APIs such as SDO) 2. Tuscany runtime code 3. Tuscany extension code 4. 3rd party code that Tuscany runtime/extension depends on 5. Application code from SCA contributions 3) What's desired visibility? 5 -- imported java classes by the owning contribution -- 1 2 -- 1 -- 4 3 -- 2 (SPI portion) -- 1 -- 4 -- potentially other extensions I created a graph at http://cwiki.apache.org/confluence/download/attachments/68801/classloader-dependencies.png as the starting point. Once we have the relationship flushed out, we could then apply techniques such as OSGi or multi-parent classloaders, or a combination to enforce the loading scheme. Raymond - Original Message - From: Rajini Sivaram [EMAIL PROTECTED] To: tuscany-dev@ws.apache.org Sent: Monday, October 15, 2007 12:52 AM Subject: Re: Classloading in Tuscany Mike, There are two sets of classloading in Tuscany that we need to look at and these can be handled independently of each other. 1) Classloading architecture for SCA contributions 2) Classloading architecture for SCA runtime modules In both cases, there are two ways of improving modularity in Tuscany a) Use separate classloaders per module to provide isolation, using a classloader architecture similar to OSGi, but without actually running in an OSGi runtime. b) Use OSGi bundles to provide module isolation and versioning, where the versioning support would rely on an OSGi runtime. For both 1) and 2), we could support a) and/or b). Tuscany already supports 1b), and the proposed fixes will support 1a). Tuscany does not implement 2a) or 2b), and if done properly, the implementation would required code changes that are pervasive across Tuscany. So the question is - do we really want to run Tuscany modules as separate OSGi bundles (or isolate modules using separate classloaders)? IMHO, it is only worth the hassle, if Tuscany modules are properly versioned and dynamically replaceable - ie, run as bundles in an OSGi runtime (2b). The proposed fixes do not implement 2a) and provide a partial solution for 2b) based on OSGi manifest files to minimize code changes to Tuscany. 1) Classloading architecture for SCA contributions At the moment, OSGi bundle contributions can be used in Tuscany which provide modularity and versioning with the help of an OSGi runtime. Plain Jar contributions or folders use a single classloader at the moment and the proposed fixes will introduce contribution classloaders to isolate contributions. SCA contributions can specify dependencies in terms of import/export statements in the same way as OSGi bundles. If you consider Java contributions, SCA contribution dependencies are a subset of OSGi bundle dependencies, because SCA does not support versioning or any of the other attributes that can be associated with importing packages in OSGi. So SCA contribution classloading will be a simpler version of OSGi bundle classloading. The code for supporting SCA import/export is already in place in Tuscany- it just doesn't get used because the thread context classloader is currently used to resolve classes. 2) Classloading
Re: Classloading in Tuscany
Rajini Sivaram wrote: Raymond, Thank you for your reply (and the diagram). The biggest advantage of migrating to an OSGi classloader scheme would be that apart from module isolation, OSGi would also provide module versioning, enabling multiple versions of SCA runtime to exist within a single VM. OSGi would also enable Tuscany modules to be dynamically installed, started and uninstalled. The use of multi-parent classloaders to load modules in Tuscany would require the same amount of code changes as migrating to OSGi, but it would be much harder to implement versioning and dynamic replacement of modules (which come for free with OSGi). The desired visibility of classes that you have listed correspond to the static dependencies that currently exist in the code. The actual visibility that exists today includes arrows from the core modules to extensions, forming a cycle. It is this visibility that is used to locate and start modules dynamically in Tuscany today. There is also an arrow from the Axis library to binding.ws.axis2, through the thread context classloader, and even though not particularly desirable, it is not avoidable. Thank you... Regards, Rajini How about going step by step and: 1. try to bootstrap the tuscany runtime with two classloaders: CL1 application code, CL2 runtime 2. extend to CL1 application code, CL2 Tuscany and SCA APIs, CL3 runtime 3. split the runtime in multiple CLs and on a separate path: 1. try to bootstrap the tuscany runtime with two classloaders: CL1 application code, CL2 runtime 2. split the application code in multiple CLs We could create integration tests for these configurations (not necessarily using OSGi, as these can be built with just plain classloaders IMO), and it would help us identify bad classloader usages, fix them, and detect+prevent classloader issues over time. Thoughts? -- Jean-Sebastien - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Classloading in Tuscany
Jean-Sebastien Delfino wrote: Rajini Sivaram wrote: Raymond, Thank you for your reply (and the diagram). The biggest advantage of migrating to an OSGi classloader scheme would be that apart from module isolation, OSGi would also provide module versioning, enabling multiple versions of SCA runtime to exist within a single VM. OSGi would also enable Tuscany modules to be dynamically installed, started and uninstalled. The use of multi-parent classloaders to load modules in Tuscany would require the same amount of code changes as migrating to OSGi, but it would be much harder to implement versioning and dynamic replacement of modules (which come for free with OSGi). The desired visibility of classes that you have listed correspond to the static dependencies that currently exist in the code. The actual visibility that exists today includes arrows from the core modules to extensions, forming a cycle. It is this visibility that is used to locate and start modules dynamically in Tuscany today. There is also an arrow from the Axis library to binding.ws.axis2, through the thread context classloader, and even though not particularly desirable, it is not avoidable. Thank you... Regards, Rajini How about going step by step and: 1. try to bootstrap the tuscany runtime with two classloaders: CL1 application code, CL2 runtime 2. extend to CL1 application code, CL2 Tuscany and SCA APIs, CL3 runtime 3. split the runtime in multiple CLs and on a separate path: 1. try to bootstrap the tuscany runtime with two classloaders: CL1 application code, CL2 runtime 2. split the application code in multiple CLs We could create integration tests for these configurations (not necessarily using OSGi, as these can be built with just plain classloaders IMO), and it would help us identify bad classloader usages, fix them, and detect+prevent classloader issues over time. Thoughts? While going through some JIRAs I came across http://issues.apache.org/jira/browse/TUSCANY-1487, this is basically step (1) reported as a user requirement. -- Jean-Sebastien - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Classloading in Tuscany
Mike, There are two sets of classloading in Tuscany that we need to look at and these can be handled independently of each other. 1) Classloading architecture for SCA contributions 2) Classloading architecture for SCA runtime modules In both cases, there are two ways of improving modularity in Tuscany a) Use separate classloaders per module to provide isolation, using a classloader architecture similar to OSGi, but without actually running in an OSGi runtime. b) Use OSGi bundles to provide module isolation and versioning, where the versioning support would rely on an OSGi runtime. For both 1) and 2), we could support a) and/or b). Tuscany already supports 1b), and the proposed fixes will support 1a). Tuscany does not implement 2a) or 2b), and if done properly, the implementation would required code changes that are pervasive across Tuscany. So the question is - do we really want to run Tuscany modules as separate OSGi bundles (or isolate modules using separate classloaders)? IMHO, it is only worth the hassle, if Tuscany modules are properly versioned and dynamically replaceable - ie, run as bundles in an OSGi runtime (2b). The proposed fixes do not implement 2a) and provide a partial solution for 2b) based on OSGi manifest files to minimize code changes to Tuscany. 1) Classloading architecture for SCA contributions At the moment, OSGi bundle contributions can be used in Tuscany which provide modularity and versioning with the help of an OSGi runtime. Plain Jar contributions or folders use a single classloader at the moment and the proposed fixes will introduce contribution classloaders to isolate contributions. SCA contributions can specify dependencies in terms of import/export statements in the same way as OSGi bundles. If you consider Java contributions, SCA contribution dependencies are a subset of OSGi bundle dependencies, because SCA does not support versioning or any of the other attributes that can be associated with importing packages in OSGi. So SCA contribution classloading will be a simpler version of OSGi bundle classloading. The code for supporting SCA import/export is already in place in Tuscany- it just doesn't get used because the thread context classloader is currently used to resolve classes. 2) Classloading architecture for SCA runtime modules At the moment, Tuscany uses a single classloader for the runtime and its dependencies, and even though Tuscany runtime architecture uses extensible modules with reasonably well defined dependencies, module isolation is not achieved because of the use of a single classloader. Tuscany also has dependencies on many libraries which rely on the thread context classloader. Even though we are looking at running Tuscany in an OSGi runtime to support distributed-OSGi, at the moment we are still assuming that by default Tuscany would be run without an OSGi runtime. Hence the proposed fixes aim to minimize Tuscany changes required to implement 2b). Tuscany's use of thread context classloader will be removed wherever possible, but the requirement on thread context classloader will not be removed altogether since it is used by libraries that Tuscany depends on. There are two issues with modularizing Tuscany runtime using OSGi or OSGi-style classloading. Thread context classloaders and OSGi dont go very well together. And the extension module architecture used by Tuscany where a core module is extended through the use of extension modules ends up in a classloader hierarchy which is the reverse of what is required - the core bundle does not have visibility of the classes from the extension bundles. There is an OSGi RFP which addresses classloading enhancements for OSGi including those required for applications relying on thread context classloaders. Possible solutions to implement 2b) now include the use of DynamicImport-Package, Eclipse buddy policy, Spring-OSGi Extender Model or OSGi services. If we want to implement 2a) and 2b) properly at some point, it might make sense to provide a solution that uses a utility library to implement all classloading (which can then do something different based on whether Tuscany is running inside an OSGi runtime or outside). But the changes required for this will be pervasive across Tuscany code. Thank you... Regards, Rajini On 10/12/07, Mike Edwards [EMAIL PROTECTED] wrote: Rajini, Little though here: - can this be done in a way that moves us closer to the OSGi handling of classloading? - so if ever we wanted an OSGi style runtime, it would be easier to adapt what we have... Yours, Mike. Rajini Sivaram wrote: Thank you, Ant. I will try to split the work into small pieces and submit separate patches. Thank you... Regards, Rajini On 10/12/07, ant elder [EMAIL PROTECTED] wrote: On 10/11/07, Rajini Sivaram [EMAIL PROTECTED] wrote: Hello, Tuscany's use of classloaders doesn't seem to be well-defined, even though the concept of a runtime classLoader
Re: Classloading in Tuscany
Hi, Rajini. Thank you for the detailed writeup. I copied your note into the following wiki page so we can capture the design points. http://cwiki.apache.org/confluence/display/TUSCANYWIKI/Classloading+in+Tuscany+SCA+Java I found it a bit difficult to reply in long e-mails so I decide to attack the problem from a slightly different angle. A) What's the purpose of classloading scheme? I think it's used to provide sharing and isolation of java classes. B) What are the players? 1. SCA/Tuscany APIs (and potentially other APIs such as SDO) 2. Tuscany runtime code 3. Tuscany extension code 4. 3rd party code that Tuscany runtime/extension depends on 5. Application code from SCA contributions 3) What's desired visibility? 5 -- imported java classes by the owning contribution -- 1 2 -- 1 -- 4 3 -- 2 (SPI portion) -- 1 -- 4 -- potentially other extensions I created a graph at http://cwiki.apache.org/confluence/download/attachments/68801/classloader-dependencies.png as the starting point. Once we have the relationship flushed out, we could then apply techniques such as OSGi or multi-parent classloaders, or a combination to enforce the loading scheme. Raymond - Original Message - From: Rajini Sivaram [EMAIL PROTECTED] To: tuscany-dev@ws.apache.org Sent: Monday, October 15, 2007 12:52 AM Subject: Re: Classloading in Tuscany Mike, There are two sets of classloading in Tuscany that we need to look at and these can be handled independently of each other. 1) Classloading architecture for SCA contributions 2) Classloading architecture for SCA runtime modules In both cases, there are two ways of improving modularity in Tuscany a) Use separate classloaders per module to provide isolation, using a classloader architecture similar to OSGi, but without actually running in an OSGi runtime. b) Use OSGi bundles to provide module isolation and versioning, where the versioning support would rely on an OSGi runtime. For both 1) and 2), we could support a) and/or b). Tuscany already supports 1b), and the proposed fixes will support 1a). Tuscany does not implement 2a) or 2b), and if done properly, the implementation would required code changes that are pervasive across Tuscany. So the question is - do we really want to run Tuscany modules as separate OSGi bundles (or isolate modules using separate classloaders)? IMHO, it is only worth the hassle, if Tuscany modules are properly versioned and dynamically replaceable - ie, run as bundles in an OSGi runtime (2b). The proposed fixes do not implement 2a) and provide a partial solution for 2b) based on OSGi manifest files to minimize code changes to Tuscany. 1) Classloading architecture for SCA contributions At the moment, OSGi bundle contributions can be used in Tuscany which provide modularity and versioning with the help of an OSGi runtime. Plain Jar contributions or folders use a single classloader at the moment and the proposed fixes will introduce contribution classloaders to isolate contributions. SCA contributions can specify dependencies in terms of import/export statements in the same way as OSGi bundles. If you consider Java contributions, SCA contribution dependencies are a subset of OSGi bundle dependencies, because SCA does not support versioning or any of the other attributes that can be associated with importing packages in OSGi. So SCA contribution classloading will be a simpler version of OSGi bundle classloading. The code for supporting SCA import/export is already in place in Tuscany- it just doesn't get used because the thread context classloader is currently used to resolve classes. 2) Classloading architecture for SCA runtime modules At the moment, Tuscany uses a single classloader for the runtime and its dependencies, and even though Tuscany runtime architecture uses extensible modules with reasonably well defined dependencies, module isolation is not achieved because of the use of a single classloader. Tuscany also has dependencies on many libraries which rely on the thread context classloader. Even though we are looking at running Tuscany in an OSGi runtime to support distributed-OSGi, at the moment we are still assuming that by default Tuscany would be run without an OSGi runtime. Hence the proposed fixes aim to minimize Tuscany changes required to implement 2b). Tuscany's use of thread context classloader will be removed wherever possible, but the requirement on thread context classloader will not be removed altogether since it is used by libraries that Tuscany depends on. There are two issues with modularizing Tuscany runtime using OSGi or OSGi-style classloading. Thread context classloaders and OSGi dont go very well together. And the extension module architecture used by Tuscany where a core module is extended through the use of extension modules ends up in a classloader hierarchy which is the reverse of what is required - the core bundle does not have visibility of the classes from
Re: Classloading in Tuscany
Thank you, Ant. I will try to split the work into small pieces and submit separate patches. Thank you... Regards, Rajini On 10/12/07, ant elder [EMAIL PROTECTED] wrote: On 10/11/07, Rajini Sivaram [EMAIL PROTECTED] wrote: Hello, Tuscany's use of classloaders doesn't seem to be well-defined, even though the concept of a runtime classLoader and contribution classloaders should have made it easy to isolate these namespaces. All Tuscany samples and tests are currently run with a single application classloader containing absolutely everything including Tuscany, all the jar files Tuscany requires and all the Java contribution jars/folders. I am running Tuscany as a bundle inside an OSGi runtime, and came across some issues with classloading when multiple classloaders are used. Even though these can be fixed for OSGi without changes to the non-OSGi related code in Tuscany, it will be good to fix these properly in Tuscany since these issues affect anyone who wants to use Tuscany without a great big classloader hierarchy containing Tuscany, all its dependencies and all contributions. Here is my understanding of classloaders used by Tuscany: 1) Tuscany Runtime classloader This is the classloader used to load Tuscany itself. It should be able to locate all Tuscany jar files and all its dependent jar files (eg. axis2). There are many locations in Tuscany which explicitly read the classloader used to load one Tuscany class in order to load another Tuscany class. For example, many of the files defined in META-INF/services and the classes they refer to are loaded in this way. 2) Contribution classloaders Referred to as application classloader in the DefaultSCADomain, a separate classloader can (in theory) be used to refer to the contributions - in the case of DefaultSCADomain, this is a single classloader associated with a single contribution. There is currently no concept of a contribution classloader for each contribution (except for OSGi contributions), and all resolution of classes from contributions is done using a single classloader. This does not reflect the SCA specification, which requires contribution imports/exports to be explicitly specified - requiring multiple classloaders to enforce the import/export definition during class resolution. 3) Thread context classloader Tuscany sets thread context classloader only in one class - HotUpdatableSCADomain (which sets Context classloader to a single URLClassLoader containing all the contribution jar files, with the original context classloader as parent). Tuscany uses the thread context classloader in around 30 different locations. Around half of these have FIXMEs saying that the classloader should be passed in. Many of these uses of the context classloader are trying to obtain the runtime classloader. And at least one is trying to obtain the contribution classloader. Many libraries which are used by Tuscany require the thread context classloader to be able to load the library classes. Most of these use the factory pattern and dynamically load implementation classes to create instances using the context classloader (eg. javax.xml.datatype.DataTypeFactory.newInstance()). The context classloader should in these cases to be able to find classes in Tuscany's dependent jar files, and hence the classloader used to load these dependent jars should be on the thread context classloader hierarchy. Axis2 libraries (and possibly others) use the thread context classloader to load Tuscany classes. Axis2 needs to find Tuscany's message receivers org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceInOutSyncMessageReceiverand org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceInMessageReceiver, and these are loaded by Axis2 using the context classloader. So Tuscany runtimeClassloader should be on the thread context classloader hierarchy. 4) Java Application classloader Tuscany doesn't directly rely on the application classloader (the classloader corresponding to CLASSPATH). But since Tuscany doesn't set the thread context classloader, for any application that doesn't explicitly set thread context classloader, there is an indirect dependency on the application classloader, and hence CLASSPATH should contain everything required by the thread context classloader (which at the moment includes the entire world). So we have the following requirements on classloaders: 1. Tuscany runtime classloader should find Tuscany and all its dependencies (essentially tuscany-sca-manifest.jar). 2. Contributions are not required to be on the classpath, nor do they have to be visible to the thread context classloader. One classloader per contribution is required to enforce SCA contribution import/export semantics. 3. Thread context classloader should be able to
Re: Classloading in Tuscany
On 10/11/07, Rajini Sivaram [EMAIL PROTECTED] wrote: Hello, Tuscany's use of classloaders doesn't seem to be well-defined, even though the concept of a runtime classLoader and contribution classloaders should have made it easy to isolate these namespaces. All Tuscany samples and tests are currently run with a single application classloader containing absolutely everything including Tuscany, all the jar files Tuscany requires and all the Java contribution jars/folders. I am running Tuscany as a bundle inside an OSGi runtime, and came across some issues with classloading when multiple classloaders are used. Even though these can be fixed for OSGi without changes to the non-OSGi related code in Tuscany, it will be good to fix these properly in Tuscany since these issues affect anyone who wants to use Tuscany without a great big classloader hierarchy containing Tuscany, all its dependencies and all contributions. Here is my understanding of classloaders used by Tuscany: 1) Tuscany Runtime classloader This is the classloader used to load Tuscany itself. It should be able to locate all Tuscany jar files and all its dependent jar files (eg. axis2). There are many locations in Tuscany which explicitly read the classloader used to load one Tuscany class in order to load another Tuscany class. For example, many of the files defined in META-INF/services and the classes they refer to are loaded in this way. 2) Contribution classloaders Referred to as application classloader in the DefaultSCADomain, a separate classloader can (in theory) be used to refer to the contributions - in the case of DefaultSCADomain, this is a single classloader associated with a single contribution. There is currently no concept of a contribution classloader for each contribution (except for OSGi contributions), and all resolution of classes from contributions is done using a single classloader. This does not reflect the SCA specification, which requires contribution imports/exports to be explicitly specified - requiring multiple classloaders to enforce the import/export definition during class resolution. 3) Thread context classloader Tuscany sets thread context classloader only in one class - HotUpdatableSCADomain (which sets Context classloader to a single URLClassLoader containing all the contribution jar files, with the original context classloader as parent). Tuscany uses the thread context classloader in around 30 different locations. Around half of these have FIXMEs saying that the classloader should be passed in. Many of these uses of the context classloader are trying to obtain the runtime classloader. And at least one is trying to obtain the contribution classloader. Many libraries which are used by Tuscany require the thread context classloader to be able to load the library classes. Most of these use the factory pattern and dynamically load implementation classes to create instances using the context classloader (eg. javax.xml.datatype.DataTypeFactory.newInstance()). The context classloader should in these cases to be able to find classes in Tuscany's dependent jar files, and hence the classloader used to load these dependent jars should be on the thread context classloader hierarchy. Axis2 libraries (and possibly others) use the thread context classloader to load Tuscany classes. Axis2 needs to find Tuscany's message receivers org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceInOutSyncMessageReceiverand org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceInMessageReceiver, and these are loaded by Axis2 using the context classloader. So Tuscany runtimeClassloader should be on the thread context classloader hierarchy. 4) Java Application classloader Tuscany doesn't directly rely on the application classloader (the classloader corresponding to CLASSPATH). But since Tuscany doesn't set the thread context classloader, for any application that doesn't explicitly set thread context classloader, there is an indirect dependency on the application classloader, and hence CLASSPATH should contain everything required by the thread context classloader (which at the moment includes the entire world). So we have the following requirements on classloaders: 1. Tuscany runtime classloader should find Tuscany and all its dependencies (essentially tuscany-sca-manifest.jar). 2. Contributions are not required to be on the classpath, nor do they have to be visible to the thread context classloader. One classloader per contribution is required to enforce SCA contribution import/export semantics. 3. Thread context classloader should be able to see Tuscany's dependencies and also Tuscany classes - so this can be the same as (or a child of) the Tuscany runtime classloader. 4. Any code using Tuscany should either have Tuscany runtime and its dependencies on the CLASSPATH, or should set the thread context
Re: Classloading in Tuscany
Rajini, Little though here: - can this be done in a way that moves us closer to the OSGi handling of classloading? - so if ever we wanted an OSGi style runtime, it would be easier to adapt what we have... Yours, Mike. Rajini Sivaram wrote: Thank you, Ant. I will try to split the work into small pieces and submit separate patches. Thank you... Regards, Rajini On 10/12/07, ant elder [EMAIL PROTECTED] wrote: On 10/11/07, Rajini Sivaram [EMAIL PROTECTED] wrote: Hello, Tuscany's use of classloaders doesn't seem to be well-defined, even though the concept of a runtime classLoader and contribution classloaders should have made it easy to isolate these namespaces. All Tuscany samples and tests are currently run with a single application classloader containing absolutely everything including Tuscany, all the jar files Tuscany requires and all the Java contribution jars/folders. I am running Tuscany as a bundle inside an OSGi runtime, and came across some issues with classloading when multiple classloaders are used. Even though these can be fixed for OSGi without changes to the non-OSGi related code in Tuscany, it will be good to fix these properly in Tuscany since these issues affect anyone who wants to use Tuscany without a great big classloader hierarchy containing Tuscany, all its dependencies and all contributions. Here is my understanding of classloaders used by Tuscany: 1) Tuscany Runtime classloader This is the classloader used to load Tuscany itself. It should be able to locate all Tuscany jar files and all its dependent jar files (eg. axis2). There are many locations in Tuscany which explicitly read the classloader used to load one Tuscany class in order to load another Tuscany class. For example, many of the files defined in META-INF/services and the classes they refer to are loaded in this way. 2) Contribution classloaders Referred to as application classloader in the DefaultSCADomain, a separate classloader can (in theory) be used to refer to the contributions - in the case of DefaultSCADomain, this is a single classloader associated with a single contribution. There is currently no concept of a contribution classloader for each contribution (except for OSGi contributions), and all resolution of classes from contributions is done using a single classloader. This does not reflect the SCA specification, which requires contribution imports/exports to be explicitly specified - requiring multiple classloaders to enforce the import/export definition during class resolution. 3) Thread context classloader Tuscany sets thread context classloader only in one class - HotUpdatableSCADomain (which sets Context classloader to a single URLClassLoader containing all the contribution jar files, with the original context classloader as parent). Tuscany uses the thread context classloader in around 30 different locations. Around half of these have FIXMEs saying that the classloader should be passed in. Many of these uses of the context classloader are trying to obtain the runtime classloader. And at least one is trying to obtain the contribution classloader. Many libraries which are used by Tuscany require the thread context classloader to be able to load the library classes. Most of these use the factory pattern and dynamically load implementation classes to create instances using the context classloader (eg. javax.xml.datatype.DataTypeFactory.newInstance()). The context classloader should in these cases to be able to find classes in Tuscany's dependent jar files, and hence the classloader used to load these dependent jars should be on the thread context classloader hierarchy. Axis2 libraries (and possibly others) use the thread context classloader to load Tuscany classes. Axis2 needs to find Tuscany's message receivers org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceInOutSyncMessageReceiverand org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceInMessageReceiver, and these are loaded by Axis2 using the context classloader. So Tuscany runtimeClassloader should be on the thread context classloader hierarchy. 4) Java Application classloader Tuscany doesn't directly rely on the application classloader (the classloader corresponding to CLASSPATH). But since Tuscany doesn't set the thread context classloader, for any application that doesn't explicitly set thread context classloader, there is an indirect dependency on the application classloader, and hence CLASSPATH should contain everything required by the thread context classloader (which at the moment includes the entire world). So we have the following requirements on classloaders: 1. Tuscany runtime classloader should find Tuscany and all its dependencies (essentially tuscany-sca-manifest.jar). 2. Contributions are not required to be on the classpath, nor do they have to be visible to the thread context classloader. One classloader per contribution is required to enforce SCA