Andres Olarte Andres Olarte - 16 days ago 5
Java Question

Using @Inject with OSGi Services with Eclipse4 Dependency Injection

I have 3 plugins


  • de.vogella.osgi.quote
    (Defines the interface IQuoteService)

  • de.vogella.osgi.ds.quoteservice
    (Defines the implementation
    QuoteService)

  • test
    (My actual application)



I'm registering
QuoteService
as an OSGi Service using a Service-Component entry in the manifest, basically following the instructions here.

I'm trying to get this service to be injected in my application, using this code:

package test;

import javax.inject.Inject;

import org.eclipse.e4.core.di.InjectorFactory;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

import de.vogella.osgi.quote.IQuoteService;


public class Activator extends AbstractUIPlugin {
@Inject
IQuoteService quoteService;

public static final String PLUGIN_ID = "test"; //$NON-NLS-1$

private static Activator plugin;


public Activator() {
}

public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
InjectorFactory.getDefault().inject(this, null);
System.out.println(quoteService.getQuote());
}

public void stop(BundleContext context) throws Exception {
plugin = null;
super.stop(context);
}

}


When I run this I get this exception:

Caused by: org.eclipse.e4.core.di.InjectionException: Unable to process "Activator.quoteService": no actual value was found for the argument "IQuoteService".
at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:412)
at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:403)
at org.eclipse.e4.core.internal.di.InjectorImpl.inject(InjectorImpl.java:108)
at org.eclipse.e4.core.internal.di.InjectorImpl.inject(InjectorImpl.java:84)
at test.Activator.start(Activator.java:45)


I know that my service is registered, because I can access it with this code:

public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;

ServiceReference serviceReference = context.
getServiceReference(IQuoteService.class.getName());
quoteService = (IQuoteService) context.
getService(serviceReference);

//InjectorFactory.getDefault().inject(this, null);
System.out.println(quoteService.getQuote());
}


Is what I'm trying to do possible? According to some source such as this, it should be possible.

Answer

You are not supplying an IEclipseContext to the injection code so it has no way to resolve the service (there is no fallback if you do not supply a context).

In an Activator you can access the OSGi service context with:

IEclipseContext serviceContext = EclipseContextFactory.getServiceContext(bundleContext);

Use ContextInjectionFactory rather than InjectorFactory:

ContextInjectionFactory.inject(this, serviceContext);