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?