javaosgiosgi-fragment

Registering services inside OSGi extension bundles


I'm playing with OSGi framework extension bundles in order to fully understand them. After looking at the OSGi R6 specification (3.15 and 4.2.4.1) I've sucessfully invoked the "start" method of the ExtensionBundleActivator. Now I'm trying to register a service inside such activator. However, when I trying to consume such service, the reference annotation fails to connect the service.

Here's my code ('ve changed the name of the bundle, but it shouldn't matter):

public class ExtensionBundleActivator implements BundleActivator {

    @Override
    public void start(BundleContext context) throws Exception {
        System.out.println("start extension bundle activator!");

        context.registerService(
            BundleExample.class.getName(),
            new BundleExampleImpl(),
            new Hashtable<>(new HashMap<>()));
    }

    @Override
    public void stop(BundleContext context) throws Exception {
        //service automatically unregistered
    }

}

And here's the manifest of such extension bundle:

Manifest-Version: 1.0
Bnd-LastModified: 1476436248622
Build-Jdk: 1.8.0_91
Built-By: massi
Bundle-ClassPath: .
Bundle-ManifestVersion: 2
Bundle-Name: extensionbundleexample
Bundle-SymbolicName: com.massimobono.microsi.extensionbundleexample
Bundle-Version: 0.0.1.SNAPSHOT
Conditional-Package: com.massimobono.microsi.common.*;
Created-By: Apache Maven Bundle Plugin
ExtensionBundle-Activator: com.massimobono.microsi.bundleexample.imp
 l.ExtensionBundleActivator
Fragment-Host: system.bundle; extension:=framework
Provide-Capability: osgi.service;objectClass:List<String>="com.massimobo
 no.microsi.bundleexample.BundleExample"
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
Service-Component: OSGI-INF/com.massimobono.microsi.bundleexample.im
 pl.ExtensionBundleExample.xml
Tool: Bnd-3.0.0.201509101326

The consuming bundle (part of the bundle):

@Reference(cardinality=ReferenceCardinality.OPTIONAL)
public BundleExample actualBundleExample;

@Activate
public void activate() {
    System.out.println("activating " + this.getClass().getSimpleName() + "with actual bundle set to "+ this.actualBundleExample);
}

My question is: What am I doing wrong? Why the consumer can't detect the registered service of the extension bundle? Or maybe I'm just doing something the framework forbids... in this case is it impossible to provide a service from an extension bundle? How can I interact with the code within the extension bundle (aka accessing something inside the extension bundle itself)?

Here some notes:

  1. I'm using felix as OSGi implementation;
  2. Both "ExtensionBundleExample" and "BundleExample" are loaded inside the auto-process folder of felix (the default one is "bundle" but I tweaked the config.properties to use "corebundles" folder;
  3. The output corretly show "start extension bundle activator!" but when it's time to display the reference of actualBundleExample, the output shows "null";
  4. the optional cardinality of BundleExample is used for testing purposing: I just wanted to invoke the "acivator" method the consumer component has (in order to see the System.out.println console;
  5. from my previous question I understand extension bundles are a niche inside the OSGi framework, but I want to understand them nonetheless: I find the lack of examples on the internet regarding this topic quite annoying;

Thanks for any reply!


Solution

  • The primary purpose of extension bundles is for framework extensions, absolutely not for regular usage. I.e. extension bundles are often tightly coupled to a framework. The reason is that many rules do not count for extension bundles because they are on the "wrong" side of the fence. There are few examples for very good reasons. You should not use them unless you really know what you're doing because most of the OSGi rules do not apply.

    That said. My expectation is that the package you use for the BundleExample differs between the extension bundle (comes from the class path) and the DS example exported by some bundle. Since they come from different class loaders OSGi considers them different services because you would get a class loader exception when you tried to use it.

    You can solve this by letting the framework export this package.

    Just a guess.