In my last post I explained how easy it is to inject your own objects. For the common use case that you want to specify an interface attribute but want an object being injected I showed a simple solution using a little factory. Another way of doing this is the use of OSGi declarative services (DS). But instead of creating a declarative service that implements the service interface you create a declarative service for a helper object that just registers your implementation class for the needed interface with the ContextInjectionFactory. So, the ContactPresentation code looks like this now:
... private IContactView contactView; @Inject public ContactPresenter(IContactView contactView) { this.contactView = contactView; ...
The xml for the declarative service is in OSGI-INF/views.xml:
<?xml version="1.0" encoding="UTF-8"?> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.e4.demo.contacts.mvp.views"> <implementation class="...mvp.views.ContactViewCreationFunction"/> <service> <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/> </service> <property name="service.context.key" type="String" value="...contacts.mvp.presenters.ContactPresenter$IContactView"/> </scr:component>
The implementation class provides the interface org.eclipse.e4.core.contexts.IContextFunction and an additional property with the name service.context.key specifies the actual interface that the contact function is going to register. Here is the simple code for the ContactViewCreationFunction:
public class ContactViewCreationFunction extends ContextFunction { @Override public Object compute(IEclipseContext context) { return ContextInjectionFactory.make(ContactView.class, context); } }
The only thing the ContactViewCreationFunction does is to bind the ConatcsView class to the context, using the above service.context.key to know the interface. I will check in the code soon, stay tuned…
It’s very important that you don’t forget to add the 2 manifest headers in the manifest.mf:
Service-Component: OSGI-INF/views.xml Bundle-ActivationPolicy: lazy
I would like to thank Tom Schindl for giving me the tip not to forget the lazy Bundle-ActivationPolicy!
Have Fun
Not knowing everything about DS and the Blueprint service, does the Blueprint service provide an alternative way to solve this same problem?
@Sudr, the Blueprint service is another OSGi service component model based on Spring Dynamic Modules (Spring DM). While it is not supported out of the box in e4 (e.g., it requires quite a lot Spring bundles at runtime), you could create an implementation that plays well with e4 DI. For a comparison of different component models take a look at Heiko Seeberger’s and my slides http://www.slideshare.net/heiko.seeberger/jax-09-osgi-service-components-models