*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

Reply via email to