Search code examples
javaeclipse-rcpe4

E4 cannot auto inject MApplication on class variable


I have a E4 application where I need to inject MApplication to the first created class. The class itself has been made inside the start method in my Activator and called there.

My Class is called FrameworkModule and looks like:

public class FrameworkModule implements ISubscription {

    private static final Logger logger = LoggerFactory.getLogger(FrameworkModule.class);

    private @Inject IEclipseContext context;
    protected @Inject EPartService partService;

    protected @Inject MApplication application;

    protected @Inject EModelService modelService;
...
}

The activator will create the above class and run a method of it. The start method of the activator looks like:

@Override
    public void start(BundleContext bundleContext) throws Exception {
        Activator.context = bundleContext;

        IEclipseContext eContext = EclipseContextFactory.getServiceContext(bundleContext);

        ExecutorService service = Executors.newSingleThreadExecutor();

        service.execute(() -> {
            framework = ContextInjectionFactory.make(FrameworkModule.class, eContext);
            framework.startup();
        });

        service.execute(() -> CacheUtil.getManager());

        service.shutdown();
    }

When the code startup I got following error:

 org.eclipse.e4.core.di.InjectionException: Unable to process "FrameworkModule.application": no actual value was found for the argument "MApplication".
    at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:488)
    at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:479)
    at org.eclipse.e4.core.internal.di.InjectorImpl.internalInject(InjectorImpl.java:128)
    at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:411)
    at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:333)
    at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:202)
    at com.xxx.client.eclipse.Activator.lambda$0(Activator.java:84)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

How can I fix this in my FrameworkModule class? I need all the injected classes there and cannot find a way to get it there.


Solution

  • The service context returned by EclipseContextFactory.getServiceContext only has very limited contents and does not include the MApplication. You cannot create your class like this in the activator.

    Depending on exactly how you want to use the class you could:

    • create the class in an 'Add-on' specified in the application.e4xmi or fragment.e4xmi
    • just let it be created automatically using the @Creatable annotation on the class. You can also use the @Singleton annotation if you want a single instance of the class.
    • create it in the LifeCycle class
    • create it using a ContextFunction