Version 5.6
Copyright © 2009 - 2011 Lars Vogel
03.11.2011
| Revision History | ||
|---|---|---|
| Revision 0.1 | 14.02.2009 | Lars Vogel |
| created | ||
| Revision 0.2 - 5.6 | 16.02.2009 - 03.11.2011 | Lars Vogel |
| bug fixes and enhancements | ||
Eclipse e4
This tutorial gives an overview about the Eclipse 4 application platform.
This tutorial describes the creation of Eclipse 4 based applications, e.g. Eclipse RCP applications. It describes the modeled application concept and the new programming model which is based on annotations and dependency injection.
Table of Contents
Eclipse 4 introduces a new set of technologies which make the process of Eclipse plug-in development faster and more efficient. The next release of Eclipse 4 will be the Eclipse 4.2 release in June 2012. The Eclipse 3.x series will be stopped after the Eclipse 3.8 release. Eclipse 3.8 will be the last 3.x release and will be released parallel to Eclipse 4.2.
Eclipse 4 has the target to solve some of the problems Eclipse 3.x had. The major enhancements in Eclipse 4.x compared to Eclipse 3.x are:
The Eclipse application is available as a dynamic model at development and runtime.
Eclipse 4 supports dependency injection.
Eclipse widgets can be styled via external CSS files, similar to webpages.
The application model is decoupled from its presentation, e.g. different user interface toolkits, e.g. SWT or JavaFX, can be used to render the model.
Eclipse 4 provides a compatibility layer which allows that Eclipse 3.x plug-ins work unmodified on the new runtime.
The user of the Eclipse IDE, e.g a web developer or a Swing developer, will only indirectly benefit from Eclipse 4 because tool development of Eclipse becomes easier. Therefore the tooling of Eclipse 4 will become better over time.
"Eclipse e4" is the name of the project which created the Eclipse 4 product. Originally the term "e4" was used for the project as well as for the product. Today it is only the name of the project.
The Eclipse e4 project included also several evaluations which have not been ported to the core Eclipse framework. All functionality described in this description is part of the Eclipse 4 release except the "Eclipse e4 tooling".
The subproject "Eclipse e4 tooling" provides tools to develop Eclipse 4 applications. These tools are very useful for developing Eclipse 4 based applications.
Projects like XWT, TM or OpenSocial Gadgets which are also part of the Eclipse e4 project are not included in the Eclipse 4 platform and not described in this document.
On top of OSGi the Eclipse framework provides also extension-points. Extension-points define interfaces for other plug-ins to contribute functionality (code and non-code ).
They are defined in the "plugin.xml" file, which must be in the root directory of your plug-in project. This file is an XML file which provides a user interface for editing this file.
Existing extensions (contributions) are collected during the start of an Eclipse application. The information in the extension points is converted into so-called descriptors and stored in registries.
The Eclipse IDE provides an editors for the "plugin.xml" file (via the so called Plug-in Development Environment).
In Eclipse 4 the usage of extension points is very limited. They are mostly used to define the settings for the application and to find components which contribute to the application model.
The
org.eclipse.core.runtime.products
extension point
is used to define the Eclipse application.
org.eclipse.e4.workbench.model
is used to define contributions to the Eclipse application model.
The Eclipse e4 projects creates regulary a Milestone build of Eclipse 4.2. Weekly (usually Tuesday night) an integration build is triggered.
The following assumes that you have Java installed in at least version 1.6.
Download the latest M-Build (4.2Mx) of Eclipse 4.2 from Eclipse Download Site for your platform. The download is a zip file.
Unzip the zip file onto your local directly. Do not use a path with spaces; this might lead to problems in the usage of Eclipse.
Double-click the Eclipse.exe (or the launcher icon specific to your platform) to start Eclipse.
Select an empty directory as the workspace. The workspace will contain all your project files and to avoid any collision with existing work we want to use a new one.
The Eclipse SDK download does not include the Eclipse e4 tooling, which makes working with Eclipse e4 easier. These tools provides wizards to create Eclipse 4 artifacts and the specialized model editor for the application model.
Please use the included e4 update site to install the e4 tooling via the Eclipse update manager.
Sometimes the included e4 tooling update site does not work, in this case use the following update site:
http://download.eclipse.org/e4/updates/0.12-I-builds/
If your Eclipse download reports incompatible versions and refuses to install the tooling you should try to download a newer version of Eclipse. In this case try the latest Integration Build.
The latest Integration Build of Eclipse 4.2 can also be found on the Eclipse Download Site under the "Stream Integration Builds" label.
Currently the Application Programming Interface (API) for Eclipse 4 is still marked as provisional, i.e. this means that the API might be changed in the future.
As Eclipse 4.2 now is able to run the Eclipse IDE, it is unlikely in the opinion of the author of this text, that dramatic changes will occur in the future.
Therefore it is relatively save to start using the API. But you must be prepared that you might do adjustments to your application.
Per default Eclipse will create warnings in your coding if you use provisional API. You can turn of these warnings via → → → → and setting the "Discouraged Access" to ignore.

