chemistry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Sascha Homeier (JIRA)" <>
Subject [jira] [Commented] (CMIS-878) Allow loading classes from other OSGi Bundles in OSGi Client Wrapper
Date Fri, 30 Jan 2015 01:26:35 GMT


Sascha Homeier commented on CMIS-878:

After some research I like the suggestion of [~fmeschbe] most to use the OSGi extender model
to get the Bundles which contain SPI implementations.
But instead of injecting the class loaders of these Bundles we also can consume the SPI implementations
directly as real OSGI services.

For both options I can think of the following:

h4. *1) Get the ClassLoader from other OSGI Bundles*
Inside the Chemistry OpenCmis OSGI Client Wrapper the Activator needs to be adjusted to add
a Bundle Listener which listens for Bundle changes (additional logic can be added to also
iterate over already loaded bundles in case Chemistry Client Wrapper was started later then
SPI Implementation Bundles).
If a bundle is in proper state (e.g. RESOLVED) we should be able to get the Bundle Classloader
via BundleWiring:

public void bundleChanged(BundleEvent event) {
        if (event.getType() == BundleEvent.RESOLVED) {
	    BundleWiring bundleWiring = event.getBundle().adapt(BundleWiring.class);
	    ClassLoader classLoader = bundleWiring.getClassLoader();
            // pass the class loader to ClassLoaderUtil

This ClassLoader then can be passed to ClassLoaderUtil and when it tries to load a class it
first uses current behaviour by trying to load the class from context class loader. If this
failed it tries loading class by iterating over List of injected class loaders.

We still need to define how to tag the Bundles which contain OpenCmis SPI implementations.
For example it could be done by setting a Manifest header like
In Activator we then can get the header via:
        if (event.getType() == BundleEvent.RESOLVED) {
            String header = (String) event.getBundle().getHeaders().get("Chemistry-SPI");
            // if header is not null get the class loader via BundleWiring interface and pass
it to ClassLoaderUtil

A better option may be to put a property.

h4. *2) Loading SPI Implementations from other OSGI Bundles*

As OpenCmis does not use java.util.ServiceLoader  I would prefer to provide SPI services as
real OSGI services instead of specifying them in files META-INF/services/<FQCN_OF_SPI>.
The OSGI services then can be accessed in Activator of OpenCmis Client Wrapper. For example
AuthenticationProvider can be retrieved via:
public void start(BundleContext context) {
    ServiceReference<?> serviceReference = context.getServiceReference(org.apache.chemistry.opencmis.commons.spi.AuthenticationProvider.class.getName());
    AuthenticationProvider authProvider = (AuthenticationProvider) context.getService(serviceReference);

    // pass authProvider to proper places in OpenCmis Client framework

This would make the Client library of OpenCmis much more OSGI compliant but is also the most
intrusive option:
It requires to pass the SPI implementations to different locations in OpenCmis framework.
For example AuthenticationProvider implementation could be passed to CmisBindingFactory while
an own Cache implementation is needed in SessionImpl. When injecting ClassLoaders instead
of explicit services we can pass them to a single location: ClassLoaderUtil.

I'm interested in what the OpenCmis developers think about these options?
Do you see other alternatives or improvements?

> Allow loading classes from other OSGi Bundles in OSGi Client Wrapper
> --------------------------------------------------------------------
>                 Key: CMIS-878
>                 URL:
>             Project: Chemistry
>          Issue Type: Improvement
>          Components: opencmis-client
>    Affects Versions: OpenCMIS 0.12.0
>         Environment: OSGi
>            Reporter: Sascha Homeier
>            Priority: Minor
> When using the OpenCMIS OSGi Client Wrapper it is hard to load classes from other bundles.
For example if you specify an own Authentication Provider class as Session Parameter then
the Wrapper will not find this class when it is located inside another bundle. Same problem
should occur when defining an own Cache.
> *1)*
> It would be nice if other bundles could register their Classloaders so that ClassLoaderUtil
can use it when trying to load classes.
> *2)*
> Another simpler option would be to simply add "DynamicImport-Package: *" to the Manifest
of the Wrapper. By doing this the Wrapper will find all classes which are exported by other
bundles. Though this approach feels more like a hack since it breaks modularity.
> What do you think about it?
> Cheers
> Sascha

This message was sent by Atlassian JIRA

View raw message