1
votes

I have an unsatisfied osgi service:

ls 142
Components in bundle A: 
ID  State           Component Name          Located in bundle
90  Unsatisfied     ServiceA            A(bid=142)

The reference to ServiceB is unsatisfied:

comp 90
    Component[
    name = ServiceA
    activate = activate
    deactivate = deactivate
    modified = 
    configuration-policy = optional
    factory = null
    autoenable = true
    immediate = false
    implementation = ServiceA
    state = Unsatisfied
    properties = 
    serviceFactory = false
    serviceInterface = [ServiceA]
    references = {
        Reference[name = ServiceB, interface = ServiceB, policy = static, cardinality = 1..1, target = null, bind = setServiceB, unbind = unsetServiceB]
    }
    located in bundle = B_2.12.0.qualifier [142]
]
Dynamic information :
  *The component is NOT satisfied
  The following references are not satisfied:
    Reference[name = ServiceB, interface = ServiceB, policy = static, cardinality = 1..1, target = null, bind = setServiceB, unbind = unsetServiceB]
  Component configurations :
    Configuration properties:
      component.name = ServiceA
      component.id = 136
      objectClass = String[ServiceA]
    Instances:

Nevertheless, ServiceB is active:

ls 52
Components in bundle B: 
ID  State           Component Name          Located in bundle
14  Active      ServiceB            B(bid=52)

So why is the reference from ServiceA to ServiceB unsatisfied? A restart of bundle A (stop and start) doesn't help. Configuring the reference on a working ServiceC in bundle C makes ServiceC unsatisfied.

Update: ServiceB has been registered

The result of the "services" command in the osgi console contains the following nipped:

{ServiceB}={service.id=180}
  Registered by bundle: Z_2.12.0.qualifier [123]
  No bundles using service.

Additional information: configuration, initialization and registration of ServiceA and ServiceB

ServiceB is basically an apache cxf web service, that's implementing an interface. This interface has been generated out of a wsdl. The ServiceB is registered programmatically. ServiceA has a reference to the generated interface. This pattern works perfectly with another web service (lets say ServiceC and ServiceD).
And if it helps: This pattern even worked between ServiceA and ServiceB until we upgraded apache cxf. I didn't provide this information before because I feared it would make this problem too complicated ????.

Update: configuration of the component ServiceB

There are two parts considering the configuration: The xml file and the registration. The xml file contains the implementation class "WebServiceConfigImpl", a provided interface "WebServiceConfig" and some properties. One of the properties is the webservice "ServiceB" - the name under that the service is registered programmatically later in the start procedure.

xml file:

<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="activate" deactivate="deactivate" name="ServiceB">
   <implementation class="WebServiceConfigImpl"/>
   <service>
      <provide interface="WebServiceConfig"/>
   </service>
   <property name="webservice" type="String" value="ServiceB"/>
   <property name="address" type="String" value="${adresse}"/>
   <property name="username" type="String" value="${benutzer}"/>
   <property name="password" type="String" value="${passwort}"/>
   (...)
   two references to other osgi services for resolving the web service configuration
</scr:component>

registration: We are using our own org.osgi.util.tracker.ServiceTracker for this. This ServiceTracker is opened in the Activator of bundle Z. It calls the constructor of ServiceTracker with "WebServiceConfig" as parameter, so this ServiceTracker is notified if a Service providing the interface "WebServiceConfig" has been registered. Our implementation of the SeriveTracker now reads the property "webservice" and publishs the osgi service under this name:

context.registerService(serviceName, service, null);

After that, the service is available and activated in the osgi console.

Update: accessing ServiceB

After the registration through our ServiceTracker, ServiceB is available through the osgi console AND by source code:

ServiceTracker st = new ServiceTracker(bundleContext, "ServiceB", null);
st.open();
st.getService();

Update: accessing ServiceB 2

ServiceB is accessible via source code in bundle Z. But it cannot be accessed via source code from bundle A. Then the service object is null.

1
How does you component ServiceB look like? I suspect it does not export a service.Christian Schneider
@ChristianSchneider That was a good hint. I'm still investigating.Frank Büttner
Can you add the setup of your component B to the question?Christian Schneider
It is possible that both bundle are not using that same package containing WebServiceConfig interface.BJ Hargrave
@BJHargrave Good point, but this interface (ServiceB) exists only one time in my workspace. All bundle dependencies are set to the current snapshot version. The bundle containing the interface exists only one time (also at runtime). The interface is contained in bundle B.Frank Büttner

1 Answers

2
votes

I found a workaround to get programmatically access to ServiceB:

ServiceTracker st = new ServiceTracker(context, ServiceB.class.getName(), null);
st.open(true);
st.getService()

The boolean parameter in the open method makes the difference.

Unfortunatelly I wasn't able to answer the question why some bundles have "direct" access to the ServiceB (no parameter in the open method needed) and some need the "true" parameter.