NOW Hiring

Quick links

Eclipse platform services - Tutorial

Lars Vogel

Version 6.1

11.02.2016

Eclipse e4

This tutorial gives an overview of the available services of the Eclipse platform. These service are used to developing Eclipse RCP applications and Eclipse plug-ins.


Table of Contents

1. Eclipse platform services
1.1. What are Eclipse platform services?
1.2. Overview of the available platform services
1.3. How are Eclipse platform services implemented?
2. Selection service
2.1. Usage of the selection service
2.2. Changing the current selection
2.3. Getting the selection
3. Model Service
3.1. What is the model service?
3.2. How to access the model service
3.3. Cloning elements or snippets
3.4. Searching model elements
4. Application model modifications at runtime
4.1. Creating model elements
4.2. Modifying existing model elements
5. Example for changing the application model
5.1. Example: Search for a perspective and change its attributes
5.2. Example: Dynamically create a new window
5.3. Example: Dynamically create a new part
6. Part service and editor like behavior
6.1. What is the part service?
6.2. How to access the part service
6.3. Example: Showing and hiding parts
6.4. Example: Switching perspectives
6.5. Using part descriptors
6.6. Example: Part descriptors and creating parts dynamically
7. Implementing editor like behavior
7.1. Parts which behave similar to editors
7.2. MDirtyable and @Persist
7.3. Use part service to trigger save in editors
7.4. MPart and multiple editors
7.5. MInputPart
8. Command and Handler service
8.1. Purpose of the command and handler service
8.2. Access to command and handler service
8.3. Example for executing a command
8.4. Example for assigning a handler to a command
9. Learn more about Eclipse 4 RCP development
10. About this website
11. Links and Literature
Get the book! Eclipse RCP book

1. Eclipse platform services

1.1. What are Eclipse platform services?

Services are software components (based on an interface or a class) which provide functionality. The Eclipse platform defines several services. The classes which are created based on the application model can access these services via dependency injection.

To use an Eclipse service you specify the service dependency via an @Inject annotation and the Eclipse framework injects this component into your object.

The typical naming convention for Eclipse service interfaces is to start with an E and end with Service e.g. E*Service.

1.2. Overview of the available platform services

The following table gives an overview of the most important available platform services.

Table 1. Platform services

Service Description
EModelService Used to search for elements in the model, create new model elements, clone existing snippets and insert new elements into the runtime application model.
ESelectionService Used to retrieve and set the current active selection in the user interface.
ECommandService Gives access to existing commands and allows you to create and change commands.
EHandlerService Allows you to access, change and trigger handlers.
EPartService Provides API to access and modify parts. It also allows you to switch perspectives and can be used to trigger that a method annotated with @Persist in dirty parts, i.e. if the corresponding part behaves like an editor.
IEventBroker Provides functionality to send event data and to register for specified events and event topics.
EContextService Activate and deactivate key bindings defined as BindingContext in the application model. The content referred to in this service is the BindingContext and not the IEclipseContext.
IThemeEngine Allows to switch the styling of the application at runtime.
EMenuService Registers a popup menu (MPopupMenu) for an control


Other available services are:

  • org.eclipse.e4.core.services.Adapter - An adapter can adapt an object to the specified type, allowing clients to request domain-specific behavior for an object. It integrates IAdaptable and IAdapterManager. See the Adapter wiki for details.

  • org.eclipse.e4.core.services.Logger - Provides logging functionality

  • org.eclipse.jface.window.IShellProvider - allows access to a Shell, depends on SWT.

1.3. How are Eclipse platform services implemented?

Usually services have two parts: the interface definition and the implementation. How these two are linked is defined by a context function, an OSGi service or plain context value setting (IEclipseContext). Please note that there can be more than one service implementation for an interface.

2. Selection service

2.1. Usage of the selection service

The ESelectionService service allows you to retrieve and set the global selection in your current application window. Other classes in the application model can use the dependency injection mechanism to retrieve the relevant active selection directly.

A client can get the selection service via: @Inject ESelectionService.

Tip

The selection is window specific, i.e. stored in the context of the MWindow model object.

2.2. Changing the current selection

You can change the current selection with the setSelection() method of the ESelectionService class. This is demonstrated in the following code.

// use field injection for the service
@Inject ESelectionService selectionService;

// viewer is a JFace Viewer
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
  @Override
  public void selectionChanged(SelectionChangedEvent event) {
    IStructuredSelection selection = viewer.getStructuredSelection();
    selectionService.setSelection(selection.getFirstElement());
  }
}); 

