Search code examples
javaosgi

OSGI can not find ServiceReference


I have a very simple program starting up an OSGI framework (Felix in this case):

        final Map configMap = new HashMap();
        configMap.put(Constants.FRAMEWORK_STORAGE_CLEAN, "onFirstInit");
        m_framework = new Felix(configMap);
        m_framework.init();

        final BundleContext context = m_framework.getBundleContext();

        Bundle api = context.installBundle("file:../api/target/api-1.0.jar");
        Bundle provider = context.installBundle("file:../hello/target/hello-1.0.jar");

        m_framework.start();

        api.start();
        provider.start();

        System.out.println("List of all service references:");
        ServiceReference[] ss = context.getAllServiceReferences(null, null);
        for (ServiceReference sr : ss) {
            System.out.println("sr = " + sr);
        }
        System.out.println(HelloService.class.getName());            
        ServiceReference<HelloService> sr = (ServiceReference<HelloService>) context.getServiceReference(HelloService.class.getName());
        HelloService hs = context.getService(sr);
        System.out.println("hs: " + hs.sayHello("Bob"));

        m_framework.stop();

I have an API bundle which contains the HelloService interface class.

I have a Hello bundle which contains an implementation of the HelloService, conveniently named HelloServiceImpl.

These both seems fine, I can load them here and in the Felix console, I can't load the implementation without loading and starting the API (as expected).

I have simple debug println in the bundles to show them being activated, and the HelloServiceImpl being constructed.

This is how I register the service in the Hello module:

    System.out.println("Hello service implementation activated");
    HelloService hs = new HelloServiceImpl();
    context.registerService(HelloService.class.getName(), hs, null);
    System.out.println("Registered " + hs + " to " + HelloService.class.getName());

I print out all of the Service References in the framework, and see that there is, indeed, a HelloService reference listed (output below).

But when I try to look up the ServiceReference, so that I can invoke the service, the framework is returning null.

Below is the output of this routine:

API Activator fired.
Hello service implementation activated
HelloServiceImpl created
Registered com.mycompany.hello.HelloServiceImpl@64bf3bbf to com.mycompany.api.HelloService
List of all service references:
sr = [org.osgi.service.packageadmin.PackageAdmin]
sr = [org.osgi.service.condition.Condition]
sr = [com.mycompany.api.HelloService]
sr = [org.osgi.service.startlevel.StartLevel]
sr = [org.osgi.service.resolver.Resolver]
com.mycompany.api.HelloService
Error starting program: java.lang.NullPointerException: Specified service reference cannot be null.
java.lang.NullPointerException: Specified service reference cannot be null.
    at org.apache.felix.framework.BundleContextImpl.getService(BundleContextImpl.java:440)
    at com.mycompany.main.Main.main(Main.java:40)

Clearly missing something fundamental, curious why this is not working.


Solution

  • The problem is that inside OSGi HelloService interface is loaded from the bundle api-1.0.jar. Outside of OSGi HelloService interface is loaded from a jar on the classpath.

    So when you ask for the service references for HelloService you do not see any. The best way to interact with your service is from inside another OSGi bundle.

    If you must interact with the service from outside OSGi then instead of installing the api bundle you could export the package from system bundle. Use the run property: org.osgi.framework.system.packages.extra