The Eclipse 4 tooling provides a project generation wizard. This wizard allows you to create an Eclipse 4 based RCP application.
Select → → → → .
Create the
project
de.vogella.e4.rcp.wizard
using the default settings. This should be similar to the following
screenshots.



This wizard created all necessary files to start your application. The central file for starting your application is the .product file, created in your project folder.
Eclipse 4 based applications are standard Eclipse plug-ins with some additional file and configuration switches.
To convert an Eclipse plug-in into an Eclipse 4 RCP application you have to:
Create a product configuration which uses the predefined
E4Application
application for the
org.eclipse.e4.ui.workbench.swt.
package.
Maintain the dependencies regarding the necessary Eclipse 4 plug-ins.
Create a file which describes the Application model. This file is
typically called
Application.e4xmi.
In the
plugin.xml
file the application points to
the Application model
description
file, via the property
applicationXMI. The path to the file follows the "plug-in id"/filename" pattern,
e.g. "com.example.e4.rcp/Application.e4xmi"."
Eclipse 4 applications require certain components of the
Eclipse
platform
to
run. The following plug-ins must be listed as dependency in
the
MANIFEST.MF
file.
org.eclipse.core.runtime
org.eclipse.e4.ui.workbench
org.eclipse.e4.ui.workbench.swt
org.eclipse.e4.ui.workbench.renderers.swt
org.eclipse.e4.ui.css.swt.theme
org.eclipse.e4.core.services
org.eclipse.e4.core.di
org.eclipse.e4.core.contexts
org.eclipse.e4.ui.services
javax.inject
javax.annotation
org.eclipse.equinox.ds
org.eclipse.equinox.event
org.eclipse.swt
Most Eclipse 4 applications use the SWT toolkit, therefore the SWT plug-in is also included in the list.
If you enter all dependencies the resulting
MANIFEST.MF
should look similar to the following, except that your version might
also include version numbers.
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Todo Bundle-SymbolicName: de.vogella.e4.todo Bundle-Version: 1.0.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Require-Bundle: org.eclipse.core.runtime, org.eclipse.e4.ui.workbench, org.eclipse.e4.ui.workbench.swt, org.eclipse.e4.ui.workbench.renderers.swt, org.eclipse.e4.ui.css.swt.theme, org.eclipse.e4.core.services, org.eclipse.e4.ui.services, javax.inject, javax.annotation, org.eclipse.equinox.ds, org.eclipse.equinox.event, org.eclipse.swt, org.eclipse.e4.core.di, org.eclipse.e4.core.contexts
The visual part of an Eclipse application consists of Perspectives, Parts (Views, Editors), Menus etc. An Eclipse application also includes non-visual components, e.g. Handlers, Commands and Keybindings.
A Perspective is a visual container. Parts are the separate Windows within your application. Parts can be placed on top of each other if they are contained in a Stack. A SashContainer (Sash) allows to divide two elements either horizontally or vertically.
Eclipse 4 uses a model to describe an application. This application model contains the visual parts as well as some non-visual parts. Each model element has attributes which describe its current state, e.g. the size and the position for a Window. Model elements might be in a hierarchical order, for example Parts might be grouped below a Perspective.
The application model defines the structure of the application; it does not describe the content of the individual user interface components.
For example the application model describes which Parts are
available.
But it does not describe the content of the
Part, e.g. the SWT
Labels,
Buttons
etc. The content of the
Parts
is still defined via coding.
If the application model would be a house, it would describe the available rooms (Parts) and their arrangement (Perspectives, Stacks, Sashes) but not the furniture of the rooms. This is illustrated by the following image.

