Version 6.8
Copyright © 2009 , 2010 , 2011 , 2012 , 2013 Lars Vogel
08.04.2013
| Revision History | |||
|---|---|---|---|
| Revision 0.1 | 14.02.2009 | Lars Vogel |
created |
| Revision 0.2 - 6.8 | 16.02.2009 - 08.04.2013 | 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 increase the flexibility of Eclipse plug-in development. The simultaneous release of Eclipse named Juno in June 2012 was based on Eclipse 4.2.
Eclipse 3.8 was released in parallel to Eclipse 4.2 but the Eclipse 3.x series will be discontinued after the Eclipse 3.8 release, i.e. there will not be an Eclipse 3.9 release. Eclipse 3.8 receives bug fixes for a year via service releases.
Eclipse 4 was an opportunity to rationalize the best parts of the Eclipse 3.x APIs and to fix pain points of Eclipse 3.x development. Eclipse 3.x changed from 3.0 to 3.8, and tough lessons were learned about the difficulties and flexibility of the APIs.
Eclipse 3.x developers will find that many of the concepts that they know are carried across and found in Eclipse 4.
The major enhancements in Eclipse 4 compared to Eclipse 3.x are the following.
The Eclipse application is described via a defined structure called the application model
This application model can be modified at development and runtime
This application model can be extended
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 such as SWT or JavaFX, can be used to render the model
Eclipse 4 provides a compatibility layer which allows Eclipse 3.x plug-ins to run unmodified.
Eclipse 4 primarily contains enhancements for Eclipse based development. The user of the Eclipse IDE, e.g. a web developer or a Swing developer, will only indirectly benefit because tool development of Eclipse becomes easier. This allows Eclipse developers to create better tools for Eclipse users.
The Eclipse Platform project provides the core frameworks and services upon which all Eclipse based applications are created. It also provides the runtime in which Eclipse components are loaded, integrated, and executed. The primary purpose of the Platform project is to enable other developers to easily build and deliver integrated tools and applications.
Eclipse e4 is the name used for the Eclipse Platform's incubator project. This incubator is used for exploratory projects relating to improving the Eclipse Platform. The new Eclipse 4 platform was originally developed within the incubator and the incubator name became synonymous with the new Eclipse Platform. Today the term e4 is only the name of the project.
The e4 project includes several technology evaluations. Some of these evaluations have been ported back to the core Eclipse framework. All functionality described in this document are part of the official Eclipse 4 release, except the Eclipse e4 tooling project.
The subproject Eclipse e4 tooling provides tools to develop Eclipse 4 applications. They are very useful, but have not been added to the Eclipse core because they are not as mature as the other components.
Projects such as XWT, TM or OpenSocial Gadgets, which are also part of the Eclipse e4 project, are not included in the standard Eclipse 4.2 core platform and are not described in this document.
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.
Eclipse 4.2 already runs the complete Eclipse IDE therefore it is unlikely that dramatic changes will occur in the future.
It is therefore relatively safe to start using the API now, but nevertheless you must be prepared that you might have to make some adjustments to your application.
An Eclipse application consists of individual software components. The Eclipse IDE can be viewed as a special Eclipse application with the focus on supporting software development.
The components of the Eclipse IDE are primarily the following. Please note that the graph should display the concept, the displayed relationship is not 100 % accurate.

OSGi is a specification which describes a modular approach for Java application. Equinox is one implementation of OSGi and is used by the Eclipse platform. The Equinox runtime provides the necessary framework to run a modular Eclipse application.
SWT is the standard user interface component library used by Eclipse. JFace provides some convenient APIs on top of SWT. The workbench provides the framework for the application. The workbench is responsible for displaying all other UI components.
On top of these base components, the Eclipse IDE adds components which are important for an IDE application, for example the Java Development Tools (JDT) or version control support (EGit).
Eclipse 4 has a different programming model then Eclipse 3.x. Eclipse 4 provides the 3.x Compatibility Layer component which maps the 3.x API to the 4.0 API. This allows Eclipse 3.x based components to run unmodified on Eclipse 4.
Eclipse based applications which are not primarily used as software development tools are called Eclipse RCP applications. An Eclipse 4 RCP application typically uses the base components of the Eclipse platform and adds additional application specific components.

The programming model of OSGi (Equinox) allows you to define dynamic software components, i.e. OSGi services, which can also be part of an Eclipse based application.
An Eclipse application consists of several Eclipse components. A software component in Eclipse is called a plug-in. A software component in OSGi is called a bundle. Both terms can be used interchangeably.
This tutorial uses the terms Eclipse based applications, Eclipse application, Eclipse 4 application and Eclipse RCP application interchangeably for referring to an application which is based on the Eclipse 4 framework.
If a certain concept refers to Eclipse 3.x, then it is explicitly stated.
An Eclipse plug-in has the following main configuration files.
MANIFEST.MF - Contains the OSGi configuration information.
plugin.xml - Contains information about Eclipse specific extension mechanisms
An Eclipse plug-in defines its API via the MANIFEST.MF file,
e.g. the
Java packages which can be used by other plug-ins and its
dependencies, e.g. the packages or plug-ins which are required by the
plug-in.
The
plugin.xml
file provides the possibility to define
extension points
and
extensions.
Extension-points
define interfaces for other
plug-ins to contribute functionality.
Extensions
contribute
functionality to these interfaces. Functionality can be
code
and non-code based.
In Eclipse 4 the usage of extension points and extensions is very limited. They are mostly used to define pointers to other Eclipse 4 configuration files.
The description in this tutorial is based on the Eclipse 4.3 release. Download the latest available official Eclipse SDK build from the following URL.
http://download.eclipse.org/eclipse/downloads/

The download is a zip file, which is a compressed archive of multiple files. Most operating systems can extract zip files in their file browser. For example if you are using Windows7 as the operating system, right-click on the file in the explorer and select the Extract all... menu entry. If in doubt about how to unzip, search via Google for How to unzip a file on ... , replacing "..." with your operating system.
Do not extract Eclipse to a directory with a path which contains spaces as this might lead to problems in the usage of Eclipse.
After you extracted the zip file, double-click the
eclipse.exe
(Windows) or the
eclipse
file (Linux)
(or the launcher icon
specific to
your platform) to start
Eclipse.
To avoid any collision with existing work select an empty directory as the workspace for this tutorial.
The Eclipse SDK download does not include the Eclipse e4 tooling, which makes creating Eclipse 4 applications easier. These tools provide wizards to create Eclipse 4 artifacts and the specialized model editor for the application model.
The author of this documentation provide an working and recent version of the e4 tools for the Eclipse 4.3 release under the following URL.
http://download.vogella.com/kepler/e4tools
You can install the tools via → and by entering the URL.
From this update site, install only the E4 CSS Spy and the Eclipse e4 Tools. The other entries are not used in this tutorial and may cause different behavior.

The above update site was created to provide a stable link for the reader of the tutorial. The same code basis is used by Eclipse.org to create an official update site for the Eclipse e4 tooling.
Unfortunately the link for this update site changes from time to time but it can be found on the following website: Eclipse.org e4tools site .
If you click on a Build name you find also the URL for the update site. The following screenshots demonstrate this for a particular build of the e4 tools. Please note that the website might change over time.


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


Select the
development mode
and the creation of
sample content
checkbox on the last page. The
development mode
flag adds the
clearPersistedState
flag to the product configuration file so ensure that changes in your
application structure during development are always visible. Via the
sample content
flag you define if a minimal Eclipse RCP application should be
generated or if some additional components should be added to your
application, e.g. an example
view with some example content.