2.3. Getting the selection

A client can retrieve the last selection for the current window directly from the ESelectionService via the getSelection() method. The getSelection(partId) method allows you to retrieve the selection of a specific part.

Tip

The possibility of retrieving the selection of a part is based on the hierarchy of the IEclipseContext. With this hierarchy it is possible to store a selection per window and also per part.

It is preferred that a class which is part of the application model uses dependency injection to retrieve the selection. The selection is stored under the key based on the IServiceConstants.ACTIVE_SELECTION constant. This key can be specified via the @Named annotation. The Eclipse framework ensures that selections are only injected if they have the fitting type.

The usage of the @Named annotation to retrieve the selection is demonstrated with the following method.

@Inject
public void setTodo(@Optional 
    @Named(IServiceConstants.ACTIVE_SELECTION) Todo todo) {
  if (todo != null) {
    // do something with the value
  }
} 

3. Model Service

3.1. What is the model service?

The model service gives you access to the application model at runtime and allows you to modify it. For example, you can add and remove model elements. It also contains functionality to clone application model snippets which can be added to the application.

3.2. How to access the model service

This service can be accessed via dependency injection. For example, via field injection with the following statement: @Inject EModelService modelService;

3.3. Cloning elements or snippets

In the application model you can create Snippet model elements which can be used to create model objects at runtime. It is also possible to copy existing application model elements via the model service.

You can use the cloneElement() and cloneSnippet() methods of the model service to copy an existing element or snippet. The resulting object can be assigned to another model element.

3.4. Searching model elements

The findElements() method allows you to search for specific model elements. The following code shows an example for using the findElements() method.

package com.example.e4.rcp.todo.handlers;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.workbench.modeling.EModelService;

public class ModelServiceExampleHandler {

  @Execute
  public void execute(MApplication application, EModelService service) {

    // find objects by ID
    findPartsById(application, service);

    // find objects by type
    findParts(application, service);

    // find objects by tags
    findObjectsByTag(application, service);

  }

  // example for search by ID
  private void findPartsById(MApplication application, EModelService service) {
    List<MPart> parts = service.findElements(application, "mypart",
        MPart.class, null);
    System.out.println("Found part(s) : " + parts.size());

  }

  // example for search by type
  private void findParts(MApplication application,
      EModelService service) {
    List<MPart> parts = service.findElements(application, null,
        MPart.class, null);
    System.out.println("Found parts(s) : " + parts.size());

  }

  // example for search by tag
  private void findObjectsByTag(MApplication application,
      EModelService service) {
    List<String> tags = new ArrayList<>();
    tags.add("justatag");
    List<MUIElement> elementsWithTags = service.findElements(application,
        null, null, tags);
    System.out.println("Found parts(s) : " + elementsWithTags.size());
  }
} 

Here is an example of how to find the perspective for a part.

package com.example.e4.rcp.todo.handlers;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.workbench.modeling.EModelService;

public class FindPerspectiveHandler {
  @Execute
  public void execute(MApplication application, EModelService service) {
    // search for a part with the following ID
    String ID = "com.example.e4.rcp.parts.tododetail";
    MUIElement element = service.find(ID, application);
    MPerspective perspective = service.getPerspectiveFor(element);
    System.out.println(perspective);
    // TODO do something useful with the perspective
  }
} 

You can also use the findElements method with a fifth parameter which allows you to specify additional search flags, e.g., IN_ACTIVE_PERSPECTIVE, OUTSIDE_PERSPECTIVE, IN_ANY_PERSPECTIVE. See the Javadoc of the findElements method for further details.

4. Application model modifications at runtime

4.1. Creating model elements

As the application model is interactive, you can change it at runtime. For example you can add parts to your application or remove menu entries.

To add your new model elements to the application you can use the model service or get existing elements injected.

4.2. Modifying existing model elements

You can also access existing model elements, via the model service or via dependency injection and adjust their attributes.

The Eclipse framework automatically keeps track of the application model and changes in the model are reflected immediately in your application.

For example, if you add a new window to your application, it becomes visible instantly. Or if you inject an MPart object and call its setLabel() method, the text of the part in a PartStack changes immediately.

5. Example for changing the application model

5.1. Example: Search for a perspective and change its attributes

The following code shows how to access a PartSashContainer with the mypartsashcontainer ID. It also demonstrates how to modify model attributes.

