Home Tutorials Training Consulting Products Books Company Donate Contact us









Online Training

Quick links

Share

This tutorial explains how to contribute to the Eclipse application model via other plug-ins.

1. Prerequisites

The following assumes that you have already basic Eclipse RCP development experience. See the http://www.vogella.com/tutorials/Eclipse4RCP/article.html - Eclipse RCP Tutorial for details.

2. Contributing to the application model

2.1. Modularity support for the application model

Eclipse applications are based on the modularity of plug-ins. Every plug-ins can contribute to the application model.

Typical, the initial structure of the application model is described in file called Application.e4xmi. Model contributions can be static or dynamic:

  • Static contributions are contributed via text files. These extensions are called fragments or model fragments.

  • Dynamically contributions are contributed via Java classes. These extensions are called processors or model processors.

These model contributions are registered via the org.eclipse.e4.workbench.model extension point. This extension point is defined in the org.eclipse.e4.ui.workbench plug-in.

The model contributions are read during startup and are used to build the runtime application model.

2.2. Constructing the runtime application model

2.2.1. User Changes

Changes during runtime, are written back to the model. For example, if the user positions a part into another stack via drag and drop.

If the Eclipse application is closed, theses changes are recorded and saved in the workbench.xmi file. This file is located in the .metadata/.plugins/org.eclipse.e4.workbench folder.

User changes can be deleted at start of your application via the clearPersistedState parameter as a launch parameter. In most cases this is undesired behavior for an exported application and only used during development.

2.2.2. Runtime application model

At runtime the application model of an Eclipse application consists of different components:

  • Application model - By default defined via the Application.e4xmi file

  • Model contributions - Based on fragments and processors

  • User changes - Changes the user did to the user interface during his last usage

These different components of the runtime application model need to be combined.

The Eclipse platform creates the runtime application model based on the initial application model(Application.e4xmi) and applies the model contributions to it. User deltas are applied afterwards. If these deltas do not apply anymore, e.g., because the base model has changed, they will be skipped.

The deltas are applied to the model based on the IDs of the user interface component.

The automatic persistence of the application model is misleading during development. The developer adds a new part and this part is not visible after startup of the application because Eclipse assumes that the user closed it in an earlier session. Use the clearPersistedState parameter to avoid the processing of user changes at startup.

Comparison with Eclipse 3.x

The programming model of Eclipse 3.x primarily uses extension points to define contributions to the application. These extensions define new parts, new menus, etc. This approach is no longer used in pure Eclipse 4 RCP applications. All contributions are made via fragments or processors. If your are using the compatibility layer, Eclipse stills supports plug-in based contributions.

3. Model fragments

A model fragment is a file which typically ends with the .e4xmi extension. It statically specifies model elements and the location in the application model to which it should be contributed.

For example, a fragment can contribute a new menu containing several new menu entries.

The e4 tools project provides a wizard and an editor for model fragments.

The application model editor also allows you to extract a subtree into a new or existing fragment. Select a model element, right click on it and select Extract into a fragment from the context menu.

3.1. How to define model fragments extension elements

In fragments you contribute to an existing model element. You also have to specify the Featurename to which you want to contribute. A Featurename is a direct link to the structure of the application model.

The following table lists some Featurename values and their purposes.

Table 1. Contribution, Featurename and Element id
You want to contribute to a Featurename Element Id

Command to the application

commands

ID of your application

Handler to the application

handlers

ID of your application

New MenuItem / HandledMenuItem to existing menu

children

ID of the menu

New menu to the main menu of the window

children

ID of your main menu

New Part to existing PartStack

children

ID of your PartStack

3.2. Defining the model element which gets extended

If you want to contribute to an element of the application model you can:

  • specify the ID of the element to which you are contributing

  • use an XPath expression to describe the model element which should get extended

The following table gives several examples how you can use XPath expressions to define the model element you want to extend.

Table 2. Sample XPaths for the Application Model
XPath Element in Application Model

xpath:/

The slash (/) always addresses the root element of an XML file, which always is the MApplication element.

xpath://mainMenu

Contribute to the main menu.

xpath://mainMenu/children

Contribute to all children of the main menu, e.g. to every menu in it.

xpath://mainMenu/*[1]

Contribute to the first child of the main menu. In most applications this would be the menu:File menu.

xpath://mainMenu/[@[local-name()='type' and .='menu:Menu']]

Contribute to the first Menu of the main menu. This xpath is more detailed than the one above since it also requires that the main menu child is of type menu:Menu. In most application this would be the menu:File menu.

xpath://trimBars[@side="Bottom"]

