*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(Class<T> extensionPointType) { ..... ClassLoader classLoader = extensionPointType.getClassLoader(); if (classLoader == null) { classLoader = Thread.currentThread().getContextClassLoader(); } List<String> 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
