annotationsosgieventhandlerservice-referencedeclarative-services

How do I use Declarative Services to ensure that EventAdmin is not null?


Im new to OSGi and I tried to create a simple EventPublisher/-Admin application using DS to ensure that the EventAdmin is not null. But I'm not sure how to use the DS in the right way.

The Activator class:

package publishertest;

import java.util.HashMap;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;

public class Activator implements BundleActivator {

    private static BundleContext context;
    
    @Reference
    EventAdmin eventAdmin;

    static BundleContext getContext() {
        return context;
    }

    public void start(BundleContext bundleContext) throws Exception {
        Activator.context = bundleContext;
        Event event = new Event("test", new HashMap<String, Object>());
        eventAdmin.postEvent(event);
        System.out.println("event posted");
    }

    public void stop(BundleContext bundleContext) throws Exception {
        Activator.context = null;
    }

}

The EventHandler class:

package publishertest;

import org.osgi.service.component.annotations.Component;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;

@Component(
    property = {
        "event.topics=org/osgi/framework/BundleEvent/STARTED,test"
    }
)


public class ServiceComponent implements EventHandler {

    public void handleEvent(Event event) {
        System.out.println(event.getTopic());
    }

}

Adding the @Reference annotation leads to a BundleException. Can somebody help? thanks :)


Solution

  • You are mixing up incompatible technologies here. A DS component should not implement BundleActivator. In your case your class is initialized as a bundle activator the DS annotations are ignored. This is why eventAdmin is null.

    Instead you should DS to activate your component via @Component annotation and @Activator annotation on constructor.

    Your code should look like this:

    @Component(immediate=true)
    public class MyClass {
    
    @Activate
    public MyClass(@Reference EventAdmin eventAdmin) {
        Event event = new Event("test", new HashMap<String, Object>());
        eventAdmin.postEvent(event);
        System.out.println("event posted");
    }
    
    }