Home Tutorials Training Consulting Products Books Company Donate Contact us









NOW Hiring

Quick links

Share

Using the Eclipse event system within your application. This tutorial gives an overview about the event system of the Eclipse application platform.

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. Communication within your Eclipse application

2.1. Event based communication

In your application you frequently have the need to communicate between application components. If this communication is loosely coupled, you can develop and test the components in isolation, which improves software qualify.

This can be archived by the subscriber/ publisher model implemented as an event system. Software components can register for certain events. Components can send such events. The event system ensures that all registered components receive the event they registered for.

2.2. The event bus of Eclipse

For this purpose the Eclipse platform provides a global event based communication system, called the event bus.

Any software component which has access to the event system can send out arbitrary events as depicted in the following graphic.

Sending out events with an event broker

The Eclipse platform makes sure that registered components receive the messages. The Eclipse platform uses this event system for the internal communication.

2.3. Event service

The Eclipse framework provides the event service for event communication. This service can be accessed via dependency injection based on the IEventBroker interface. This communication service can also be used to communicate between your own application components.

The Eclipse event service is based on the OSGi EventAdmin service.

2.4. Required plug-ins to use the event service

The following plug-ins are required to use the event service functionality:

  • org.eclipse.e4.core.services

  • org.eclipse.osgi.services

2.5. Sending out events

The event service can be injected via dependency injection.

@Inject
private IEventBroker eventBroker;

The following code examples assume that you have a class named MyEventConstants. This class contains a static final field (constant) to define a string.

The event service allows to notify the registered components. This can be done asynchronously or synchronously.

@Inject IEventBroker broker;

...
// asynchronously
// sending code is not blocked until the event has been delivered
broker.post(MyEventConstants.TOPIC_TODO_NEW, todo);

//synchronously sending a todo
//the calling code is blocked until delivery

broker.send(MyEventConstants.TOPIC_TODO_NEW, newTodo);

You can now send arbitrary Java objects or primitives through the event bus.

2.6. Registration for events for receiving events

You can use dependency injection to register and respond to events. In this case the Eclipse framework automatically removes all event subscriptions when the model class is disposed.

The @EventTopic and @UIEventTopic annotations tag methods and fields that should be notified on event changes. The @UIEventTopic ensures the event notification is performed in the user interface thread.

import java.util.Map;

// MyEventConstants.TOPIC_TODO_UPDATE is
// a String constant

@Inject
@Optional
private void subscribeTopicTodoUpdated
        (@UIEventTopic(MyEventConstants.TOPIC_TODO_UPDATE)
                Todo todo) {
        if (viewer!=null) {
            // this example assumes that you do not use data binding
                todoService.getTodos(viewer::setInput);
        }
}

An object can also register directly an instance of the org.osgi.service.event.EventHandler via the IEventBroker.subscribe() method. To unsubscribe use the unsubscribe() method.

Using dependency injection for subscribing should be preferred compared to the direct subscription. This way the framework handles the listener registration and de-registration automatically for you. But sometimes it is useful to control when to listening to events, for, example when an event should only received once.

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;

public class LazyLoadingAddon implements EventHandler {

        @Inject
        private IEventBroker broker;

        @PostConstruct
        public void lazyLoadInContributorPerspective() {
                broker.subscribe(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT, this);
        }

        @Override
        public void handleEvent(Event event) {
                Object property = event.getProperty(UIEvents.EventTags.NEW_VALUE);

                if (!(property instanceof MPerspective)) {
                        return;
                }

                MPerspective perspective = (MPerspective) property;

                // only load the data, when this particular perspective is selected
                if ("com.example.speciallazyloaded.perspective".equals(perspective.getElementId())) {

                        // loading data...

                        // unsubscribe afterwards, so that the loading is only done once
                        broker.unsubscribe(this);
                }
        }

}

2.7. Which objects should be send out?

The event system allows sending and receiving objects of an arbitrary type. Often it is sufficient to send the desired object through an event. But it is good practice to use a map like structure for sending events, i.e., to have common interface for events.

2.8. Subscribing to sub-topics

You can subscribe to specific topics or use wildcards to subscribe to all sub-events. Sub-events are separated by /. The following example code defines string constants including the TOPIC_TODO_ALLTOPICS constant. This constant can be used to register for all sub-events.

package com.example.e4.rcp.todo.events;
/**
 *
 * @noimplement This interface is not intended to be implemented by clients.
 *
 * Only used for constant definition
 */

public interface MyEventConstants {

        // topic identifier for all todo topics
        String TOPIC_TODO = "TOPIC_TODOS";

        // this key can only be used for event registration, you cannot
        // send out generic events
        String TOPIC_TODO_ALLTOPICS = "TOPIC_TODOS/*";

        String TOPIC_TODOS_CHANGED = "TOPIC_TODOS/CHANGED";

        String TOPIC_TODO_NEW = "TOPIC_TODOS/TODO/NEW";

        String TOPIC_TODO_DELETE = "TOPIC_TODOS/TODO/DELETED";

        String TOPIC_TODO_UPDATE = "TOPIC_TODOS/TODO/UPDATED";
}

2.9. Event system compared to Eclipse context

The IEventBroker is a global event bus and is unaware of the IEclipseContext hierarchy. The IEventBroker service supports sending event information without knowing who is receiving it. Interested classes can register for events without knowing who is going to provide them. This is known as the whiteboard pattern and this pattern supports the creation of very loosely coupled application components.

The disadvantage is that it is a global bus, i.e. there is no scoping of the events. Publishers have to ensure they provide enough information in the topic and the send object to allow subscribers to discriminate and decide that the particular event is applicable to a subscriber.

2.10. Asynchronous processing and the event bus

Your threads can use the IEventBroker to send event data. The event listeners are called by the framework. If the method is annotated with the UIEventTopic annotation, it is called in the main thread.

private static final String UPDATE ="update";

// get the IEventBroker injected
@Inject
IEventBroker broker;

// somewhere in you code you do something
// performance intensive

button.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(SelectionEvent e) {
                                Runnable runnable = new Runnable() {
                                        public void run() {
                                                for (int i = 0; i < 10; i++) {
                                                        try {
                                                                Thread.sleep(500);
                                                        } catch (InterruptedException e) {
                                                                e.printStackTrace();
                                                        }
                                                        // send out an event to update
                                                        // the UI
                                                        broker.send(UPDATE, i);
                                                }
                                        }
                                };
                                new Thread(runnable).start();
                        }
                });



// more code
// ....


// get notified and sync automatically
// with the UI thread

@Inject @Optional
public void  getEvent(@UIEventTopic(UPDATE) int i) {
        // text1 is a SWT Text field
        text1.setText(String.valueOf(i));
        System.out.println(i);
}

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

4. About this website

5.1. 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-2016 vogella GmbH. Free use of the software examples is granted under the terms of the EPL License. This tutorial is published under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany license.

See Licence.