Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OSGi Declarative Services in Eclipse, multiple service interfaces, and Thread Safety

I just stumbled over a phenomenon in my code which comes down to this:

I have an OSGi Declarative Service providing two service interfaces configured as follows:

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" deactivate="dispose" enabled="true" name="redacted.redactedstore">
   <implementation class="redacted.RedactedStore"/>
   <service>
      <provide interface="redacted.IRedactedStore"/>
      <provide interface="redacted.IRedactedStoreControl"/>
   </service>
</scr:component>

In my code, I have two different threads which both open a ServiceTracker to get the service instance, but via different interfaces:

tracker = new ServiceTracker<>(getBundle().getBundleContext(), <serviceClass>.class, null);
tracker.open();
tracker.waitForService(1000l);

So one thread uses IRedactedStore as service class and the other uses IRedactedStoreControl as service interface.

So what seems to happen is that when both threads run in parallel at the right time, the Equinox SCR will instantiate not one (as I would expect) but two instances of the component implementation class.

Is this behavior correct? Or is this a bug in the Equinox implementation of OSGi?

If the behavior is correct, can I do something in my code to prevent that by configuring the service another way? (of course I could restructure the service so it only provides one interface, or I could synchronize the service trackers...)

like image 662
Stefan Winkler Avatar asked Jul 17 '19 12:07

Stefan Winkler


People also ask

What are declarative services in OSGi?

OSGi declarative services are the OSGi way to handle the instantiation problem: the fact that we want to code to interfaces, but we need some way to instantiate classes and some way to provide some concrete instance of an interface in order for the parts of our modular application to work together.

What capability does OSGi component @component provide?

The @Component annotation makes the class an OSGi component. Setting a service property to a particular service type in the annotation, allows other components to reference the service component by the specified service type.

How to use declarative services in OSGi?

That means, if you want to use declarative services in your application, you need to ensure that a Service Component Runtime bundle is installed and activated in your environment. When talking about OSGi declarative services you will always talk about components.

What is increasingly declarative services?

Increasingly Declarative Services (DS) is the backbone of OSGi. While other Dependency Injection (DI) frameworks can be used with OSGi, the OSGi Alliance strongly recommend DS.

What is DS in OSGi?

Declarative Services (DS) Increasingly Declarative Services (DS) is the backbone of OSGi. While other Dependency Injection (DI) frameworks can be used with OSGi, the OSGi Alliance strongly recommend DS. All of the enRoute examples are DS based and walk you from the simplest of DS components quickstart through a range of DS capabilities.

What is the lazy bundle activation policy in OSGi?

Note: When using OSGi declarative services, it’s good practice to use the lazy bundle activation policy (Bundle-ActivationPolicy: lazy), which means instantiation of declarative services takes place just before the service is called.


1 Answers

For non prototype scope component I would expect that it is created only once. See declarative services spec.

If this issue only happens when the service trackers run in parallel then I suspect it might be an concurrency issue in equinox scr.

like image 107
Christian Schneider Avatar answered Oct 19 '22 20:10

Christian Schneider