This wizard creates all the necessary files to start your
application. The
central file for starting your application is the
.product
file, created in your project folder.
A run configuration in Eclipse defines the environment where a generic launch will be executed from within. For example it defines arguments to the Java virtual machine (VM), plug-in (classpath) dependencies etc. Sometimes a run configuration is called launch configuration.
If you start your Eclipse application, using the link in the product file, the run configuration will be automatically created.
You can use the created run configuration directly for starting the application again. Changes in the product configuration file will not be considered.
You can update the run configuration by starting the application from the product definition again.
To see and edit your run configuration select your product configuration file, right-click on it and select → .
On the Main tab in the field location you specify where the Eclipse IDE will create the files necessary to start your Eclipse based application.

The run configuration allows you to add additional parameters for
your
application on the
Arguments
tab. By default the
-consoleLog
parameter is included. This will
write error messages of the running
Eclipse application instance to
the
Eclipse IDE
Console
view.

The following table lists useful launch parameters.
Table 1. Launch parameters
| Parameter | Description |
|---|---|
consoleLog
|
Error messages of the running Eclipse application are written to the Eclipse IDE Console view started this application. |
nl
|
Specifies
the runtime language for
your
application. For example
-nl en
will start your application based on
the
English language. Useful
for testing translations.
|
console
|
Provides access to an OSGi console where you can check the status of your application. |
noExit
|
Keeps the OSGi console open even if the application crashes. |
clearPersistedState
|
Deletes runtime changes of the Eclipse 4 application model. |
Error in the run configurations of Eclipse RCP application are frequently the source of problems.
The most common problem is that some required plug-ins are missing in your product. If you are using features your need to ensure that all plug-ins which are referred to in the MANIFEST.MF file are also included in your features.
Eclipse can check for missing dependencies automatically for you before every start. On the Plug-ins Tab select the Validate plug-ins prior to launching option. This will check if you have all the required plug-ins in your run configuration.
If this check reports that some plug-ins are missing, try clicking the button. Also make sure you add all dependent plug-ins in your product.

Afterwards you should add the missing plug-in to your feature or your product (if the product is not feature based).
The following table lists potential problems and solutions.
Table 2. Run Configuration problems
| Problem | Investigate |
|---|---|
| During start you get error messages such as "One or more bundles are not resolved because the following root constraints are not resolved" or "java.lang.RuntimeException: No application id has been found." |
Check that all required plug-ins are included in your run configuration. Make sure that your product defines dependencies to all required plug-ins or features.
Bundles may also require a
certain version of the Java virtual
machine, e.g. a bundle may
require Java 1.6 and will therefore
not load in a Java 1.5 VM. Check the
|
| Strange behavior but no error message. |
Check if your run configuration includes the
-consoleLog
parameter.
This
option allows you to see errors from Eclipse
based
application
in the
console
view of the Eclipse IDE.
|
| Runtime configuration is frequently missing required plug-ins | Make sure that your product or your feature(s) includes all required dependencies. |
| A change in the product dependencies, e.g. a new plug-in is added but is not included in the run configuration. | A product updates an existing run configuration if you start the product directly from the product definition file. If you select the run configuration directly it will not be updated. |
| Application model changes are not reflected in the Eclipse 4 application. |
Eclipse 4 persists user changes in the application model.
During
development this might lead to situations where model
changes are
not correctly applied to the runtime model, e.g. you
define a new
menu entry and this entry is not display in your
application.
Either set the
Clear
flag on the
Main
tab in your Run configuration or add the
-clearPersistedState
parameter for your product configuration file or Run
configuration.
|
| Services, e.g. key bindings or the selection service, are not working in an Eclipse 4 application. |
Ensure that every
part
correctly implements
@Focus. Eclipse 4.2 requires that one
control get the focus assigned.
Eclipse 4.3 has solved this.
|
| Menu entries are disabled in an Eclipse 4.3 build. | Eclipse 4.3 introduces a new model add-on which you need to register with your application model. If you are using Eclipse 4.3 ensure that your application model has an entry pointing to in the HandlerProcessingAddon class in the package org.eclipse.e4.ui.internal.workbench.addons. The bundle symbolic name is org.eclipse.e4.ui.workbench. |
| Application "org.eclipse.ant.core.antRunner" could not be found in the registry or Application "" could not be found in the registry. |
Ensure that you pressed the
New
button in the product configuration file and selected the
E4Application
as application to start. You can check the current setting in
your
plugin.xml
file on the
Extensions
tab and in the details of the
org.eclipse.core.runtime.products
extension.
|
The visual part of an Eclipse application consists of Perspectives, parts (Views and Editors), Menus, Toolbars, etc. An Eclipse application also includes non-visual components, e.g. Handlers, Commands and Key bindings .
Eclipse 4 uses an abstract description, called the application model, to describe the structure of an application. This application model contains the visual elements as well as some non-visual elements of the Eclipse 4 application.
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. It also describes the parts properties, e.g. if a part is closable, its label, ID, etc.
But it does not describe the content of the part, e.g. the labels, text fields and button it consists of. The content of the part is still defined by your source code.
If the application model was a house, it would describe the available rooms (parts) and their arrangement (Perspectives, PastStacks, PartSashContainer) but not the furniture of the rooms. This is illustrated by the following image.

