OSGI Declarative Services (DS): What is a good way of using service component instances
Posted
by Christoph
on Stack Overflow
See other posts from Stack Overflow
or by Christoph
Published on 2009-07-09T09:20:15Z
Indexed on
2010/05/10
21:34 UTC
Read the original article
Hit count: 418
I am just getting started with OSGI and Declarative Services (DS) using Equinox and Eclipse PDE.
I have 2 Bundles, A and B. Bundle A exposes a component which is consumed by Bundle B. Both bundles also expose this service to the OSGI Service registry again.
Everything works fine so far and Equinox is wireing the components together, which means the Bundle A and Bundle B are instanciated by Equinox (by calling the default constructor) and then the wireing happens using the bind / unbind methods.
Now, as Equinox is creating the instances of those components / services I would like to know what is the best way of getting this instance?
So assume there is third class class which is NOT instantiated by OSGI:
Class WantsToUseComponentB{ public void doSomethingWithComponentB(){ // how do I get componentB??? Something like this maybe? ComponentB component = (ComponentB)someComponentRegistry.getComponent(ComponentB.class.getName()); }I see the following options right now:
1. Use a ServiceTracker in the Activator to get the Service of ComponentBundleA.class.getName() (I have tried that already and it works, but it seems to much overhead to me) and make it available via a static factory methods
public class Activator{ private static ServiceTracker componentBServiceTracker; public void start(BundleContext context){ componentBServiceTracker = new ServiceTracker(context, ComponentB.class.getName(),null); } public static ComponentB getComponentB(){ return (ComponentB)componentBServiceTracker.getService(); }; }
2. Create some kind of Registry where each component registers as soon as the activate() method is called.
public ComponentB{ public void bind(ComponentA componentA){ someRegistry.registerComponent(this); }
or
public ComponentB{ public void activate(ComponentContext context){ someRegistry.registerComponent(this); } }
}
3. Use an existing registry inside osgi / equinox which has those instances? I mean OSGI is already creating instances and wires them together, so it has the objects already somewhere. But where? How can I get them?
Conclusion Where does the class WantsToUseComponentB (which is NOT a Component and NOT instantiated by OSGI) get an instance of ComponentB from? Are there any patterns or best practises? As I said I managed to use a ServiceTracker in the Activator, but I thought that would be possible without it.
What I am looking for is actually something like the BeanContainer of Springframework, where I can just say something like Container.getBean(ComponentA.BEAN_NAME). But I don't want to use Spring DS.
I hope that was clear enough. Otherwise I can also post some source code to explain in more detail.
Thanks Christoph
UPDATED: Answer to Neil's comment:
Thanks for clarifying this question against the original version, but I think you still need to state why the third class cannot be created via something like DS.
Hmm don't know. Maybe there is a way but I would need to refactor my whole framework to be based on DS, so that there are no "new MyThirdClass(arg1, arg2)" statements anymore. Don't really know how to do that, but I read something about ComponentFactories in DS. So instead of doing a
MyThirdClass object = new MyThirdClass(arg1, arg2);
I might do a
ComponentFactory myThirdClassFactory = myThirdClassServiceTracker.getService(); // returns a if (myThirdClassFactory != null){ MyThirdClass object = objectFactory.newInstance(); object.setArg1("arg1"); object.setArg2("arg2"); } else{ // here I can assume that some service of ComponentA or B went away so MyThirdClass Componenent cannot be created as there are missing dependencies? }
At the time of writing I don't know exactly how to use the ComponentFactories but this is supposed to be some kind of pseudo code :)
Thanks Christoph
© Stack Overflow or respective owner