Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Eclipse4/RCP/Dependency Injection
With 10 years of experience with the Eclipse platform, a number of problems have surfaced.
- Code frequently uses global singleton accessors (e.g., Platform, PlatformUI) or required navigating a deep chain of dependencies (e.g., obtaining an IStatusLineManager). Singleton services is particularly problematic for app servers like RAP/Riena.
- This tightly couples consumers of "things" to their producer/provider, inhibits reuse, etc
- Mechanisms are not very dynamic — plugins react to context changes drastically rather than incrementally (just close the affected controls)
-
IEvaluationContext has global state that gets swapped according to context change (such as the focus control) -
Current solutions are not multi-threadable - they assume evaluation occurs in the UI thread - Scaling granularity
- Current solutions don't scale down to services with brief lifetimes
- Current solutions may not scale up to very large numbers of services
- Currently don't track service consumers to notify when services come/go
- Client code needs to know the internals of the Eclipse code base
- No support for services lookup that are composed out of other services on the fly
Dependency Injection (DI) is one approach to circumvent these problems: rather than require client code to know how to access a service, the client instead describes the service required, and the platform is responsible for configuring the object with an appropriate service.
- DI is not new. Pointers to other projects and books (e.g., Dhanji Prasanna's Dependency Injection)
- Different approaches: separate configuration, or annotating POJOs with injection points.
The Eclipse 4 Application Platform provides a JSR 330-compatible dependency injection (DI) framework, similar to Spring or Guice. Instead of PlatformUI.getWorkbench().getHelpSystem(), E4AP plugins can have the HelpSystem directly injected into an object.
Using the E4AP DI Framework
- E4AP's injector uses annotations
- JSR 330 annotations: @Inject, @PostConstruct, @PreDestroy, @Named
- E4AP-specific annotations: @Preference, @Event, @UIEvent
- Order of injection classes: Constructor, @Injected variables, @Injected methods, @PostConstruct
- no guarantees of ordering within injection classes; methods requiring values from injected variables should either be called from @PostConstruct or be injected with both variables
- List of available services
- E4AP services
- OSGi services
- plugins: org.eclipse.e4.core.di, org.eclipse.e4.core.di.extensions, and org.eclipse.e4.ui.di
- Accessing the IEclipseContext
- Adding, setting, or modifying variables
- Why is modify different from set
- Adding, setting, or modifying variables
Advantages / Disadvantages
DI provides a number of advantages:
- Clients are able to write POJOs and list the services they need. The DI framework provides
- Useful for testing: the assumptions are placed in the DI container rather than in the client code
DI has some disadvantages too:
- Concerns about discoverability of services - cannot use code completion to find out what is available.