In this example it changes the container data parameter for its children. This will arrange (layout) the parts in the container.

@Execute
public void execute(EModelService service, MWindow window) {
  MPartSashContainer find = (MPartSashContainer) service.
    find("mypartsashcontainer", window);
  List<MPartSashContainerElement> list = find.getChildren();

  int i = 0;
  // make the first part in the container larger
  for (MPartSashContainerElement element : list) {
    
    if (i > 0) {
      element.setContainerData("20");
    } else {
      element.setContainerData("80");
    }
    i++;
  }
} 

5.2. Example: Dynamically create a new window

To create new model objects you can use the createModelElement() of the model service. After you created such an object you can add it to your application model at runtime.

For example, the creation of a new window for a running application is demonstrated by the following code snippet.

// create a new window and set its size
MWindow window = modelService.createModelElement(MWindow.class);
window.setWidth(200);
window.setHeight(300);

// add the new window to the application
application.getChildren().add(window); 

5.3. Example: Dynamically create a new part

The following code demonstrates how to create and add a new part to the currently active window.

package com.example.e4.rcp.todo.handlers;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState;

public class DynamicPartHandlerCode {
  // used as reference
  @Execute
  public void execute(MApplication application, EPartService partService,
      EModelService modelService) {

    // create new part
    MPart mPart = modelService.createModelElement(MPart.class);
    mPart.setLabel("Testing");
    mPart.setElementId("newid");
    mPart.setContributionURI("bundleclass://com.example.e4.rcp.todo/"
        + "com.example.e4.rcp.todo.parts.DynamicPart");
    partService.showPart(mPart, PartState.ACTIVATE);
  }
} 

Tip

Typically you would add the part to a pre-defined PartStack. Use the model service to search for the correct one.

6. Part service and editor like behavior

6.1. What is the part service?

The part service allows you to find and perform actions on parts in the application model.

It also allows you to switch perspectives and to create and activate new parts based on part descriptors in the application model.

6.2. How to access the part service

Use dependency injection to get access to the part service. For example via the @Inject EPartService partService; statement.

6.3. Example: Showing and hiding parts

The following example shows how you can find parts, hide or show them. If the Visible attribute of the part was initially set to false (not visible), you need to call the setVisible(true) method of the model element to ensure that the part gets displayed.

@Inject private EPartService partService;

// search part with ID "com.example.todo.rcp.parts.tododetails"
// assume that a part with this ID exists
detailsTodoPart = partService.findPart("com.example.todo.rcp.parts.tododetails");

// hide the part
partService.hidePart(detailsTodoPart);

//show the part
detailsTodoPart.setVisible(true); // required if initial not visible
partService.showPart(detailsTodoPart, PartState.VISIBLE); 

6.4. Example: Switching perspectives

The following example shows how you can switch to another perspective with the part service.

package com.example.e4.rcp.todo.handlers;

import java.util.List;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState;

public class SwitchPerspectiveHandler {
  @Execute
  public void execute(MApplication app, EPartService partService, 
      EModelService modelService) {
    MPerspective element = 
        (MPerspective) modelService.find("secondperspective", app);
    // now switch perspective
    partService.switchPerspective(element);
  }
} 

6.5. Using part descriptors

The part descriptor model element is a template for the creation of a part. By defining a common set of attributes via such a blueprint it is possible to create concrete instances of it via the part service.

Via the Multiple of the part descriptor you configure if multiple instances of this part can be created or not. Such a model element is depicted in the following screenshot.

Adding a PartDescripter to the model

6.6. Example: Part descriptors and creating parts dynamically

If you define a part descriptor in your application model, you can use the EPartService to create a part from it.

The following screenshot shows the definition of a part descriptor in the application model. As the Multiple parameter is set, it is possible to create several parts based on this template.

Adding a PartDescripter to the model

The part service allows you to create a new part based on this template. This is demonstrated by the following example code.

package com.example.e4.rcp.todo.handlers;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState;

public class OpenPartHandler {

  // the following code assumes that 
  // the "com.example.e4.rcp.todo.partdescriptor.fileeditor" ID
  // is used for the part descriptor
  @Execute
  public void execute(EPartService partService) {
    
    // create a new part based on a part descriptor
    // if multiple parts of this type are allowed a new part
    // is always generated
    
    MPart part = partService
        .createPart("com.example.e4.rcp.todo.partdescriptor.fileeditor");
    part.setLabel("New Dynamic Part");
    
     // the provided part is be shown
    partService.showPart(part, PartState.ACTIVATE);
  }
} 