The application model is extensible. The basis of this
model is
typically defined
as a
static file. The default name for this file
is
Application.e4xmi
and the default location is the main directory of your application
plug-in.
You can change the default name and location via the
org.eclipse.core.runtime.products
extension point. Via the
applicationXMI
parameter you specify the local and name of the model file. See the
appendix for a detailed description of this procedure.
The XMI file is read at application startup and the initial application model is constructed from this file.
Application model elements can contain references to Java classes via an Uniform Resource Identifier (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 contains attributes such as labels, tooltips and icon URIs. It also contains a class URI which points to a Java class for this element. This class provides the behavior of the part ??? using the house/rooms metaphor from earlier, the class is responsible for defining the furnishings and the layout of the room, and how the interactive objects behave.
If the model elements get activated this class will get instantiated.
The objects created based on the application model are called model objects.
URIs follow one of two patterns, one for identifying resources and another one for identifying classes. The following table describes these two patterns. The example assumes that the bundle is called test.
Table 3. URI pattern
| Pattern | Description |
|---|---|
|
bundleclass://Bundle-SymbolicName/ package.classname Example: bundleclass://test/test.parts.MySavePart
|
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,
and the fully qualified
classname.
|
|
platform:/plugin/Bundle-SymbolicName/ path/filename.extension Example: platform:/plugin/test/icons/save_edit.gif |
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.
|
The Eclipse tooling project provides an 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
→ .

The model editor has several preference settings which can be reached via → → . The following screenshot shows the preference page.

The application model is also available at runtime. The application can access the model and change it via a defined API.
Add the
org.eclipse.e4.tools.emf.liveeditor
plug-in and its dependencies to your launch configuration to make the
model editor available in 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 itself.
Opening the live editor in your Eclipse 4 application requires that your application has keybindings configured.
You can change your application model
directly at runtime by
using
the
model editor. Most changes are directly applied, e.g. if you
change
the orientation of a
PartSashContainer
your user interface will
update itself automatically. If you modifying
the Eclipse IDE model you should
be careful as this might put the
running Eclipse IDE into a bad state.
In the live model editor, you can select the part element, right click on it and select Show Control to get the part highlighted.
The possible structure of the application model is defined by a meta-model created with the Eclipse Modeling Framework (EMF). A meta-model describes the structure of a data model, e.g. it defines which properties a Part has.
EMF is a popular general purpose modeling framework and is the basis for lots of Eclipse based projects. EMF allows to generate Java classes from a meta-model.
Eclipse
EMF
uses
an
.ecore
file to define the
meta-model.
The meta-model of the Eclipse 4 applications
is
stored in the
org.eclipse.e4.ui.model.workbench
plug-in inside the
model
folder. The base model definition can be found in
the
UIElements.ecore
file. The Eclipse 4 model classes have been
generated based on this
model.
If you want to investigate this model, you could install the EMF tooling via the Eclipse update manager and import the defining plug-in into your workspace. To import a plug-in from your current Target Platform (default is the Eclipse IDE) into your workspace, use the Plug-ins view, right-click on a plug-in and select → .
The
Application.e4xmi
file, which describes the Eclipse application model, is a persisted
version of an EMF model.
During startup
the
Eclipse
runtime
creates the application model based on
the
Application.e4xmi
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.
The Supplementary tab in the model editor allows to enter additional information about a model element.
All model elements allow to enter
Tags. These
Tags
can be used by the Eclipse platform to select the related model
elements
via the
ModelService. By default Eclipse uses some predefined
Tags
to determine the state of certain model elements. For example the
shellMaximized
and
shellMinimized
tag on a
Window
is used by Eclipse to determine if the
Window
should be maximized or minimized.
The following screenshot shows how to define the maximization of a Window.

Another tag which is used frequently is the
NoAutoCollapse
tag which you can add to a
PartStack
container. With this flag the
PartStack
will not collapse even if you remove all parts from it.

Tags are automatically persisted by the Eclipse runtime between
application restarts and are
represented as
Collection
of Strings.
Check the appendix of this tutorial for more tags.
Model elements allow also to have persisted state. If you retrieve the model element you can get and set this persisted state.
// modelObject is the model object // retrieved via dependency injection (e.g. an MPart) // Get the state by the "yourKey" key String state = modelObject.getPersistedState().get(yourKey); // Store the state modelObject.getPersistedState().put(yourKey, state)
Persisted data for model elements is automatically restored by the Eclipse application between application restarts and allow to store key/values pairs based on Strings.
Model elements have Java classes associated with them. 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. These model elements can also get injected.
Table 4. 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. |
| MTrimmedWindow | 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 Eclipse platform that this Part contains unsaved data (is dirty). In a Handler you can query this property to trigger a save. |
| MPartDescriptor |
MPartDescriptor is a template for new Parts. You define in your
application model a PartDescriptor. A new Part based on this
PartDescriptor can be created via the EPartService and shown
its
showPart()
method.
|
| Snippets |
Snippets can be used to pre-configure model parts which you want
to create via your program. You can use
EcoreUtil.copy
to copy a Snippet and assign it to another model element,
e.g. on
a
MSash
you can add a newly copied
MStack
called copy,
via
getChildren().add(copy). Also the model service has some methods to create and clone a
snippet.
|
Every model element allows you to define an ID. This ID is used by the Eclipse framework to identify this model element. Make sure you always maintain an ID for every model elements and ensure that these IDs are unique.
Therefore make sure that all your model elements have an ID assigned to them.
The following suggest best practice for naming conventions, which are also used in this tutorial.
Table 5. Naming conventions
| Object | Description |
|---|---|
| Project Names | The plug-in project name is the same as the top-level package name. |
| Packages |
For plug-in containing lots of user interface components
use
sub-packages based on the primary purpose
of the components. For
example
the
com.example
package
may have the
com.example.parts
and
com.example.handler
sub-package.
|
| Class names for model elements |
Use the primary purpose of the model element as a suffix in the
class
name. For example a class which represents a Part which
displays
Todo
objects, might be called
TodoOverviewPart.
|
| IDs |
Define clear rules for naming IDs in plugin.xml. IDs should always start with the top-level package. If appropriate use the sub-package of the implementing class also. The remainder of the ID should be descriptive for the purpose of the component. For example: "com.example.parts.todolist". ID should be only lower cases (some Eclipse projects also use camelCase for the last part of the ID).
|
The following description uses feature projects and products, please see Feature projects and Eclipse Products and Deployment for a description of these topics.
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 uncheck This plug-in will make contributions to the UI . Uncheck the Generate an activator, a Java class that controls the plug-ins life-cycle option.

Press the Finish button; we will not use a template.
In this chapter we convert the Eclipse plug-in into an Eclipse 4 application.
Create a new project called com.example.e4.rcp.todo.product of type → .

Right-click on this project and select
→ . Create a
todo.product
product configuration file.


Press the New button on the Overview tab of the product editor.

Enter
to-do
as
the name, the
defining
plug-in is your plug-in and use the name
product
as the ID. Select as
Application
the
E4Application
application class.

Create a new feature project called com.example.e4.rcp.todo.feature.

Include the
com.example.e4.rcp.todo
plug-in into this feature via the
feature.xml
file.

Change your product configuration file to use features. To do this open your product configuration file and select the Feature option on the Overview tab of the product editor.

Select the
Dependencies
tab
and add the
org.eclipse.e4.rcp
and the
com.example.e4.rcp.todo.feature
features
as dependencies via the
button.

Press the
button. This adds the
org.eclipse.emf.common
and
org.eclipse.emf.ecore
features to the
dependencies.
Ensure that after this step you have a total of four features in your product configuration file. If you cannot add feature to your product check that you have changed your product to be based on features.
To avoid dependency problems with different versions of the
org.eclipse.e4.rcp
plug-in,
delete
the version number from your
features. You can do this
via
the
Properties
button on the
Dependencies
tab of the product configuration file editor.


Select
→ → → → →
to open a wizard. Enter your
todo
application plug-in
as the container and the filename
suggested by the
wizard.

This will create the
Application.e4xmi
file and open this file
with the application model editor.
Add one
Window
to your application model so you have a visual component.
Select the
Windows
node
and press the
Button
for
a
TrimmedWindow.

Enter an ID, the position and size of the window and a label as shown in the screenshot below.

Open the product file and select the Overview tab. Press the Launch an Eclipse application hyperlink in the Testing Section.

Validate that your application starts. It should be an empty application, which can be moved and closed.
In the upcoming exercises you will use the functionality from other Eclipse plug-ins. This requires that you define a dependency to these plug-ins in your application. The exact details of applying this modular approach will be covered in a later chapter.
Open your
META-INF/MANIFEST.MF
file and select the
Dependencies
tab.
Use the
Add
button in the
Required Plug-ins
section to
add the following plug-ins as
dependency.
org.eclipse.core.runtime
org.eclipse.swt
org.eclipse.e4.core.di
org.eclipse.e4.ui.workbench
org.eclipse.e4.ui.di
org.eclipse.e4.core.di.extensions
Also add
javax.annotation
and
javax.inject
as package dependencies.

Ensure that generally
javax.annotation
as well as
javax.inject
are both added with minimum version
1.0.0
as package dependencies. Otherwise your application will not
work correctly in later exercises.
Optional exercise
You can also add the pde nature to your project in which you placed the product configuration file, if you want to be able to start your product via a right-click on the product and by selecting → .
For this
purpose
remove
the filter in the
Package Explorer
view
for files starting with . (dot) and modify the
.project
file to the following.
<?xml version="1.0" encoding="UTF-8"?> <projectDescription> <name>com.example.e4.rcp.todo.product</name> <comment></comment> <projects> </projects> <buildSpec> <buildCommand> <name>org.eclipse.pde.ManifestBuilder</name> <arguments> </arguments> </buildCommand> <buildCommand> <name>org.eclipse.pde.SchemaBuilder</name> <arguments> </arguments> </buildCommand> </buildSpec> <natures> <nature>org.eclipse.pde.PluginNature</nature> </natures> </projectDescription>
The Package Explorer view may have a filter set for .*resources. You can modify this filter via the view menu as depicted in the following screenshot.

The following model elements represents the basic elements which you use to create the user interface of your application.
Eclipse applications consist of one or more Windows. Typically an application has only one Window but you are not limited to that, e.g. if you want to support multiple displays for two connected monitors.

Parts are user interface components which allow you to navigate and modify data. Parts are typically divided into views and editors.

The distinction into views and editors is not based on technical differences, but on a different concept of using and arranging these parts.
A view is typically used to work on a set of data, which might be a hierarchical structure. If data is changed via the view, this change is typically directly applied to the underlying data structure. A view sometimes allows us to open an editor for a selected set of data.
An example for a view is the Package Explorer, which allows you to browse the files of Eclipse projects. If you change data in the Package Explorer, e.g. renaming a file, the file name is directly changed on the file system.
Editors are typically used to modify a single data element, e.g. a file or a data object. To apply the changes made in an editor to the data structure, the user has to explicitly save the editor content.
Editors and views can be freely positioned in the user interface.
For example the Java editor is used to modify Java source files. Changes to the source file are applied once the user selects the Save command. A dirty editor is marked with an asterisk.

A Perspective is a visual container for a set of parts. You can switch Perspectives in your Eclipse RCP application via the EPartService service.
parts can be directly assigned to a Window or a Perspective. If you want to group and arrange parts you can use PartStacks and PartSashContainers.
PartStacks contain a stack of parts of which only one is visible at the same time and can be selected via tabs. A PartSashContainer displays all its children at the same time either horizontally or vertically.
The following shows a simple Eclipse application layout using two PartSashContainers and a few PartStacks.

On the top of this layout there is a horizontal PartSashContainer which contains another PartSashContainer and some PartStacks. The hierarchy is depicted in the following graphic.

Eclipse 4 persists certain user changes in your application. During development this might lead to situations where changes are not correctly applied and displayed, e.g. you define a new menu entry and this entry is not displayed in your application.
Either set the
Clear
flag on the
Main
tab in your Run configuration or add the
clearPersistedState
parameter for your product configuration file or Run configuration.
The following screenshot shows this setting in the product configuration file.

It is recommended that you set this during your development
phase
to
avoid unexpected behavior. Please note that parameters must be
specified via the
-
sign, e.g.
-clearPersistedState.
If you don't do this step, changes in the application model after a restart of your application are not visible because Eclipse restores the last state of your application.
This section gives a high level description of the steps you do in this tutorial. In this tutorial you create the modeled user interface of your Eclipse 4 application.
The target is to create the following user interface.

The following description is just a high-level description. Detailed steps are included in the next sections.
This requires that you create several PartSashContainer and PartStacks. Each PartStacks contains currently one part.
While this is not a mandatory model element, you also add a Perspective to your application model so that you can later easily add more Perspectives.
Open the
Application.e4xmi
file. Go to your
To-do
Window
and
select
the
Controls
node. Add a
PerspectiveStack. Press the
Add
button to create
a
Perspective
entry.
Enter the value To-Do in the Label field and the value com.example.e4.rcp.todo.perspective in the Id field.

Select Controls below the newly created Perspective 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.
Re-select the parent PartSashContainer and add another PartSashContainer. Now add two PartStacks to the second PartSashContainer.
After these changes you application model should look similar to the following screenshot.

Add a
Part
to each
PartStack. As ID for the
Parts
use the prefix
com.example.e4.rcp.todo.part
and the suffix from the following table.
Table 6. Label and ID from the Parts
| ID Suffix | Label |
|---|---|
| *.todooverview | To-Dos |
| *.tododetails | Details |
| *.playground | Playground |
The following screenshot shows the data for one part.

Start your product and validate that the user interface looks as planned. Reassign your parts to other PartStacks, if required. The model editor supports drag-and drop for reassignment.
Please note that you have not yet created a Java class for your application.
You will now create Java objects and connect them to the application model.
Create the
com.example.e4.rcp.todo.parts
package.
Create three Java classes called TodoOverviewPart, TodoDetailsPart and PlaygroundPart in this package. These classes do not extend another class, nor do they implement any interface.
The following code shows the
TodoDetailsPart
class.
package com.example.e4.rcp.todo.parts; public class TodoDetailsPart { }
Open the
Application.e4xmi
file and connect the class with the
correct model object. You can do
this via
the
Class URI
property
of
the
part
model element.
The following table gives an overview of which elements should be connected.
Table 7. Connecting Java classes with Model Element
| Class | Part ID suffix |
|---|---|
| TodoOverviewPart | *.todooverview |
| TodoDetailsPart | *.tododetail |
| PlaygroundPart | *.playground |
The Eclipse 4 model editor allows you to search for an existing class via the button. The initial list is empty, start typing the class name to see the results.

Run your application. It should start, but you should see no difference in your user interface.
To validate that the model objects are created by the Eclipse
runtime, 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.
In this tutorial you will display Google Maps in a SWT
Browser
widget.
This exercise does not always work on a Linux system.
Change the
PlaygroundPart
class so the
part
looks like the following screenshot.

If you enter a text in the text field and press the button, the map should centered based on the input in the text field. This input should be interpreted as city.
As a result your Playground
class
should look similar to the following code.
package com.example.e4.rcp.todo; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import javax.annotation.PostConstruct; import org.eclipse.e4.ui.di.Focus; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; public class PlaygroundPart { private Text text; private Browser browser; @PostConstruct public void createControls(Composite parent) { parent.setLayout(new GridLayout(2, false)); text = new Text(parent, SWT.BORDER); text.setMessage("Enter City"); text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); Button button = new Button(parent, SWT.NONE); button.setText("Search"); button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { String city = text.getText(); if (city == null || city.length() == 0) { return; } try { browser.setUrl("http://maps.google.com/maps?q=" + URLEncoder.encode(city, "UTF-8") + "&output=embed"); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } } }); browser = new Browser(parent, SWT.NONE); browser.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); } @Focus public void onFocus() { text.setFocus(); } }
The general concept behind dependency injection is called Inversion of Control . A class should not configure its dependencies 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 on another class if it uses an instance of this class, e.g. via calling the constructor or via a static method call. For example a class which accesses a logger service has a dependency on this service class.
Ideally Java classes should be as independent as possible from other Java classes. This increases the possibility of reusing these classes and to be able 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 and is a framework class.
This way the Java class has no hard dependencies, i.e. it does not rely on an instance of a certain class. 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. Mock is an old English word meaning to mimic or imitate.
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)
a method (method injection)
a field (field injection)
Dependency injection can happen on static as well as on non-static fields and methods.
Eclipse 4 supports constructor, method and field injection.
It uses
the standard Java
@Inject
and
@Named
annotations, which were defined in the Java Specification Request 330
(JSR330). In addition to these standard annotations, Eclipse declares
the
@Optional
annotation.
The following table gives an overview of the dependency injection (DI) annotations.
Table 8. 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.
|
| @Optional |
Marks an injected value
to
be optional. If it can not be
resolved,
The specific behavior depends where @Optional is used:
|
In addition to these basic annotations Eclipse contains more annotations for special purposes, e.g. for the propagating events or working with preferences.
The Eclipse 4 runtime creates objects for the Java classes referred to by the application model. During this instantiation the Eclipse runtime scans the class definition for annotations.
Based on these annotations the Eclipse framework performs the injection. First the constructor injection is performed and afterwards the field and method injections.
Constructors are called before the fields are injected. Accessing an injected field in the constructor will result in an Exception thrown by the Framework.
The Eclipse framework also tracks the injected values and if they change, it can re-inject the new values. This means applications can be freed from having to install (and remove) listeners.
For example you can define that you want to get the current selection injected. If the selection changes, the Eclipse framework will inject the new value.
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, i.e. 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 application 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
Applications can define their own injection suppliers too.
For the purpose of this tutorial, all elements of the context will be called context elements.
Objects can be places in the context via the Class name or via a String. If the key is a String, this key/value pair is called a Context variable.
Key/value pairs or Context variables can be present at different levels in the context hierarchy.
Context variables and key/value pairs in the context allow to separate the interesting state from the source of the state. For example in the Eclipse IDE a lot of components use the active editor to drive their views, but it means their views are coupled to the active editor; the editor could instead set a context variable to their state and the views react to that variable change instead.
The Eclipse platform places several key/value pairs and
Context variables
into the
context. Several
Context variables
keys are defined in the
IServiceConstants
interface.
All possible values for dependency injection can be accessed via the context.
The context contains Java objects which can be accessed by keys. Keys can manifest themselves in two forms: Strings and Class objects.
If a String is used as a key, the corresponding key/value pair is called a Context Variable.
Access to the context works in a similar way to accessing a Java
Map
data structure.
The context is not a flat structure like a
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.
Model elements which implement the
MContext
interface
have a local
context. These are currently
MApplication,
MWindow,
MPerspective,
MPart
and
MPopupMenu.
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 an 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.
The following picture visualizes this context hierarchy.