Contribute to the bottom trimbar.

xpath://trimBars[not(@side)]

Contribute to the top trimbar. When the MTrimBar is on top the side attribute is omitted, therefore not(@side) is used.

xpath://children[@*[local-name()='type' and .='basic:Part']]

Contribute to a MPart.

xpath://children[@*[local-name()='type' and .='basic:Part']][./tags = 'Editor']

Contribute to a MPart which is tagged with the Editor tag.

A nice tool for evaluating XPaths is the Eclipse XPath evaluation plug-in.

Eclipse XPath plugin in the marketplace

3.3. Position of new model elements

Fragments define the desired position of new model elements via the Position in List attribute. The following values are allowed:

Table 3. Position in list
Value Description

first

Positions the element on the beginning of the list.

index:theIndex

Places the new model elements at position theIndex. Example: index:0

before:theOtherElementsId

Places the new model elements before the model element with the ID theOtherElementsId.

after:theotherelementsid

Places the new model elements after the model element with the ID theotherelementsid.

Fragments of independent plug-ins are processed in the order of the dependencies in the MANIFEST.MF file. Therefore, first or index might not always result in the desired outcome.

4. Model processors

A processor allows contributing to the model via program code. This enables the dynamic creation of model elements during the start of the application.

5. Exercise: Contributing menus via model fragments

In this exercise you create a model fragment to contribute a menu entry, a command and a handler to your application model.

5.1. Create a new plug-in

Create a simple plug-in project called com.example.e4.rcp.todo.contribute. The following description abbreviates the plug-in name to the contribute plug-in.

5.2. Add the dependencies

In the MANIFEST.MF file, add the following plug-ins as dependencies to your contribute plug-in.

  • org.eclipse.core.runtime

  • org.eclipse.swt

  • org.eclipse.jface

  • org.eclipse.e4.core.di

  • org.eclipse.e4.ui.workbench

  • org.eclipse.e4.ui.di

5.3. Create a handler class

Create the com.example.e4.rcp.todo.contribute.handlers package and the following class.

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

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Shell;

public class OpenMapHandler {

    @Execute
    public void execute(Shell shell) {
        MessageDialog.openInformation(shell, "Test", "Just testing");
    }
}

5.4. Create a model fragment

Use the fragment wizard from the e4 tools project to create a new model fragment via the File ▸ New ▸ Other…​ ▸ Eclipse 4 ▸ Model ▸ New Model Fragment menu entry.

Creating fragments with the wizard

Select the contribute plug-in as the container and use fragment.e4xmi as the name for the file.

Creating fragments with the wizard

Press the Finish button.

5.5. Validate that the fragment is registered as extension

The fragment creation wizard also adds the org.eclipse.e4.workbench.model extension to your contribute plug-in. To review this open the plugin.xml file.

If the plugin.xml file is missing, open your MANIFEST.MF file. Select the Overview tab and click on the Extensions link. This shows the Extensions tab in the editor and once you add an extension in this tab the plugin.xml file is generated.

On the Extensions tab validate that you have an entry similar to the following screenshot.

Adding the fragment to the extensions

If the entry in the plugin.xml is missing you can create it by clicking on the Add…​ button. Afterwards add a new extension for the org.eclipse.e4.workbench.model extension point. Once this has been created, use the a right mouse click to add a fragment to the extension.

The resulting plugin.xml file should look similar to the following code.

<?eclipse version="3.4"?>
<plugin>
   <extension
         id="modelContribution"
         point="org.eclipse.e4.workbench.model">
      <fragment
            uri="fragment.e4xmi">
      </fragment>
   </extension>
</plugin>

5.6. Adding model elements

Open the fragment.e4xmi file in its editor. Select the Model Fragments node and press the Add…​ button.

Adding a model fragment

Use com.example.e4.rcp.todo.application as the Element ID. This is the ID of the Application model element in your Application.e4xmi file.

You need to define to which feature you will be adding to. For Featurename, specify the value commands. Make sure you have the Model Fragment selected and use the Add…​ button to add a Command to your model fragment.

Adding a model fragment

Use com.example.e4.rcp.todo.contribute.command.openmap for the ID field and Open Map for the Name field.

Adding a command to the model fragment

Create a new model fragment for the handler. The Element ID is again your application ID, the Featurename is handlers.

Add a Handler to this model fragment.

Adding a handler to the model fragment

Use com.example.e4.rcp.todo.contribute.handler.openmap as ID for the handler. Point to the Open Map command and the OpenMapHandler class.

Adding a handler to the model fragment

