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

1. Eclipse platform services

1.1. What are Eclipse platform services?

The services provides by the Eclipse platform simplify the implementation of common tasks. These services can be accessed via dependency injection. The following table gives an overview of the available platform services, these will be covered later in detail.

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 a 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.

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

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

2. Selection service

2.1. Usage of the selection service

The ESelectionService service allows you to retrieve and set the user interface selection in each top-level window and part. This selection is stored under the IServiceConstants.ACTIVE_SELECTION context key.

2.2. Retrieving the selection service and setting the current selection

A client can get the selection service via dependency injection.

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

@Inject ESelectionService selectionService; (1)

// more code

viewer.addSelectionChangedListener(event -> { (2)
    IStructuredSelection selection = viewer.getStructuredSelection();
    selectionService.setSelection(selection.getFirstElement()); (3)
});
1 In this example you use field injection to retrieve the service
2 viewer is a JFace table viewer in this example
3 Sets the first selected element of the viewer as UI selection

2.3. Getting the selection

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

The selection can also be retrieved via dependency injection. For this, use the @Named annotation to specify the IServiceConstants.ACTIVE_SELECTION constant. The Eclipse framework ensures that selections are only injected if the request type fits to the selection.

The usage of dependency injection to retire the selection is demonstrated in the following coding.

@Inject
public void setTasks(@Optional
        @Named(IServiceConstants.ACTIVE_SELECTION) List<Task> tasks) { (1)
        // do something with the list of todos
}

@Inject
public void setTask(@Optional
        @Named(IServiceConstants.ACTIVE_SELECTION) Task task) { (2)
        // do something with the task
}
1 Method is called if the current selection is a List
2 Method is called if the current selection is a Task

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. It allows you to search for existing model elements, create news onces (completely or based on snippets).

This service can be accessed via dependency injection, as demonstrated via the following snippet.

`@Inject EModelService modelService;`

3.2. 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.vogella.tasks.ui.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());
    }
}

The following code demonstrates how you can access the current perspective for a part.

package com.vogella.tasks.ui.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.

3.3. Creating model elements

As the application model is interactive, you can dynamically create new model elements and add them to your application. For example you can add new parts to your application. This will be demonstrated in the exercises.

3.4. 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.5. 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.

3.6. Removing a model element

The deleteModelElement method EModelService allows to remove a model element from your application. It calls setToBeRendered(false) on the model element can removes it from this parent container.

4. Example for changing the application model

4.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++;
    }
}

4.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);

4.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.vogella.tasks.ui.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.vogella.tasks.ui/"
                + "com.vogella.tasks.ui.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.

5. Part service and editor like behavior

5.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.

5.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.

5.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);

5.4. Example: Switching perspectives

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

package com.vogella.tasks.ui.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);
    }
}

5.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

5.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.vogella.tasks.ui.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.vogella.tasks.ui.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.vogella.tasks.ui.partdescriptor.fileeditor");
        part.setLabel("New Dynamic Part");

         // the provided part is be shown
        partService.showPart(part, PartState.ACTIVATE);
    }
}

5.7. Showing Parts in categorized ElementContainer

In order to open and show a part in the application the EPartService.showPart(…​, …​) method is used.

By default MPartDescriptor are added to the last MElementContainer, which is found in the workspace, e.g., the one where usually the Console and Problems view reside.

But for MPartDescriptor elements a category can be defined, which can be used to specify a certain MElementContainer as container for a MPartDescriptor element by adding the defined category as tag to this container.

A category for a MPartDescriptor can be defined like this:

part descriptor category

In case a tag is applied to an element container for the part descriptor’s category the part descriptor will to added to this element container when the showPart method is invoked.

element container tag category
EPartService partService = getPartService();

partService.showPart("e4app.partdescriptor.categorizedpartdescriptor", PartState.ACTIVATE);

6. Implementing editor like behavior

6.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.

6.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.basic.MPart;
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
    MPart part;

    @PostConstruct
    public void createControls(Composite parent) {
        Button button = new Button(parent, SWT.PUSH);
        button.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                part.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(MPart part, TaskService todoService) {
    // save changes via TaskService for example
    todoService.saveTodo(todo);
    // save was successful
    part.setDirty(false);
}
Every part is responsible for saving itself. Hence every part which behaves like an editor must have one method annotated with @Persist.

6.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.vogella.tasks.ui.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);
    }
}

6.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. Command and Handler service

7.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.

7.2. Access to command and handler service

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

7.3. Example for executing a command

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

// create parameter for the command
// optional, can be null
Map<String, String> parameters = new HashMap<String, String>();
parameters.put(Constants.SEARCH_QUERY_ID, id);

ParameterizedCommand cmd =
    commandService.createCommand("com.example.mycommand", parameters);

// execute the registered handler for the command
handlerService.executeHandler(cmd);

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

8. Learn more and get support

This tutorial continues on Eclipse RCP online training or Eclipse IDE extensions with lots of video material, additional exercises and much more content.