The context is hierarchical to avoid collisions in injected
values and
to
increase the isolation of the classes in terms of what they
need.
For
example a
part
needs a unique
Composite
objects to create its user interfaces. Since
parts
have
different
local contexts, their
@Inject
gets the needed implementation from the actual context.
The search happens transparently for the caller of the injection.
The interface for the context object is the
IEclipseContext
interface.
The Eclipse platform uses the
OSGiContextStrategy
class to search for OSGi services 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 via the
EclipseContextFactory
class 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.
Another example is the
WBWRenderer
class which is responsible for creating a
Window. This class puts an instance of the
IWindowCloseHandler
and the
ISaveHandler
interface
into the context of the
Window. The first is responsible for
the
behavior of a
Window
during close, the other one for saving. For
example the default
IWindowCloseHandler
would prompt you if you want to save
parts
which indicate that they have saveable content via the
MDirtyable
model attribute. You can change this default
IWindowCloseHandler
implementation
via the
MWindow
model object. The following example shows this.
@Execute public void execute(final Shell shell, EModelService service, MWindow window) { IWindowCloseHandler handler = new IWindowCloseHandler() { @Override public boolean close(MWindow window) { return MessageDialog.openConfirm(shell, "Close", "You will loose data. Really close?"); } }; window.getContext().set(IWindowCloseHandler.class, handler); }
In general, every framework defines an application programming interface (API).
If you use a framework you need to have a convention for 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 via an abstract class which methods
must be
implemented.
In this
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
class
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. It also makes extending or updating the framework difficult.
Eclipse does not provide framework classes which you can extend. To identify which methods should be called at a certain point in time, the Eclipse platform uses annotations to identify methods which should be called at a certain point.
These annotations are called 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 for parts.
Table 9. Eclipse lifecycle annotations for Parts
| Annotation | Description |
|---|---|
| @PostConstruct | Is called after the class is constructed and the field and method injection has been performed. |
| @PreDestroy | Is called before the class is destroyed. Can be used to clean up resources. |
| @Focus | Indicates that this method should be called, once the Part gets the focus. It is required to set the focus on one user interface control otherwise certain workbench functionality does not work. |
| @Persist | Is called if a save request on the Part is triggered. Can be used to save the data of the Part. |
| @PersistState | Is called before the model object is disposed, so that the Part can save its state. |
All these annotations will also trigger dependency injections.
Therefore you do not need to add the
@Inject
annotation if you use these annotations.
The
@PostConstruct,
@PreDestroy
annotations are included in the
javax.inject
package.
Eclipse defines also more annotations for other components. The following table lists a few more but you also have annotations for commands which are covered in the command chapter.
Table 10. Other Eclipse Behavior Annotations
| Annotation | Description |
|---|---|
| @GroupUpdates |
Indicates that updates for this @Inject should be batched.
If you
change such objects in the
IEclipseContext
the update will be
triggered by the
processWaiting()
method on
IEclipseContext.
|
| @EventTopic and @UIEventTopic | Allows you to subscribe to events send by the EventAdmin service. |
@Persists,
@PersistState
and
@Focus
are part of the
org.eclipse.e4.ui.di
package.
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) { // Assuming that dependency injection works // parent will never be null System.out.println("Woh! Got Composite via DI."); // Does it have a layou manager? System.out.println("Layout: " + parent.getLayout().getClass()); } }
It is possible to create the user interface of a part in the constructor but injection for fields and method has not been done at this point.
Therefore it is recommended that the user interface is
created in a
@PostConstruct
method.
Realizing the user interface
in a method annotated with
@PostConstruct
requires that
@Inject
methods
be aware that the user interface might not yet be created.
Add the following method to your
TodoOverviewPart,
TodoDetailsPart
and
PlaygroundPart
classes.
// Declare a field label, required for @Focus Label label; @PostContruct public void createControls(Composite parent) { label = new Label(parent,SWT.NONE); label.setText("A text...."); }
Remove all constructors from your classes.
Implement a
@Focus
method in each
part. Setting the focus to one of SWT controls is mandatory in Eclipse
4.2. Eclipse 4.3 made this optional.
@Focus private void setFocus() { label.setFocus(); }
Run your application and validate that the
@PostConstruct
method
is
called. Use
either debugging or a
System.out.println()
statement. Every Part needs to assign focus to one of its controls,
otherwise certain services will not work. Therefore we added a SWT
label to be the focus control. Even though a label cannot take focus,
it triggers the
SWT.ACTIVATE
event, which is sufficient for the Eclipse services to work
correctly.
If you are familiar with SWT, add a few more controls to your user interface.
If the
@PostConstruct
method is not called, ensure that you have entered a package
dependency to the
java.annotation
package and set the version to 1.0.0. See
http://wiki.eclipse.org/Eclipse4/RCP/FAQ for details on this issue.
The Eclipse application model can contain commands and handlers.
A command in Eclipse is a declarative description of an abstract action which can be performed, for example save, edit or copy. A command is independent from its 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.
The handler can be global to the application, or scoped to a window or a part. This means that you can define for example a copy handler globally in your application but define special copy handlers for certain parts. Eclipse uses the most detailed one.
The behavior annotations for handler classes are described in the following table.
Table 11. Other Eclipse Behavior Annotations
| Annotation | Description |
|---|---|
| @Execute | Marks a method in a handler class to be executed. Only one method in a handler should be annotated with @Execute. |
| @CanExecute | Marks a method to be visited by the Command- Framework to check if a handler is enabled |
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. If the handler can always execute, it does not need
to supply a
@CanExecute
method.
package com.example.e4.rcp.todo.handlers; // Imports statements cut out // .. public class ExitHandler { @Execute public void execute(IWorkbench workbench) { workbench.close(); } // Default to true if not implemented @CanExecute public boolean canExecute() { // TODO add some logic here return true; } }
@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 is
automatically
registered by
the Eclipse framework
which, as of the time
of this
writing, executes
every 400
Milliseconds. This timer will check
the
@CanExecute to
enable
or disable the related toolbar entry.
In the handler class you can determine the command ID if the command was triggered via the user interface. Determining the ID is not possible, if it was triggered via the command service. The following code snippet shows how to get the command ID.
@Execute public void execute(MHandledItem item) { MCommand command = item.getCommand(); // Prints out the commmand ID System.out.println(command.getElementId()); }
If you know Eclipse 3.x you are probably searching for the predefined commands which you can re-use. The Eclipse 4 platform tries to be as lean as possible.
Eclipse 4 does not include standard commands anymore. You have to define all your commands.
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 selected, 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 you to define a class to be executed directly. This is useful if you just want to respond to the user clicking on a menu item or tool item.
Using commands together with handlers gives you more flexibility, for example you can have different Handlers for different scopes (Applications or Views) and you can define key bindings for the handler's associated commands.
Toolbars in the application are encapsulated in the application model via the trimbar model element. A trimbar can be defined for Windows. Via its attribute you define if the trimbar should be placed on the top, left, right or bottom corner of the Window.
The related command is assigned to the menu and toolbar entry. Menus and toolbars support separators. Menus can have submenus.
To make menus more accessible, a menu label can make use of an mnemonic. An mnemonic appears as an underlined letter in the menu when the user presses and holds Alt key and acts as a way to easily navigate menus by keyboard. Defining mnemonics is as simple as prefixing the letter intended to be the mnemonic with an ampersand in the label definition. For example the label &Save shows up as Save with the S underlined when the Alt key is pressed.
Each command can have only one valid handler for a given scope. The application model allows you to define a handler for the application, for a Window and for a part.
If more than 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.
Once the handler is selected,
@CanExecute
is called so the handler can determine if it is able to execute in
the
given context. If it returns false it will disable any menu and
tool
items that point to that command.
The Javadoc of
@Execute
defines that only one methods of a handler is allowed to be annotated
with
@Execute.
Therefore it is an error to annotated more than one method with
@Execute.
A good convention is to start IDs with the top level package name of your project and to use only lower case.
The IDs of commands and handler should reflect their
relationship.
For
example if you implement a
command with the
com.example.contacts.commands.show
ID, you should use
com.example.contacts.handler.show
as the ID for the handler. If you have more than one handler
defined,
add
another suffix to it, describing its purpose,
e.g.
com.example.contacts.handler.show.details.
In case you implement commonly used functions, e.g. save, copy,
you
should use the existing platform IDs, as some Eclipse
contributions
expect these IDs. A more complete list of command IDs
is available in
org.eclipse.ui.IWorkbenchCommandConstants.
Table 12. 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 |
One menu in a part can be defined as a view menu. Please note that you can define a maximum of one menu as view menu.
To add such a view menu entry, select the Menus entry under our Part, select ViewMenu and press the Add button.

You can also define a popup menu for SWT controls. For this you define a Popup Menu for your part in the application model.


You can then assign it via the
EMenuService
class with the
registerContextMenu(control, id)
to a
SWT
control. The
id
parameter
of the
registerContextMenu
method
must be the
elementId
of your
Popup Menu
model element.
The following code shows an example for the registration.
package com.example.e4.rcp.todo.parts; import javax.annotation.PostConstruct; import org.eclipse.e4.ui.workbench.swt.modeling.EMenuService; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; public class TodoDetailsPart { @PostConstruct public void createUi(Composite parent, EMenuService service) { final Text text = new Text(parent, SWT.BORDER); text.setText("Hello"); // Make use to use the correct ID // from the application model service.registerContextMenu(text, "com.example.e4.rcp.todo.popupmenu.table"); } }
If you using a JFace viewer you have to use the SWT control.
package com.example.e4.rcp.todo.parts; import javax.annotation.PostConstruct; import org.eclipse.e4.ui.workbench.swt.modeling.EMenuService; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; public class TodoDetailsPart { @PostConstruct public void createUi(Composite parent, EMenuService service) { // more code... TableViewer viewer = new TableViewer(parent, SWT.FULLSELECTION | SWT.MULTI); // more code /register context menu on the table menuService.registerContextMenu(viewer.getTable(), "com.example.e4.rcp.todo.popupmenu.table"); } }
If you want to implement this example you also need to have a
dependency to the
org.eclipse.e4.ui.workbench.swt
plug-in in your application.
You can also pass parameters to commands.
To define that a command accepts a parameter, select your command and press the Add button in the Parameter section.
The ID is the identifier which you can use to get the parameter via
the
@Named
annotation.


Getting the parameter via
@Named
annotation in your handler is demonstrated in the
following code
example.
package com.example.e4.rcp.todo.handlers; import javax.inject.Named; import org.eclipse.e4.core.di.annotations.CanExecute; import org.eclipse.e4.core.di.annotations.Execute; public class TestHandler { @Execute public void execute(@Named("com.example.e4.rcp.todo" + ".commandparameter.input") String param) { System.out.println(param); } }
In your menu or toolbar entries the Name field must be equal to the ID entry in the parameter you defined in your command. The entry in the Value field is passed to the command.

The id of the parameter is the important one. This id of the
parameter must be injected via the
@Named
annotation and use as
Name
(second field) during the definition of the menu or toolbar. This is
highlighted in the following picture.

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 in the
plugin.xml
file.
To add this extension point to your application, open the
plugin.xml
file and select the
Dependencies
tab in the editor. Add the
org.eclipse.core.expressions
plug-in in the
Required Plug-ins
section.
Afterwards select the
Extensions
tab, press the
Add
button
and add the
org.eclipse.core.expressions.definitions
extension. You define an ID under which the core expression can be
referred to in the application model.
Via right-click on the extension you can start building your expression.
You can assign this core expression to your menu entry in the application model. The following screenshot shows this for the Test menu entry.
The following example can be used to restrict the visibility of
a menu
entry based on the type of the current selection. You will later
learn how to set the current selection. Please note that
the variable
for the
selection is currently called
org.eclipse.ui.selection. In Eclipse 3.x this variable is called
selection.
<extension
point="org.eclipse.core.expressions.definitions">
<definition
id="com.example.e4.rcp.todo.selectionset">
<with variable="org.eclipse.ui.selection">
<iterate ifEmpty="false" operator="or">
<instanceof value="com.example.e4.rcp.todo.model.Todo">
</instanceof>
</iterate>
</with>
</definition>
</extension>
This expression can be used to restrict the visibility of model elements.


This approach is similar to the definition of core expressions in Eclipse 3.x.
The values available for Eclipse 3.x are documented in the Eclipse
Wiki under the following
link:
Core Expressions
and contained in the
ISources
interface. Eclipse 4 does not always support the same variables, but
the wiki might still be helpful.
You can also place values in the
IEclipseContext
of your application and use these for your visible-when evaluation.
Later you will learn more about modifying the
IEclipseContext
but the following code is an example
Handler
which places a value for the
myactivePartId
key in the context.
@Execute public void execute(IEclipseContext context) { // put an example value in the context context.set("myactivePartId", "com.example.e4.rcp.ui.parts.todooverview"); }
The following shows an example core expression which evaluates to
true
if an
myactivePartId
key
with the value
com.example.e4.rcp.ui.parts.todooverview
is found in the context.
This core expression can get assigned to a menu entry and control the visibility.
<extension
point="org.eclipse.core.expressions.definitions">
<definition
id="com.example.e4.rcp.todo.todooverviewselected">
<with
variable="myactivePartId">
<equals
value="com.example.e4.rcp.ui.parts.todooverview">
</equals>
</with>
</definition>
</extension>

You will now define commands and handlers for your application. We will define our handlers for the whole application.
Open
the
Application.e4xmi
file and select
Commands.

Via the button you can create new commands. The name and the ID are the important fields. Create the following commands.
Table 13. Commands
| ID | Name |
|---|---|
| org.eclipse.ui.file.saveAll | 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.test | For testing |
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 SaveAllHandler { @Execute public void execute() { System.out.println("Called"); } }
Using this template for all classes, implement the following classes.
SaveAllHandler
ExitHandler
NewTodoHandler
RemoveTodoHandler
TestHandler
Select the entry Handlers in your application model and create the handlers from the following table for your commands. For the definition of handlers the ID, the command and the class is relevant information.
Use the com.example.e4.rcp.todo.handlers prefix for all handlers IDs.
Table 14. Handlers
| Handler ID | Command - Class |
|---|---|
| *.save | Save - SaveAllHandler |
| *.exit | Exit - ExitHandler |
| *.new | New Todo - NewTodoHandler |
| *.remove | Remove Todo - RemoveTodoHandler |
| *.test | For testing - TestHandler |
The application model editor shows both the name and the ID of
the
command. The class URI follows the
bundleclass://
schema, the table only defines the class name to make the table more
readable. For example for the save handler this looks like the
following:
bundleclass://com.example.e4.rcp.todo/[CONTINUE...] com.example.e4.rcp.todo.handlers.SaveAllHandler

You will now add a Menu to your application model.
Select the
Application.e4xmi
file. To add a menu to a
Window
select your
TrimmedWindow
entry in the model and flag the
Main Menu
attribute.

Assign the org.eclipse.ui.main.menu ID to your main menu.
Add two menus, one with the name
File
and the other one with
the name
Edit
in the
Label
attribute.
Also set the org.eclipse.ui.file.menu ID for the File menu. Use com.example.e4.rcp.todo.menu.edit as ID for the Edit menu.

Add a
HandledMenuItem
to the
File
menu. This item should point to the
Save
command via the
Command
attribute.

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
TrimBars
node under your
Window
entry and press the
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.saveAll
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 com.example.e4.rcp.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(); } }
It is also possible to define key bindings (shortcuts) for your Eclipse application. This requires two steps, first you need to enter values for the BindingContext node of your application model.
Afterwards you need to enter the keybindings for the relevant BindingContext in the BindingTable node of your application model. A BindingTable is always assigned to a specific BindingContext. A BindingContext can have several BindingTables assigned to it.
BindingContexts are defined in a hierarchical fashion, so that keybindings in child BindingContexts override the matching keybinding in the parent BindingContext.
The BindingContext is defined via its ID. A BindingContext can get assigned to a Window or a part in the application model. This would define which keyboard shortcuts are valid for the Window Window or the part.
Eclipse JFace uses predefined
BindingContext
identifier which
are
based on the
org.eclipse.jface.contexts.IContextIds
class. JFace
distinguishes between shortcuts for dialogs, windows or
both.
The following gives an overview of the supported ID and the validity of keybindings defined with reference to this Context ID.
Table 15. Default BindingContext values
| Context ID | Description |
|---|---|
| org.eclipse.ui.contexts.dialogAndWindow | Key bindings valid for Dialogs and Windows |
| org.eclipse.ui.contexts.dialog | Key bindings valid in Dialogs |
| org.eclipse.ui.contexts.window | Key bindings valid for Windows |
As an example, Ctrl+C (Copy) would be defined in dialogAndWindows as it is valid everywhere, but F5 (Refresh) might only be defined for a Window and not for a Dialog.
The BindingTable node in the application model allows you to define shortcuts for a specific BindingContext.
To define a shortcut you create a new node for BindingTable and define a reference for the Context ID.
In your keybinding you define the key Sequence and the command associated with this shortcut.

The control keys are different for the different platforms, e.g. on the Mac vs. a Linux system. For example you can use Ctrl but this would be hardcoded. It is better to use the M1 - M4 metakeys .
Table 16. Key Mapping
| Control Key | Mapping for Windows and Linux | Mapping for Mac |
|---|---|---|
| M1 | Ctrl | Command |
| M2 | Shift | Shift |
| M3 | Alt | Alt |
| M4 | Undefined | Ctrl |
These values are defined in the
SWTKeyLookup
class
You can assign a specific BindingContext to be active while a Part is active.

If there are several valid key bindings defined the
ContextSet
class
is responsible for selecting the default one.
ContextSet
uses the
BindingContext
hierarchy to determine the lookup order. A
BindingContext
is
more specific depending on how many ancestors are between it
and a
root
BindingContext
(the number of levels it has). The
most specific
BindingContext
are considered first, the root
BindingContext
are considered last.
You can also use the
EContextService
service which allows you to explicitly activate and deactivate a
BindingContext
via the
activateContext()
and
deactivateContext()
methods.
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.
To add your new model elements to the application you can use the modelservice or get existing elements injected.
To create new model objects you can use the
MBasicFactory.INSTANCE
class. This is a factory used to create new model objects via typed
create*()
methods. For example you can create a new Window at runtime as shown
in the
following snippet.
// Create a new window and set its size MWindow window = MBasicFactory.INSTANCE.createTrimmedWindow(); window.setWidth(200); window.setHeight(300); // Add new Window to the application application.getChildren().add(window);
For example the following adds 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.[CONTINUE...] .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.setElementId("mynewid"); part.setLabel("A new Part"); part.setContributionURI("bundleclass://com.example." + "e4.rcp.todo/com.example.e4.rcp.todo.parts.TodoOverviewPart"); window.getChildren().add(part); } }
Eclipse 4 tries to keep the core framework as minimal as possible. Addon model object can be registered globally on the application model and can enhance the application with additional functionality. Addons are normal Java objects.
Addons
use the
bundleclass://
URI convention in the application model to refer to the Java
objects.
Having these addons registered allows them to be enhanced or replaced by the Eclipse platform team or by a customer specific implementation in case the need arises.
Currently the following standard addons are useful for Eclipse applications. Their class names give an indication of their provided functionality. Check their Javadoc to get a short description of their purpose.
CommandServiceAddon
ContextServiceAddon
BindingServiceAddon
CommandProcessingAddon
ContextProcessingAddon
BindingProcessingAddon
Additional addons are available, e.g. to support drag-and-drop of parts in your application.
To support drag-and-drop for
parts
you need to add the
org.eclipse.e4.ui.workbench.addons.swt
plug-in to your product configuration file. Then you can use the
DnDAddon
and the
CleanupAddon
from this bundle as
addons
in your application model. This plug-in
contains also the
MinMax
add-on which adds the minimize and maximize functionality to your
application.
The
org.eclipse.e4.ui.workbench.addons.swt
plug-in contributes these plug-ins to your application model via a
processors, e.g. a Java class which changes the application model. If
you remove the plug-in from your product then these
addons
are not
available.
Addons are created before the rendering engine renders the model and after the EventAdmin Service has been created.
This allows
addons
to alter the user interface that is produced by the rendering
engine.
For example, the
min/max
addon
changes the tab folders created for
MPartStacks
to have min/max buttons in the corner.
The
EventAdmin
services provides the notifications about Eclipse events, e.g. if a
part
is activated.
Addons
can
to subscribe to events from the Eclipse platform.
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 // ... } }
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 MPart, MWindow,
MApplication and MPerspective 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; // Getting the application context // via the MApplication object public class TodoDetailsPart { @PostConstruct public void createControls(Composite parent, MApplication application) { IEclipseContext context = application.getContext(); // Add or access objects to and from the application context // ... } }
If you are outside of a model object, you still can access the OSGi 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); }
You can add objects to the context via OSGi services. OSGi services are automatically available in the context. But OSGi services are global to the framework runtime ??? they can not access the workbench model or its context.
You can add key / value pairs directly to the
IEclipseContext, for example a todo object under the
active
key.
Adding objects to
a Context can be done via
the
set()
method on
IEclipseContext. The following example creates a new context via the
EclipseContextFactory.create()
factory method call and adds some objects to it.
@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); // Alternatively you can also // establish a parent/child // relationship via the // context.createChild() method call }
A
Context variable
can be declared as
modifiable
via the
declareModifiable(key)
method call.
@Inject public void addingContext(IEclipseContext context) { // Putting in some values context.set("mykey1", "Hello1"); context.set("mykey2", "Hello2"); // Declares the named value as modifiable // by descendants of this context. If the value does not // exist in this context, a null value is added for the name. context.declareModifiable("mykey1"); }
Modifiable
Context variables
are added to particular levels of the
IEclipseContext
hierarchy and can also be modified using the
modify()
method rather than
set()
method of the
IEclipseContext.
The
modify()
methods searches up the chain to find the
Context
defining the variable. If none of the
Context
on the parent chain have a value set for the name, the value will be
set in this
Context.
If the key already exists in the context, then
modify()
requires that the key has been set to modifiable with the
declareModifiable()
method, if not, the method
throws an
exception.
You can add key/values pairs and Context variables at different levels of the context hierarchy so supply your application with different objects.
You can add Addons to the application model. These Addons contain a reference to Java classes, which can extend the context or interact with other Eclipse platform services, e.g. the EventAdmin.
For example you could register a model Addon to put some values into the context.

The following code shows an example implementation for the Addon.
package com.example.e4.rcp.todo.addons; import javax.annotation.PostConstruct; import org.eclipse.e4.core.contexts.IEclipseContext; public class MyModelAddon { @PostConstruct public void init(IEclipseContext context) { context.set("test1", "Hello"); } }
The
IEclipseContext
allows you via the
runAndTrack()
method to register a Java object of type
RunAndTrack.
A
RunAndTrack
is basically a
Runnable
which has access to the context. If the runnable accesses any values
in this context
during its execution, the runnable will be executed
again after any
of those values change.
The
runAndTrack()
method allows a client to keep some external state
synchronized
with
one or more values
in this context.
The runnable does not need to be explicitly unregistered from this context when it is no longer interested in tracking changes. If a subsequent invocation of this runnable does not access any values in this context, it is automatically unregistered from change tracking on this context.
If the Eclipse dependency injection framework does not find an object in the current context it queries the defined context functions to see if a class has been registered to create it.
A
context functions
implement the
IContextFunction
interface or extends the abstract
ContextFuntion
class
and allow you to lazily create an object.
In Eclipse 4 you would
extend the
ContextFunction
class to receive an
IEclipseContext
in the
compute()
method as input.
Context Functions
are contributed as OSGi Services. They implement the
IContextFunction
interface from the
org.eclipse.e4.core.contexts
package. The Eclipse 4 runtime adds
context functions
by default to the
application context.
Via the
service.context.key
property,
they define their key under which they are added to the
context.
Using dependency injection for your own Java objects has two
flavors.
First you want the Eclipse dependency container to create
your own
objects and then get them injected into your model objects.
Secondly
you want
to create objects which declare their dependencies with
@Inject
and want to create it via dependency injection.
Both approaches are described here.
If you want the Eclipse framework to create your objects
for you,
annotate them with
@Creatable. This way you are telling the Eclipse DI container that it should
create
a new instance of this object if it does not find an instance
in the
context.
The Eclipse DI container will use the constructor with the highest
number of parameters of this class for which the Eclipse DI container
can find values in the Eclipse context.
You can also use
@Inject
on the constructor to indicate that Eclipse should try to run
dependency injection also for this constructor.
For example, assume that you have the following domain model.
@Creatable class Todo { @Inject public Todo(Dependent depend, YourOSGiService service) { // placeholder } } @Creatable class Dependent { public Dependent() { // placeholder } }
If no fitting constructor is found, the Eclipse framework will throw an exception.
Assuming that you have defined the
YourOSGiService
service in your application, you
can get an instance of your Todo
data
model injected in a Part.
// Field Injection
@Inject Todo todo
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);
The
ContextInjectionFactory.make()
method creates the object. You can also put it into the context. If
you want to retrieve
the object from the
Context, you can use the key you specified.
For this you can either use an existing context as described in the last section or a new context. Using a new context is preferred to avoid collision of keys and to isolate your changes in a local context.
IEclipseContext context = EclipseContextFactory.create(); // Add your Java objects to the context context.set(MyDataObject.class.getName(), data); context.set(MoreStuff.class, moreData);
The following table lists the most important tags for model elements of Eclipse 4 applications.
Additional tags are defined in the
IPresentationEngine
class. It is up to the renderer implementation and model AddOns to
interpret these tags. Renderer might also define additional tags. You
also find more information about the available tags in the Eclipse 4
Wiki (see resources for link).
Table 17. Relevant tags of application model elements
| Tag | Model element | Description |
|---|---|---|
| shellMaximized | Window or Trimmed Window | Window is maximized at start of the application. |
| shellMinimized | Window or Trimmed Window | Window is minimized at start of the application. |
| NoAutoCollapse | PartStack | Avoids that the MinMax Addon minimizes this PartStack if all Parts have been removed from it. |
| FORCE_TEXT | ToolItem | Enforces that text and icon is shown for a toolbar item. |
| NoMove | Part | Prevents the user from moving the part (based on the DndAddON). |
Best practices tend to be subjective. If you disagree with certain suggestions, feel free to use your own approach.
The application can use the Eclipse Context for providing functionality, communication and for changing Eclipse behavior. You have several options to contribute to the context: OSGi services, context functions, context elements, context variables and ModelAddons.
The programming model of Eclipse 4 makes it relatively easy to use OSGi services, compared to Eclipse 3.x. OSGi services are effectively Singletons and do not have access to the Eclipse application context. OSGi services are a good approach for infrastructure services which are Singletons.
Context functions are OSGi services which are typically stored on the application level and have access to the Eclipse application context. If this is required, they can be used instead of pure OSGi services.
Context elements are useful, if values should be stored on certain places in the Eclipse context hierarchy. Also replacing Eclipse platform implementations is a valid use case to use context elements, e.g. to change the default window close handler.
Context functions and context variables are useful in situations where the variables need to change, and are different for different levels in the Eclipse context hierarchy.
Model AddOns allow you to contribute Java objects to the application context. The advantages of Model AddOns are that they are part of the application model, hence they are very visible components. A Model AddOn can register itself to events or contribute again to the Eclipse context.
For user interface scoped communication it is recommended to use
Context
variables
or the
EventAdmin
service for communicating the state.
The
EventAdmin
service is a good choice, if there is no scope involved in the
communication. The strengths of
EventAdmin
is
that arbitrary
listeners can listen to events and that the
publish
/ subscribe mechanism is relatively simple.
If your application model is primarily static, you should define it statically, as this static model provides a good visibility of your application at development time.
If required, add dynamic behavior. These dynamic parts can be evaluated at runtime via the live model editor.
Eclipse and OSGi support component based development.
User interface related and core functionalities should be separated into different plug-ins.
The data model of the application should be kept in its own plug-in. Almost all plug-ins will depend on this plug-in, therefore keep it as small as possible.
The programming model of Eclipse 4 has reduced the need for using Extension points but Extension points still have valid use cases.
If you have multiple plug-ins which should contribute to a defined API, you can still define and use your own extension points.
Eclipse plug-ins explicitly declare their API via their exported packages. Publish only the packages which other plug-ins should use. This way you can later on change your internal API without affecting other plug-ins. Avoid exporting packages just for testing.
OSGi allows you to define dependencies via plug-ins or via packages.
Dependencies based on packages express an API dependency as they allow you to exchange the implementing plug-in. Dependencies based on plug-ins imply a dependency on an implementation.
Use package dependencies whenever you intent to exchange the implementing plug-in.
Package dependencies add complexity to the setup as you usually have more packages than plug-ins.
Therefore use plug-in dependencies, if there is only one implementing plug-in and an exchange of this plug-in in the near future is unlikely.
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.com Google Group. I have created a short list how to create good questions which might also help you.