7. Implementing editor like behavior

7.1. Parts which behave similar to editors

An editor is a part which requires that the user triggers a save operation to persist data changes in the editor. Editors that contain data, which can be saved, are typically called dirty.

The part service allows you to save dirty parts. Every part can mark itself as dirty, hence behave like an editor.

7.2. MDirtyable and @Persist

A part has the MDirtyable attribute which indicates that it can be marked as dirty. Dirty indicates that the part contains data which has been changed but not yet saved. The MDirtyable object can get injected into a part.

You can use the setDirty(boolean) method to mark the part as dirty.

The following snippet demonstrates how to use the MDirtyable model property in a part to flag it as dirty after a button was pressed.

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);
      }
    });
  }

} 

The part service allows you to query the dirty parts and to call a method annotated with @Persist on the dirty parts. This method saves the data of the part and sets the dirty flag back to false if the save operation was successful.

@Persist
public void save(MDirtyable dirty, ITodoService todoService) {
  // save changes via ITodoService for example
  todoService.saveTodo(todo);
  // save was successful
  dirty.setDirty(false);
} 

Note

Every part is responsible for saving itself. Hence every part which behaves like an editor must have one method annotated with @Persist.

7.3. Use part service to trigger save in editors

The part service allows you to trigger the @Persist method on the dirty parts via the saveAll() method.

The EPartService searches in each part which is marked as dirty for a method annotated with @Persist. This method is called by the framework and has to save the data which the editor holds. If saving the data was successful it should call the setDirty(false) method on the MDirtyable object.

The following example demonstrates that.

package com.example.e4.rcp.todo.handlers;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.workbench.modeling.EPartService;

public class SaveHandler {

  @Execute
  void execute(EPartService partService) {
    partService.saveAll(false);
  }
} 

7.4. MPart and multiple editors

You can use the MPart model element to create multiple editors. Every model element can get persisted data assigned which can be accessed via the getPersistedState() method.

In its @PostConstruct method the implementation class can get the MPart injected and access its persisted state. This information can be used to configure the editor.

7.5. MInputPart

Eclipse used to have the MInputPart model element. This model element has been deprecated and should not be used anymore. Use the approach described in Section 7.4, “MPart and multiple editors”.

8. Command and Handler service

8.1. Purpose of the command and handler service

The command and handler services provide the functionality to work with commands and handlers.

Via the handler service you can create, activate and trigger handlers based on commands. The command service allows you to access, and configure commands, i.e. by setting the parameters.

8.2. Access to command and handler service

You can use dependency injection to access the services. The relevant interfaces are ECommandService and EHandlerService.

8.3. Example for executing a command

The following example shows how to execute a handler for an existing command.

Command command = commandService.getCommand("com.example.mycommand");

// check if the command is defined
System.out.println(command.isDefined());

// activate handler, assumption: the AboutHandler() class exists already
handlerService.activateHandler("com.example.mycommand", 
    new AboutHandler());

// prepare execution of command
ParameterizedCommand cmd =
  commandService.createCommand("com.example.mycommand", null);

// check if the command can get executed
if (handlerService.canExecute(cmd)){
  // execute the command
  handlerService.executeHandler(cmd);
} 

8.4. Example for assigning a handler to a command

The following example shows how to add a new handler to an existing command. It assumes that the AboutHandler class already exists.

Command command = commandService.getCommand("com.example.mycommand");

// check if the command is defined
System.out.println(command.isDefined());

// activate handler, assumption: the AboutHandler() class exists already
handlerService.activateHandler("com.example.mycommand", 
    new AboutHandler());

// prepare execution of command
ParameterizedCommand cmd =
  commandService.createCommand("com.example.mycommand", null);

// check if the command can get executed
if (handlerService.canExecute(cmd)){
  // execute the command
  handlerService.executeHandler(cmd);
} 

9. Learn more about Eclipse 4 RCP development

I hope you enjoyed this tutorial. You find this tutorial and much more information also in the Eclipse 4 RCP book from this author.

10. About this website

11. Links and Literature

http://wiki.eclipse.org/E4 Eclipse E4 - Wiki

Eclipse RCP

Eclipse EMF

Dependency Injection

List of the available services and their description

http://wiki.eclipse.org/E4/Contexts#Available_Services_in_Eclipse_e4