Summary
How to integrate declared OSGi services into an existing RCP application.
Background
Traditionally you register and consume OSGi services using Java code. However in a truly dynamic system with bundles coming and going, your code must explicitly track the services. This can get very complicated with multiple services and multiple dependencies between them. As of OSGi 4.1 (and Equinox in Eclipse 3.3) we can use declarative services to deal with dependencies. There are great links to deal with all of this, in particular those supplied by Neil Bartlett. However it is not at all clear how to use declaratively declared services in an existing GUI application. That’s the purpose of this post.
Caveat
Would you even want to do this? As of 3.4, GUI RCP apps are fundamentally not dynamic as the extension point based UI is not itself dynamic. Hence any service-based dynamism should be hidden behind some static facade that the UI accesses. However, this is good thought experiment to better understand declarative services in OSGI.
Solution Theory
The declarative services are all defined and intantiated via entries in xml files within their bundles. However how does an RCP application that is defined and instantiated via extension points (in particular org.eclipse.core.runtime.applications) then access these?
The answer is the reference element in declarative services. This allows OSGI components to define dependencies and, crucially, have methods that are passed explicit Java references to these dependencies. These methods are defined in the bind and unbind attributes, and can be used as callbacks to provide your Java code with references to the declared services.
Let us say use have declared a new OSGi service based in an interface IMyService. This is now running in your VM but you have no Java reference to it. So:
- In your Java code create another interface
IMyServiceConsumerwith asetService(IMyService)method. - Create an implementation of
IMyServiceConsumerand programmatically register this as an OSGi service. This is now running in OSGi but of course itssetServicehas not yet been called. - Now create an OSGi component –
MyServiceMediatorwhich has anaddService(IMyService)and anaddConsumer(IMyServiceConsumer)methods. TheaddServicewill simply store theIMyServicereference whilst theaddConsumerwill use this in the callbackIMyServiceConsumer.setService() - The final step is to declare this component adding
referenceelements for bothIMyServiceandIMyServiceConsumer. Each reference element hasbindandunbindattributes that refer to methods that will be supplied with a reference to the service. Each method is called whenever an instance of the service is registered or unregistered. This reference can then be passed on to your client code.
Solution Practice
These are steps to go through in practice:
- Create a bundle containing the IMyService interface and an implementation;
- Define this as a declarative service with an xml file in the OSGI-INF directory:

- Ensure the xml file is picked up by OSGi declarative services by adding a line to the bundle’s MANIFEST.MF file:

- Create the
IMyServiceConsumerinterface and an implementation; - Whenever the implementation class requires a reference to
IMyServiceit should programmatically register itself as an OSGi service, hence obtaining theIMyServicevia the callback, and then deregister itself as soon as possible:
- Create the
MyServiceMediatorimplementation: - Declare this as an OSGi component, adding the essential
referenceelements to ensure all the bind methods are called:
- Finally split this up into seperate bundles as suits your purposes – it is likely you will want the actual
IMyServiceimplementation in a seperate, swapable bundle.

Notes and Further Caveats
- Why use a mediator at all? Can the core service be set up with
referenceelements direct? Absolutely! However the mediator allows you to keep the main service interface completely ‘clean’ – with no knowlede of consumers etc. - You will still need to do some coding to account for dynamic behaviour as
IMyServicemight be unregistered at any time. Ensure either the mediator and/or the consumer can deal with this situation – most probably using a method defined by the unbind attribute on the service declaration.