Add another Model Fragment to contribute a new menu to your application model. Contribute to the main menu of your Application.e4xmi. If you followed the earlier exercises correctly this should be the org.eclipse.ui.main.menu ID. The Featurename is children.

Adding a fragment for the menu
Ensure in your Application.e4xmi file that you are using the same ID for your menu in your application. The following screenshot highlights this entry.
Adding a fragment for the menu

In your fragment.e4xmi file add a Menu with the following attributes:

  • ID: com.example.e4.rcp.todo.contribute.menu.map

  • Label:_Map_

Adding a menu entry
Adding a menu entry

Add a HandledMenuItem which points to your new command. The process of defining these entries is the same as defining menus in the Application.e4xmi file. The created entry should be similar to the following screenshot.

Adding a menu item to the menu

5.7. Update the product configuration (via the feature)

Add the contribute plug-in to your com.example.e4.rcp.todo.feature feature.

5.8. Validating

Start your application.

Ensure that you added this new plug-in to your feature and saved the changes. Remember to start via the product to update the launch configuration.

You should see the new Map entry in the application menu. If you select this entry a message dialog opens.

If the menu entry is not displayed, ensure that your IDs are correctly entered. Also ensure that you either use the clearPersistedState flag or clear the workspace data in your Launch configuration.

5.9. Exercise: Contributing a part

This exercise is optional.

Define a new model fragment which contributes a part to an existing PartStack. Use the ID of an existing PartStack and use children as FeatureName.

6. Exercise: Contributing a part descriptor via model fragments

In this exercise you create a model fragment to contribute a part descriptor.

6.1. Create a new plug-in

Create a simple plug-in project called com.vogella.rcp.contribute.parts. The following description abbreviates the plug-in name to the contribute.parts plug-in.

6.2. Add the dependencies

In the MANIFEST.MF file, add the following plug-ins as dependencies to your contribute.parts plug-in.

  • org.eclipse.core.runtime

  • org.eclipse.swt

  • org.eclipse.jface

  • org.eclipse.e4.core.di

  • org.eclipse.e4.ui.workbench

  • org.eclipse.e4.ui.di

6.3. Create a part class

Create the following class.

package com.vogella.rcp.contribute.parts;

import javax.annotation.PostConstruct;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;

public class AdditionalInformationPart {
    @PostConstruct
    public void postConstruct(Composite parent) {
        Text text = new Text(parent, SWT.BORDER | SWT.MULTI);
    }
}

6.4. Create a model fragment

Use the fragment wizard to create a new model fragment via the File ▸ New ▸ Other…​ ▸ Eclipse 4 ▸ Model ▸ New Model Fragment menu entry.

Creating fragments with the wizard

Select the contribute.parts plug-in as the container and use fragment.e4xmi as the name for the file.

Creating fragments with the wizard

Press the Finish button.

6.5. Validate that the fragment is registered as extension

The fragment creation wizard also adds the org.eclipse.e4.workbench.model extension to your contribute plug-in. To review this open the plugin.xml file.

If the plugin.xml file is missing, open your MANIFEST.MF file. Select the Overview tab and click on the Extensions link. This shows the Extensions tab in the editor and once you add an extension in this tab the plugin.xml file is generated.

On the Extensions tab validate that you have an entry similar to the following screenshot.

Adding the fragment to the extensions

If the entry in the plugin.xml is missing you can create it by clicking on the Add…​ button. Afterwards add a new extension for the org.eclipse.e4.workbench.model extension point. Once this has been created, use the a right mouse click to add a fragment to the extension.

The resulting plugin.xml file should look similar to the following code.

<?eclipse version="3.4"?>
<plugin>
   <extension
         id="modelContribution"
         point="org.eclipse.e4.workbench.model">
      <fragment
            uri="fragment.e4xmi">
      </fragment>
   </extension>
</plugin>

6.6. Adding model elements

Open the fragment.e4xmi file in its editor. Select the Model Fragments node and press the Add…​ button.

Use xpath:/ as extended element id and descriptors as Feature name.

Adding a part descriptor 1

Now use the right mouse menu to add a part descriptor.

Adding a part descriptor 2

Switch to the Supplementary tab and add the following tag:

  • View

Adding a part descriptor 2

The View tag ensures that the Eclipse IDE accepts this part descriptor as valid view, if you use this plug-in in the Eclipse IDE. For pure e4 RCP applications this flag is not needed.

TheDo not forget to press the Add button, after you entered the text.

6.7. Update product

Add the new plug-ins to your feature and start via the product file. Ensure that your part descriptor is present, for example, via the model spy.

