Question

I'm designing an application whose functionality need to be the same in different contexts. Let refer to the picture below:

                     +----+         +----+       +----+
                     |B1  +--->-----+B2  +-->----+B3  |
                     |ctx1|  use    |ctx1|  use  |ctx1|
                     +----+ service +----+service+----+



     +-------+       +----+         +----+       +----+
     |Context|       |B1  +--->-----+B2  +-->----+B3  |
     |Manager|       |ctx2|  use    |ctx2|  use  |ctx2|
     |       |       +----+ service +----+service+----+
     |       |         :              :            :
     +-------+         :              :            :

                     +----+         +----+       +----+
                     |B1  +--->-----+B2  +-->----+B3  |
                     |ctxN|  use    |ctxN|  use  |ctxN|
                     +----+ service +----+service+----+

There are 4 bundles:

  • Context Manager
  • B1
  • B2
  • B3

Context Manager is the bundle that is in charge of knowing when a new context is available and to instantiate a new version of B1, B2 and B3. The services offered by B2 and B3 are exactly the same across contexts, just i want to add a property on the service to distinguish in which context it's running (ctx1 vs ctxN for example). Now this is the theory of what i want to achieve, i thought i could easily implement it via Declarative Services, in fact i made B1 *B2* and B3 to be ComponentFactory by specifying the component.factory property in the component header, and i set B1 to refer to a service provided by B2, also i set B2 to refer to a service provided by B3. These are the challenges i faced:

  • Context Manager learns about the ComponentFactory service provided only by B3, the first time, as long as B1 and B2 are not yet satisfied, they don't register the ComponentFactory service in the service registry. As long as this is the case B1 and B2 don't get instantiated for the first context.
  • B1 and B2 once created, gets an arbitrary service from other contexts, i was thinking to set the reference.target parameter to only pick the service from the same context but it doesn't seem there is any way to declarative do this, seems like the only way to select a service from the same context is by setting a reference with cardinality 0..n and to provide a "bind" method that select based on the current context, this means that every component has to replicate the same selection logic which instead i was thinking could be provided by the Context manager when a newInstance is called. In fact if during the call ComponentFactory.newtInstance(props); i could provide a property like .target=(context=mycontext) then this could be achieved, but I don't know all the reference the component is actually using.

At this point i'm thinking to actually avoid using Declarative Service and to have the per-context bundle extend a base class i will provide which will basically implement the dependency tracking similar to org.apache.felicy.dependencymanager but such that the developer of the per-context component don't have to worry to know in which context the code sits. However i hate to revert to this solution, i feel i'm just replicating logic may exist already in the OSGi specification and so my question is:

What is the best way to create bundles that can run on a per-context base in OSGi, such that the bundles can describe in a declarative way the dependency, without having to explicitly mention the context in which they are running?

Was it helpful?

Solution 2

Answering my own, question. As long as i was in a need for a solution, thanks to the help of the Apache Felix DependencyManager i have replaced the Declarative Services and for each context,bundle (Container in the source code below) i create a new instance of dependency manager which helps to track the services on a per-context base.

For code reference please look at: OpenDayLight ComponentActivatorAbstractBase

For managing dependencies and ensure they are in the same context a special ServiceDependency is created, for reference look at: OpenDayLight ServiceDependency

For example on how the activator is actually used refer to: OpenDayLight sample activator

Hope this can be of use to others too.

OTHER TIPS

There is some confusing terminology in here. You talk about bundles B1, B2 and B3. And you also talk about instantiating new versions of B1, B2 and B3. Do you mean updating the bundles B1, B2 and B3? Or do you mean bundles B1, B2 and B3 offer services S1, S2 and S3, respectively?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top