2

Hello fellow programmers,

I recently started working on an OSGi project. I was trying to get used to OSGi services using Declarative Services. I have created an inteface bundle (A), a bundle(B) implementing this interface and a bundle consuming the service(C). So far so good. But when I tried to create a bundle implementing another interface(D) I found out that I couldn't use the service provided by bundle (A).

So I have 4 bundles:

  • Bundle A: API
  • Bundle B: Bundle implements A
  • Bundle D: implements E
  • Bundle E: another api bundle

Why can't I consume service E from bundle B?

Bundle A

package liqueurplant.osgi.silo.driver.api;

import org.osgi.annotation.versioning.ProviderType;

@ProviderType
public interface SiloDriverIf {

void openDriver();

void closeDriver();
}

Bundle B

package liqueurplant.osgi.silo.driver;

import liqueurplant.osgi.silo.controller.api.SiloCtrlIf;
import liqueurplant.osgi.silo.driver.api.SiloDriverIf;
import org.osgi.service.component.annotations.*;

@Component
public class SimpleSiloDriver implements SiloDriverIf {

private SiloCtrlIf siloCtrl;

@Activate
public void activate() {
    System.out.println("Driver activated.");
}

@Deactivate
public void deactivate() {
    siloCtrl.put2EventQueue("High lever reached");
}

@Override
public void openDriver() {

}

@Override
public void closeDriver() {

}

@Reference(
        name = "siloCtrl.service",
        service = SiloCtrlIf.class,
        /* Cardinality (Whether the bundle works with or without service.
        // Mandatory: mandatory and unary 1..1
        // At least one: mandatory and multiple 1..n
        // Multiple: optional and multiple 0..n
        // Optional: optional and unary 0..1
        //*/
        cardinality = ReferenceCardinality.MANDATORY,
        policy = ReferencePolicy.DYNAMIC,
        unbind = "unsetSiloCtrlIf"
)
protected void setSiloCtrlIf(SiloCtrlIf siloCtrl){
    System.out.println("Binding silo controller service");
    this.siloCtrl = siloCtrl;
}

protected void unsetSiloCtrlIf(SiloCtrlIf siloCtrl){
    System.out.println("Unbinding silo controller service.");
    this.siloCtrl = null;
}
}

Bundle D

package liqueurplant.osgi.silo.controller;

import liqueurplant.osgi.silo.controller.api.SiloCtrlIf;
import org.osgi.service.component.annotations.*;

import java.util.concurrent.ArrayBlockingQueue;

@Component
public class SimpleSiloCtrl implements SiloCtrlIf, Runnable {

private ArrayBlockingQueue<String> eventQueue;

public SimpleSiloCtrl() {
    eventQueue = new ArrayBlockingQueue<String>(20);
}

@Activate
public void activate() {
    System.out.println("Silo controller activated.");
}

@Override
public void put2EventQueue(String event) {
    try {
        eventQueue.put(event);
        System.out.println(eventQueue.take());
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

@Override
public void run() {
    while(true){
        if(!eventQueue.isEmpty()){
            try {
                System.out.println(eventQueue.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


}

Bundle E

package liqueurplant.osgi.silo.controller.api;

import org.osgi.annotation.versioning.ProviderType;

@ProviderType
public interface SiloCtrlIf {

    void put2EventQueue(String event);
}

When I try to run the code the @Activate methods on Bundle B are not working and the Service siloCtrl.service is not binding. Any help would be appreciated. Thank you in advance!

ᄂ ᄀ
  • 5,669
  • 6
  • 43
  • 57
Panos Boc
  • 1,128
  • 1
  • 8
  • 8
  • I dont see an obvious reason why it should not work. Can you try to just use @Reference on setSiloCtrlIf without any attributes. Does SimpleSiloCtrl become active? – Christian Schneider Mar 11 '17 at 14:12
  • No adding Reference without attributes didn't work. SimpleSiloCtrl becomes active. I don't see any obvious reason why my Activate method don't run. Any ideas? @Christian Schneider – Panos Boc Mar 11 '17 at 14:23
  • What do you see in the shell for scr:info or scr:details for this component? – Christian Schneider Mar 11 '17 at 15:21
  • I see activation: delayed and activate method:activate and deactivate method: deactivate. But these methods are not running @Christian Schneider – Panos Boc Mar 11 '17 at 16:10
  • All classes have a `@Component` and implements an interface : by default, they are not activated until someone use them. I suppose you have somewhere a bundle which use theses services ? If not, you should use the "immediate=true" property on the component you want to be always activated. – Jérémie B Mar 14 '17 at 08:53
  • That might indeed be the problem. – Christian Schneider Mar 14 '17 at 09:56
  • This was indeed the problem. Immediate = true fixed it. Thank you all! And sorry for the late response. – Panos Boc Apr 13 '17 at 19:10

0 Answers0