The pluig-in can be used to extend a pure e4 RCP application or the Eclipse IDE. In the Eclipse IDE you can open the additional part via Window ▸ Show View ▸ Other…​ dialog.

7. Exercise: Implementing a model processor

In this exercise you replace an existing menu entry with another menu entry.

7.1. Enter the dependencies

Continue to use the com.example.e4.rcp.todo.contribute plug-in for this exercise.

In the MANIFEST.MF, add the following plug-ins as dependencies to your contribute plug-in.

  • org.eclipse.e4.ui.services

  • org.eclipse.e4.core.contexts

  • org.eclipse.e4.ui.model.workbench

7.2. Create the Java classes

Create the following dialog and handler classes.

package com.example.e4.rcp.todo.contribute.dialogs;

import javax.inject.Inject;
import javax.inject.Named;

import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

public class ExitDialog extends Dialog {
    @Inject
    public ExitDialog(@Named(IServiceConstants.
            ACTIVE_SHELL) Shell shell) {
        super(shell);
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        Label label = new Label(parent, SWT.NONE);
        label.setText("Closing this application may result in data loss. "
                + "Are you sure you want that?");
        return parent;
    }

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

import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.workbench.IWorkbench;
import org.eclipse.jface.window.Window;

import com.example.e4.rcp.todo.contribute.dialogs.ExitDialog;

public class ExitHandlerWithCheck {
    @Execute
    public void execute(IEclipseContext context, IWorkbench workbench) {
        ExitDialog dialog = ContextInjectionFactory.
                make(ExitDialog.class, context);
        if (dialog.open() == Window.OK) {
            workbench.close();
        }
    }
}

Create the model processor class. This class removes all menu entries which have "exit" in their ID from the menu with the org.eclipse.ui.file.menu ID. It also adds a new entry.

package com.example.e4.rcp.todo.contribute.processors;

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

import javax.inject.Inject;
import javax.inject.Named;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.model.application.ui.menu.MDirectMenuItem;
import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
import org.eclipse.e4.ui.workbench.modeling.EModelService;

import com.example.e4.rcp.todo.contribute.handlers.ExitHandlerWithCheck;

public class MenuProcessor {

    // the menu is injected based on the parameter
    // defined in the extension point
    @Inject
    @Named("org.eclipse.ui.file.menu")
    private MMenu menu;

    @Execute
    public void execute(EModelService modelService) {
        // remove the old exit menu entry
        if (!menu.getChildren().isEmpty()) {
            List<MMenuElement> list = new ArrayList<>();
            for (MMenuElement element : menu.getChildren()) {
                // use ID instead of label as label is later translated
                if (element.getElementId() != null) {
                    if (element.getElementId().contains("exit")) {
                        list.add(element);
                    }
                }
            }
            menu.getChildren().removeAll(list);
        }

        // now add a new menu entry
        MDirectMenuItem menuItem = modelService.createModelElement(MDirectMenuItem.class);
        menuItem.setLabel("Another Exit");
        menuItem.setContributionURI("bundleclass://"
                + "com.example.e4.rcp.todo.contribute/"
                + ExitHandlerWithCheck.class.getName());
        menu.getChildren().add(menuItem);
    }
}

Ensure that your menu entry in the Application.e4xmi file labeled with Exit, contains exit in its ID.

7.3. Register processor via extension

In your contribute plug-in register your processor via the org.eclipse.e4.workbench.model extension.

processor04

Right-click on the processor and select New ▸ element. The value from the ID parameter is the ID of the model element which is injected into your processor class. Use org.eclipse.ui.file.menu as id* parameter.

processor10

This assumes that you used org.eclipse.ui.file.menu as ID for your File menu in the main application model. The ID of the element defined in the extension point must match the @Named value in the processor. If such an element is not found it is not injected into the processor.

7.4. Validating

Start your application. In the model fragment exercises, the contribute plug-in was already added to your product.

Ensure that the existing Exit menu entry is removed and your new menu entry with the Another Exit label is added to the file menu.

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

9. About this website

10.2. vogella GmbH training and consulting support

TRAINING SERVICE & SUPPORT

The vogella company provides comprehensive training and education services from experts in the areas of Eclipse RCP, Android, Git, Java, Gradle and Spring. We offer both public and inhouse training. Whichever course you decide to take, you are guaranteed to experience what many before you refer to as “The best IT class I have ever attended”.

The vogella company offers expert consulting services, development support and coaching. Our customers range from Fortune 100 corporations to individual developers.

Copyright © 2012-2018 vogella GmbH. Free use of the software examples is granted under the terms of the Eclipse Public License 2.0. This tutorial is published under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany license.

See Licence.