The workbench model is extensible. The basis of this
model is
typically defined
as a
static file. This
file is
typically called
Application.e4xmi
; we assume this name for this tutorial.
The Eclipse application uses the
org.eclipse.core.runtime.products
extension point to specify the model file via the
applicationXMI
parameter.
The XMI file is read at start time of the application and the initial application model is constructed from this file.
Application model elements can contain references to Java classes via an URI.
The URI describes the location of the Java class The first part of this URI is the plug-in, the second one the package and the last one the class.
For example a model description for a part (View or Editor) contains attributes as for example label, tooltips, icon URI's, etc. It also contains a class URI which points to a Java class for this element. If the model elements get activated this class will get instantiated.
The following will call the objects created based on the application model "model objects".
URI's follow two patterns. One for identifying resources and another one for identifying classes.
Table 1. URI patter
| Pattern | Description |
|---|---|
| bundleclass://Bundle-SymbolicName/package.classname | Used to identify Java classes. It consists of the following parts: "bundleclass://" is a fixed schema, Bundle-SymbolicName as defined in the MANIFEST.MF file, package for the package of the Java class and classname is the name of the Java class. For example: bundleclass://com.example.e4.playground3/com.example.e4.playground3.parts.MySavePart |
| platform:/plugin/Bundle-SymbolicName/path/filename.extension | Identifier for a resource in the plug-in. "platform:/plugin/" is a fixed schema, followed by the Bundle-SymbolicName of the MANIFEST>MF file, followed by the path to the file and the filename, Example: platform:/plugin/com.exmaple.e4.playground3/icons/save_edit.gif |
The Eclipse tooling project provides a specialized model editor which makes it easier to work on an application model.
To open
the
model
editor double-click on your
Application.e4xmi
file (or
right click on
it
and
select
→ .

Eclipse 4 tries to keep the core framework as minimal as possible. Additional functionality to the model is provided by Add-ons to the model. These add-ons can be registered to the model and can enhance the application.
Currently the following Add-ons are useful for Eclipse applications. Their class names give a relative good indication of their provided functionality, check their Javadoc to get a short description of their purpose.
Table 2. Model Add-ons
| Add-on ID | Class |
|---|---|
| org.eclipse.e4.core.commands.service | CommandServiceAddon |
| org.eclipse.e4.ui.contexts.service | ContextServiceAddon |
| org.eclipse.e4.ui.bindings.service | BindingServiceAddon |
| org.eclipse.e4.ui.workbench.commands.model | CommandProcessingAddon |
| org.eclipse.e4.ui.workbench.contexts.model | ContextProcessingAddon |
| org.eclipse.e4.ui.workbench.bindings.model | BindingProcessingAddon |
Use the
bundleclass://
URI convention to add Add-ons to your application model.
Having these Add-ons registered allows to enhance or replace them by the Eclipse platform team or by a customer specific implementation in case the need arises.
Additional Add-ons are available, e.g. to support drag and drop of
Parts
in your application.
To support drag-and-drop for
Parts
add the
DnDAddon
class
and the
CleanupAddon
class
from the
org.eclipse.e4.ui.workbench.addons.swt
bundle as
Add-ons
to your
“Application.e4xmi”.
Add the
org.eclipse.e4.ui.workbench.addons.swt
plug-in to your product to use these two plugins.
The application model is also available at runtime. The application can access the model and change it via a defined API. We will later have a look at this API.
Add the
org.eclipse.e4.tools.emf.liveeditor
plug-in and its dependencies to your launch configuration to add the
model editor to your application.
Afterwards you can open the model editor for your running application via the ALT+Shift+F9 shortcut. This also works for the Eclipse 4 IDE.
Using the model editor you can change your application model directly at runtime. Most changes are directly applied, e.g. if you change the orientation of a perspective your user interface will update itself automatically.
You can also select the part element, right click on it and select "Show Control" to get it highlighted.
During startup the Eclipse runtime creates the application model and instantiates the referred classes in the model if required.
The life cycle of every model object is therefore controlled by the Eclipse runtime. The Eclipse runtime instantiates and destroys the model objects.
This is important for the programming model of Eclipse 4, as it supports the usage of dependency injection for the model objects.
In the following tutorial we will create a standard Eclipse Plug-in called "com.example.e4.rcp.todo".
In Eclipse select →

Give your plug-in the name "com.example.e4.rcp.todo".

Press "Next" and make the following settings. Select "No" at the question "Would you like to create a rich client application" and "This plug-in will make contributions to the UI"". Unflag the "Generated an activator, a Java class that controls the plug-ins life-cycle." option.

Press the "Finish" button; we will not use a template.
In the following we add the additional configuration so that your Eclipse plug-in can be used as Eclipse 4 application.
Add the required plug-ins as dependency to your plug-in configuration file. For this open the "MANIFEST.MF" file in the "META-INF" folder and select the tab "Dependencies".
The following shows a screenshot of the dependency tab.

The individual plug-ins are the following:
org.eclipse.core.runtime
org.eclipse.e4.ui.workbench
org.eclipse.e4.ui.workbench.swt
org.eclipse.e4.ui.workbench.renderers.swt
org.eclipse.e4.ui.css.swt.theme
org.eclipse.e4.core.services
org.eclipse.e4.core.di
org.eclipse.e4.core.contexts
org.eclipse.e4.ui.services
javax.inject
javax.annotation
org.eclipse.equinox.ds
org.eclipse.equinox.event
org.eclipse.swt
Create the "todo.product" product definition file which uses the E4Application. Right click on your project and select →


To define that your product uses the
E4Application
application, press the "New" button on the "Overview" tab of the
product
editor. Enter "To-do" as the name, "product" as ID. The
defining
plug-in is your plug-in and we must use the E4Application.

Create the "Application.e4xmi" application model file directly in your plug-in directory. Select → → → → → .

This will create the "Application.e4xmi" file and open this file an the application model editor.
Add one
Window
to your application model to have a visual component.
Select the "Windows" node
and press the "+" Button (which will be
called the "Add" Button in this description)
for
a
TrimmedWindow.

Enter a default height and width and a label as in the following screenshot.

You will now connect the application model with your product configuration. You may have to close and re-open the editor for the "plugin.xml" file to see the existing contribution to the extension point. See Bug report for incorrect initial display of plugin.xml for details on this problem.
Open the
"plugin.xml"
file, select the "Extensions" tab and open the
org.eclipse.core.runtime.products
contribution.
Right click on the "product" entry and select → . Use "applicationXMI" as name and "com.example.e4.rcp.todo/Application.e4xmi" as value. This value consists out of your plug-in name and the file name of your application model file.

Open your product configuration file and switch to the tab "Dependencies". Press the "Add" button and add your own "com.example.e4.rcp.todo" plug-in as dependency. Afterwards press "Add Required Plug-ins".
This should add all dependencies you defined in the "MANIFEST.MF" file to your product configuration file.
In your project you will use functionality provided by model Add-ons. Fortunately the wizard for creating the "Application.e4xmi" file added these Add-ons already. For completeness here is a list of the registered Add-ons.
Table 3. Model Add-ons
| Add-on ID | Class |
|---|---|
| org.eclipse.e4.core.commands.service | CommandServiceAddon |
| org.eclipse.e4.ui.contexts.service | ContextServiceAddon |
| org.eclipse.e4.ui.bindings.service | BindingServiceAddon |
| org.eclipse.e4.ui.workbench.commands.model | CommandProcessingAddon |
| org.eclipse.e4.ui.workbench.contexts.model | ContextProcessingAddon |
| org.eclipse.e4.ui.workbench.bindings.model | BindingProcessingAddon |
In the following you will extend the minimal Eclipse 4 application. After this change, your user interface should look like the following:

You will add Perspective to the Window. This Perspective will contain a SashPartContainer, which will contain two Stacks. Each stack will get one Part assigned to it.
Open the "Application.e4xmi" file. Go to your Window
and
select
the
"Controls" node. Add a
PerspectiveStack. Press the "Add" Button to create
a
"Label" entry. Enter the value
"To-Do" in the field
label and the value
"com.example.e4.rcp.todo.simple" in the field ID.

Select "Controls" below the newly created Label and add a "PartSashContainer". Change its "Orientation" attribute to "Horizontal".

In the drop-down list of the "PartSashContainer" select "PartStack" and press the "Add" button to add a stack. Re-select the "PartSashContainer" and add another "PartStack".

Add a "Part" to each Stack. The Part in the first "PartStack" should get the "com.example.e4.rcp.parts.todooverview" ID and the "To-Dos" label. The second part should get the "com.example.e4.rcp.parts.tododetail" ID and the "Details" label.

Start your product and validate that the user interface looks as planned.
Please note that so far, you have not created a Java class for our application.
In the following you will create two Java objects (model objects) and connect them to the application model.
Create the
com.example.e4.rcp.todo.parts
package.
Create two Java classes called "TodoOverviewPart"
and
"TodoDetailsPart" in this package. These classes do not
extend another
class, nor do they implement any
Interface, i.e. they are "plain old Java objects" (POJO's).
Connect the
TodoOverviewPart
class with the model element for the
Part
with the
com.example.e4.rcp.parts.todooverview
ID. You can do this via the "Class URI" property
of the
Part
model element.
Connect the
TodoDetailsPart
class with the
Part
with the
com.example.e4.rcp.parts.tododetail
ID.
Run your application. It should start, but you should see no difference in your user interface.
To validate that the model objects are create a no-argument
constructor, e.g. with no parameters, for
one of
the
classes and add a
System.out.println()
statement. Afterwards verify that the constructor is called, once you
start your
application.
The general concept between dependency injection is called Inversion of Control. A class should not configure itself but should be configured from outside.
Dependency injection is a concept which is not limited to Java. But we will look at dependency injection from a Java point of view.
A Java class has a dependency to another class if it uses this class as a variable. For example a class which accesses a logger service has a dependency to this service.
Ideally Java classes should be as independent as possible from other Java classes. This increases the possibility to reuse these classes and to test them independently from other classes, for example for unit testing.
If the Java class directly creates an instance of another class via
the
new()
operator, it cannot be used and tested independently from this class.
To decouple Java classes its dependencies should be fulfilled from the outside. A Java class would simply define its requirements like in the following example:
public class MyPart { @Inject private Logger logger; // DatabaseAccessClass would talk to the DB @Inject private DatabaseAccessClass dao; @Inject public void init(Composite parent) { logger.info("UI will start to build"); Label label = new Label(parent, SWT.NONE); label.setText("Eclipse 4"); Text text = new Text(parent, SWT.NONE); text.setText(dao.getNumber()); } }
Another class could read these dependencies and create an instance of the class, injecting objects into the defined dependency. This can be done via the Java reflection functionality. This class is usually called the dependency container.
This way the Java class has no hard dependencies. For example if you want to test a class which uses another object which directly uses a database, you could inject a mock object.
Mock objects are objects which act as if they are the real object but only simulate their behavior. They mock to be these objects, therefore the name.
If dependency injection is used, a Java class can be tested in isolation, which is good.
Dependency injection can happen on:
the constructor of the class (construction injection), defines a hard dependency
a setter (setter injection), defines a soft dependency
a field (field injection), defines a soft dependency
Eclipse 4 supports field, constructor and method injection.
It uses
the standard Java
@Inject
and
@Named
annotations, which were defined in the Java Specification Request 303
(JSR303). In addition to these standard annotations, it declares the
@Optional
and
@Preference
annotations
The following table gives an overview of the dependency injection (DI) annotations.
Table 4. Annotations for Dependency Injection
| Annotation | Description |
|---|---|
| @javax.inject.Inject | Marks a field, a constructor or a method. The Eclipse framework tries to inject the parameter. |
| @javax.inject.Named |
Defines the name of the key for the value which should be
injected. By
default the fully qualified class
name is used as
key. Several
default values are defined as constants in the
IServiceConstants
interface.
|
| @org.eclipse.e4.core.di.annotations.Optional | Marks an injected value to be optional, so if it can’t be found no error is thrown. This also ensures that the value is unset if the injected value is set to null. |
| @org.eclipse.e4.core.di.extensions.Preference | Eclipse can store key/values as so-called preferences. The @Preference annotation defines that the annotated value should be filled from the preference store. Eclipse can store key/values as so-called preferences. |
Eclipse allows to use DI for objects, OSGi services and Preferences. We will later learn where Eclipse searches for things to inject.
We learned that the Eclipse 4 runtime instantiates the Java classes referred by the model once this is required. During this instantiation the Eclipse runtime scans every object for annotations.
Based on the DI annotations the Eclipse framework performs the injection. Field and constructor injections are performed immediately once the class is instantiated.
Methods which are annotated with DI annotation will get there values injected once these methods are executed by the Eclipse framework.
Constructors are called before the fields are injected. Accessing a injected field in the constructor will result in an error.
The Eclipse framework also tracks the injected values and if they change, it will re-inject the new values. For example you can define that you want to get the current selection injected. If the selection changes, Eclipse will inject the new value.
In the following tutorial we extend our classes to use dependency injection.
Change the
TodoOverviewPart
class
to the following:
package com.example.e4.rcp.todo.parts; import javax.inject.Inject; import org.eclipse.swt.widgets.Composite; public class TodoOverviewPart { @Inject public TodoOverviewPart(Composite parent) { if (parent != null) { // Print the layout to the console System.out.println("Got Composite via DI."); System.out.println("Composite has even a Layout: " + parent.getLayout().getClass()); } else { System.out.println("No Composite available."); } } }
Each framework defines an application programming interface (API).
If you use a framework you need to have a convention which methods are called at which point of the execution of your program. For example if a Java class is responsible for handling a toolbar button click, the framework needs to know which method of this class it should call.
The "traditional" way of defining an API is via inheritance. This approach requires that your classes extend or implement framework classes and interfaces. This is how Eclipse 3.x defined its API.
The framework defines for example via an abstract class which methods
must be implemented.
In the
above
example the method might be called
execute()
and the framework knows that this method must be called once the
toolbar button is clicked.
For example in Eclipse 3.x a
View
would extend the abstract
ViewPart
class. This class defines the
createPartControl()
method.
The Eclipse 3.x framework knows that
createPartControl()
is responsible for creating the user interface and calls this method
once the
View
becomes visible.
API definition via inheritance is a simple way to define an API, but it also couples the classes tightly to the framework. For example testing the class without the framework is difficult.
Eclipse 4 does not require that classes extend framework classes. Eclipse 4 uses annotations to indicate that a certain behavior is expected from the framework.
I like to call these annotations "behavior annotations".
Behavior annotations are used to indicate that certain methods should be called at certain events. The following tables list the available behavior annotations.
Table 5. Eclipse behavior annotations
| Annotation | Description |
|---|---|
| @PostConstruct | Eclipse calls this method once the class is constructed and the field injection has been performed. |
| @PreDestroy | Eclipse calls this method before the class is destroyed. Can be used to clean up resources. |
| @Execute | Marks a method in a command to be executed |
| @CanExecute | Marks a method to be visited by the Command- Framework to check if a command is enabled |
| @Focus | Indicates that this method should be called, once the Part gets the focus. |
| @Persist | annotates method. If used in a Part-POJO this method will be called when the workbench issues a save-request. |
All these annotations will also trigger dependency injections.
Therefore you do not need to add the
@Inject
annotation, if you use these annotations.
The
org.eclipse.e4.core.di.annotations
package contains the
@PostConstruct, @PreDestroy, @Execute,
@CanExecute annotations.
@Persists and @Focus are part of the
org.eclipse.e4.ui.di
package.
Eclipse 4 provides the possibility to register a class to events of the lifecycle of the application model. For example you can use these lifecycle hooks to create a login screen.
The
org.eclipse.core.runtime.product
extension point allows to define this lifecycle class
class with a
property with the
lifeCycleURI
key.
This property points to a class via the
bundleclass://
schema.
In the lifecycle class you can use the following annotations. The annotated methods will be called by the framework depending on the life cycle of your application.
Table 6. Life Cycle Annotations
| Annotation | Description |
|---|---|
| @PostContextCreate | Is called after the IEclipseContext is created, can be used to add objects to the context. |
| @ProcessAdditions | Is called directly before the model is passed to the renderer, can be used to add additional elements to the model. |
| @ProcessRemovals | Same as @ProcessAdditions but for removals. |
| @Presave | Is called before the application model is saved. You can modify the model before it is persisted. |
In the following tutorial we use the @PostConstruct and @PreDestroy annotations.
Add the following method to your
TodoOverviewPart
and
TodoDetailsPart
class.
public void createControls(Composite parent) { }
Annotate the method with @PostContruct.
Create an empty
public void dispose()
method and annotate it with @PreDestroy.
Remove all constructors from your classes.
The Eclipse application model can also contain commands, handlers and keybinding.
A command in Eclipse is a declarative description of a component and is independent from the implementation details.
The behavior of a command is defined via a handler. A handler defines
a
class via the
contributionURI
attribute of the handler. This attribute is displayed as
"Class URI"
in the model editor.
This class uses the
@Execute
annotation to define which method is called once the handler
is
executed. The
@CanExecute
annotation defines the method which evaluates if the handler
is
currently active.
@CanExecute is called by the framework if the
SWT.SHOW
event happens. This event is for example triggered if a new Part is
displayed.
Also if you add items to the toolbar, a timer automatically registered by the Eclipse framework will, as of the time of this writing, execute every 400 Milliseconds. This timer will check the @CanExecute to enable or disable the related toolbar entry.
You can add menus and toolbars to the application model for the Window and for Parts. Menu and toolbars items contain references to commands. If a command is select the runtime will determine the relevant handlers for the command.
For simple cases you can also use the "Direct MenuItem" or a "Direct ToolItem", which allows to define a handler class directly.
A trimbars can be defined for Windows. Here you can decide if they should be placed on the top, left, right or bottom.
The related command is assigned to the menu and toolbar entry. Menus support separators and submenus.
To show a menu for a
View
you have to add a tag to the corresponding entry in the
"Application.e4xmi" file. This tag must be defined before the menu
children are defined and looks like the following.
<tags>ViewMenu</tags>
Unfortunately this tag is currently not added by the model editor and you have to add this manually. Here is an example for such an entry.
<menus xmi:id="_97aYcEzrEeGWA5PIedy0eQ" elementId="viewmenutest" label="viewmenutest Label"> <tags>ViewMenu</tags> <children xsi:type="menu:HandledMenuItem" xmi:id="_JuWbAEzsEeGWA5PIedy0eQ" elementId="handledViewMenu" label="Test" tooltip="kk" command="_rR8PMEq3EeGHfpgriXYg9Q"/> </menus>
Each command can have only one valid handler for a given scope. The application model allows to define handler for the application, specific for a Window and for a for an Part.
If more then one handler is defined for a command, Eclipse will select the handler most specific to the model element.
For example if you define a handler for the "Copy" command for your Window and if you define another "Copy" handler for your Part, the runtime will select the handlers closest to model element.
During this evaluation the
@CanExecute
is considered, e.g. if the "Copy" handler for a Part is not active at
a
given point the workbench will call the handler defined on the
Window.
The visibility of menus, toolbars and their entries can be restricted
via the core expressions. You add the corresponding attribute in the
application model to the ID defined by the
org.eclipse.core.expressions.definitions
extension point.
This approach is similar to the definition of core expressions in Eclipse 3.x.
A good convention is to start IDs with the top level package name and to use only lower cases. Handler IDs should use the command ID as a prefix and add the suffix "handler".
For example if you implement a command with the "com.example.contacts.show" you should use "com.example.contacts.show.handler" as ID for the handler. If you have more then one handler defined, add another suffix to it, describing its purpose, e.g. "com.example.contacts.show.handler.details".
If case you implement commonly used functions, e.g. save, copy, you should use the existing platform IDs, as some Eclipse contributions expect these IDs.
Table 7. Default IDs for commonly used commands
| Command | ID |
|---|---|
| Save | org.eclipse.ui.file.save |
| Save All | org.eclipse.ui.file.saveAll |
| Undo | org.eclipse.ui.edit.undo |
| Redo | org.eclipse.ui.edit.redo |
| Cut | org.eclipse.ui.edit.cut |
| Copy | org.eclipse.ui.edit.copy |
| Paste | org.eclipse.ui.edit.paste |
| Delete | org.eclipse.ui.edit.delete |
| Import | org.eclipse.ui.file.import |
| Export | org.eclipse.ui.file.export |
| Select All | org.eclipse.ui.edit.selectAll |
| About | org.eclipse.ui.help.aboutAction |
| Preferences | org.eclipse.ui.window.preferences |
| Exit | org.eclipse.ui.file.exit |
You will now define commands and handlers for your application. Open the "Application.e4xmi" file and select "Commands". We will define our handlers application-wide.

Via "Add" you can create new commands. The name and the ID are the important fields. Create the following commands.
Table 8. Commands
| ID | Name |
|---|---|
| org.eclipse.ui.file.save | Save |
| org.eclipse.ui.file.exit | Exit |
| com.example.e4.rcp.todo.new | New Todo |
| com.example.e4.rcp.todo.remove | Remove Todo |
| com.example.e4.rcp.todo.showmap | Show Map |
Create the
com.example.e4.rcp.todo.handlers
package for your handler classes.
All handler classes will implement the execute() method.
package com.example.e4.rcp.todo.handlers; import org.eclipse.e4.core.di.annotations.CanExecute; import org.eclipse.e4.core.di.annotations.Execute; public class SaveHandler { @Execute public void execute() { } @CanExecute public boolean canExecute() { return true; } }
Using this templates for all classes, implement the following classes.
ExitHandler
NewTodoHandler
RemoveHandler
SaveHandler
ShowMapHandler
Select the entry "Handlers" in your application model and create the following handlers for your command. For the definition of handlers the ID, the command and the class is relevant information.
The application model editor shows both the name and the ID of the command, in the following table we just add .handler to each command ID for its handler. Therefore it should be clear which command the handler should be referring to.
The class URI follows the
bundleclass://
schema, we only define the class name to make the table more
readable.
Table 9. Handlers
| ID | Referred Class |
|---|---|
| org.eclipse.ui.file.save.handler | SaveHandler |
| org.eclipse.ui.file.exit.handler | ExitHandler |
| com.example.e4.rcp.todo.new.handler | NewTodoHandler |
| com.example.e4.rcp.todo.remove.handler | RemoveTodoHandler |
| com.example.e4.rcp.todo.showmap.handler | ShowMapHandler |
You will now add a Menu to your application model.
Select "Application.e4xmi". To add a menu to a Window or TrimmedWindow select the entry in the model and flag the "Main Menu" attribute.

Add two menus, one with the name "File" and the other one with the name "Edit". You only need to enter the "Label" attribute.

Add a "HandledMenuItem" to the ""File" menu. This item should point to the save command.

Add a "Separator" after the save menu item and add after that an entry for the exit command.
Add all other commmands to the "Edit" menu.
Select the node "TrimBars" in your application model and press the add button. The "Side" attribute should be set to "Top" so that all toolbars assigned to that TrimBar appear on the top of the application.
Add a "ToolBar" to your TrimBar. Add
a
"Handled
ToolItem" to
this
ToolBar, which points to the
org.eclipse.ui.file.save
command.
Set the label for this entry to "Save".

To test if your handler is working, change your
ExitHandler
class, so that it will close your application.
package de.vogella.e4.todo.handler; import org.eclipse.e4.core.di.annotations.Execute; import org.eclipse.e4.ui.workbench.IWorkbench; public class ExitHandler { @Execute public void execute(IWorkbench workbench) { workbench.close(); } }
We covered how dependency injection works and which annotations can be used to define the behavior of the Java classes. But we have not yet covered what the scope of injection is, e.g. what you can inject into your model classes.
The Eclipse runtime creates a context in which the possible values for injection can be stored. This context can be modified, e.g. the application and the framework can add elements to the context.
The Eclipse context contains:
all objects associated with the workbench model
all other objects which have explicitly been added to the context
all Preferences - key/value pairs which typically used to configure the application
OSGi services - software components which can be dynamically consumed
All possible values for dependency injection can be accessed via the context.
The context contains Java objects which can be accessed via keys.
Access to the context works similar to accessing a Java
Map
data structure.
Internally the context is not a flat structure like a Java map, it is hierarchical and can also dynamically compute values for requested keys.
A context can be local to an object and can have a parent context.
Each model element has its own context assigned to it. The main context is created by the Eclipse Framework and all context objects of the model elements are hierarchically connected to the main context object.
Model objects that implement the
MContext
interface have their own local context. This is for example the case
for
MWindow
and
MPart. Each context for a model element contains a reference to the
Model
object
itself.
If for example a part requests object by a certain key from the context, Eclipse will first search for this object in the local context of the part. If it does not find the key in the local context it will search the parent context. This process continues until the main context has been reached. At this point the framework would check for fitting OSGi services in the OSGi registry.
This happens transparently for the caller of the context and is considered as an implementation detail.
The interface for the context object is the
IEclipseContext
interface.
The
OSGiContextStrategy
class is responsible for searching for OSGi service if the Eclipse
framework does not find the requested key in the hierarchy of
IEclipseContext
objects.
Eclipse 4 has a flexible renderer framework. For each model element the framework determines a renderer class which is responsible for creating the Java object associated with the model element. This renderer class creates, if required, the local context for the model element and connects this local context to the context hierarchy.
For example the
ContributedPartRenderer
class is responsible for creating the Java objects for
Parts
in the model. The interface for
Parts
is
MPart.
ContributedPartRenderer
creates a
Composite
for every
Part
and injects this
Composite
into the local context of the
Part.
We have learned about the model workbench and dependency injection. As the model is interactive you can change it at runtime, for example you can change the size of the current window, add Parts to your application or remove menu entries.
But what is the best way to access these models?
Model elements have Java classes associated with them. We will later learn how we can access these elements via dependency injection. As the model is interactive you can use these model elements to change its attributes or children.
The following is a table of important model elements based on their Java classes.
Table 10. Eclipse 4 model element
| Model element | Description |
|---|---|
| MApplication | Describes the application object. Can be used for example to add new windows to your application |
| MWindow | Represents a Window in your application. |
| MTrimWindow | Represents a Window in your application. The underlying SWT shell has been created with the SWT.SHELL_TRIM attribute which means, it has a tile, a minimize, maximize and resize button. |
| MPerspective | Object for the perspective model element. |
| MPart | Represents the model element part, e.g. a View or a Editor. |
| MDirtyable | Property of MPart which can be injected. If set to true, this property informs the mode that this Part contains unsaved data (is dirty). In a Handler you can query this property can trigger a save. |
| MPartDescriptor |
MPartDescriptor is a template for new Parts. You define in your
application model a PartDescripter. A new Part based on this
PartDescriptor can be created with the via the EPartService and
its
showPart()
method.
|
To create new model objects you can use the
MBasicFactory.INSTANCE
class. This is a factory to create new model objects via typed
create*()
methods. For example you can create a new Window at runtime via the
following snippet.
// Create a new window and set its size MWindow window = MBasicFactory.INSTANCE.createTrimmedWindow(); window.setWidth(200); window.setHeight(300); // Create a new part and assign it to the window MPart part = MBasicFactory.INSTANCE.createPart(); window.getChildren().add(part); // Add new Window to the application application.getChildren().add(window);
The following snippet demonstrates how to use the
MDirtyable
model property in a part to flag it as a Part which should be saved
by
the corresponding workbench action.
import javax.annotation.PostConstruct; import javax.inject.Inject; import org.eclipse.e4.ui.di.Persist; import org.eclipse.e4.ui.model.application.ui.MDirtyable; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; public class MySavePart { @Inject MDirtyable dirty; @PostConstruct public void createControls(Composite parent) { Button button = new Button(parent, SWT.PUSH); button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { dirty.setDirty(true); } }); } @Persist public void save() { System.out.println("Saving data"); // Save the data // ... // Now set the dirty flag to false dirty.setDirty(false); } }
For example the following ads a new part to the currently active window.
package testing.handlers; import org.eclipse.e4.core.di.annotations.Execute; import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor; import org.eclipse.e4.ui.model.application.ui.basic.MBasicFactory; import org.eclipse.e4.ui.model.application.ui.basic.MPart; import org.eclipse.e4.ui.model.application.ui.basic.MWindow; public class AddPartHandler { @Execute public void execute(MWindow window) { MPart part = MBasicFactory.INSTANCE.createPart(); part.setLabel("New part"); part.setContributionURI("platform:/plugin/testing/testing.MyView"); window.getChildren().add(part); } }
To access an existing context you can use dependency injection, if the relevant object is managed by the Eclipse runtime, i.e. if you are using a model object.
package com.example.e4.rcp.todo.handlers; import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.e4.core.di.annotations.Execute; public class ShowMapHandler { @Execute public void execute(IEclipseContext context) { // Add objects to this local context of this handler // ... } }
package com.example.e4.rcp.todo.handlers; import org.eclipse.e4.core.di.annotations.Execute; import org.eclipse.equinox.app.IApplicationContext; public class ShowMapHandler { @Execute public void execute(IApplicationContext context) { // Add objects to the application context // This way is would be accessible for other // model objects // ... } }
Alternatively if your model object extends
MContext
you can use DI to get the model object injected and use the
getContext()
method to access its context. For example Parts, Windows,
Applications and Perspectives extend MContext.
package com.example.e4.rcp.todo.parts; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.e4.ui.model.application.ui.basic.MPart; import org.eclipse.swt.widgets.Composite; public class TodoDetailsPart { @PostConstruct public void createControls(Composite parent, MPart part) { IEclipseContext context = part.getContext(); } }
If you are outside of a model object, you still can access the global context via the following:
public Object start() { // Get Bundle Information Bundle bundle = FrameworkUtil.getBundle(getClass()); BundleContext bundleContext = bundle.getBundleContext(); IEclipseContext eclipseCtx = EclipseContextFactory.getServiceContext(bundleContext); // Fill Context with information using set(String,Object) // .... // Create instance of class ContextInjectionFactory.make(MyPart.class, eclipseCtx); }
The recommended way to add objects to the context is to use OSGi services. OSGi services are automatically available in the context.
Sometimes it might be more efficient to add objects directly to the
IEclipseContext. For example you want to test your Java objects and want to supply
mock (test) objects to them via dependency injection.
If you want to add new objects to an existing context, it is best
practice
to create a new context and set the existing context as
parent of the
new one via the
setParent()
method.
To create a new context, you can use the
EclipseContextFactory.create()
factory method call. Adding objects to it can be done via
the
set()
method on
IEclipseContext.
@Inject public void addingContext(IEclipseContext context) { // We want to add objects to context // Create instance of class IEclipseContext myContext = EclipseContextFactory.create(); // Putting in some values myContext.set("mykey1", "Hello1"); myContext.set("mykey2", "Hello2"); // Adding a parent relationship myContext.setParent(context); }
Using dependency injection is not limited to the objects created by
the
Eclipse runtime. You can use
@Inject
in a Java class and use the dependency injection framework to create
your class.
// Create instance of class
ContextInjectionFactory.make(MyJavaObject.class, context);
For this you can either use an existing context as described in the last section or a new context.
IEclipse context = EclipseContextFactory.create(); // Add your Java objects to the context context.set(MyDataObject.class.getName(), data); // Add your Java objects to the context context.set(MoreStuff.class.getName(), moreData);
I hope you enjoyed this introduction into the Eclipse 4 framework. Of course there is much more, check out the "Eclipse 4 development" section under my lists of Eclipse Plug-in and Eclipse RCP Tutorials section.
Before posting questions, please see the vogella FAQ. If you have questions or find an error in this article please use the www.vogella.de Google Group. I have created a short list how to create good questions which might also help you.
http://wiki.eclipse.org/E4 Eclipse E4 - Wiki