Jonas Helming, Maximilian Koegel and Philip Langer co-lead EclipseSource. They work as consultants and software engineers for building web-based and desktop-based tools. …
EMF Change Broker
5 min ReadThe EMF Change Broker
Many applications require to listen to entity objects. EMF supports this use case well, it allows to register listeners (“Adapters”) on every EObject, which get notified on every change of a model instance. The ready-to-use EContentAdpater can even be automatically subscribed to a complete tree of a model instance and is therefore notified about all changes in a model instance. However, when implementing Adapters in EMF, the developer typically has to filter the received events for relevance. As an example, you might want to listen only to changes on a certain entity type (“EClass”). Additionally, you ideally want to maintain as few EContentAdapter as possible, as they get notified about all changes, they can potentially slow down an application.
Both issues can be solved with the EMF ChangeBroker, a component of the EMF Client Platform.
The change broker is a stand-alone component, which can used in combination with any EMF model. There is a ready-to-use integration with the persistence layer of the EMF Client Platform, but the Change Broker can also be used stand-alone without other components of the EMF Client Platform.
The following diagram shows an overview of the ChangeBrokers’s architecture.
To keep the component independent of any concrete change notification mechanism, the Broker itself does only dispatch notifications to listeners. The notifications are delivered by a “NotificationProvider”. In a simple scenario, this can just be an EContentAdapter, which forwards all notification of a model instance to the Broker. NotificationProvider need to implement the interface:
org.eclipse.emf.ecp.changebroker.spi.NotificationProvider
There is a ready-to-use implementation for the EMF Client Platform persistence layer:
org.eclipse.emf.ecp.changebroker.provider.internal.ECPNotificationProvider
If you want to implement a custom NotificationProvider for your own persistence layer or for plain xmi files, there is a conviniance implementation, which you can use as a base class:
org.eclipse.emf.ecp.changebroker.spi.AbstractNotificationProvider
A simple NotificationProvider could for example just register an EContentProvider on the model to be notified about changes and to push them to the ChangeBroker. In this case, make sure, that the following methods of the AbstractNotificationProvider get called by your custom NotificationProvider:
- notify: When an element is changed. You need to pass the EMF Notifcation as a parameter
- canDelete: Before an element gets deleted. If this method return fale, a Listener has given a veto to the delete, so it should not be deleted
- preDelete: Before an element is deleted. Allows clean-up operations.
- postDelete: After an element is deleted
The reason, why delete events are handled separately is that EMF does not support delete events natively. If you delete an element, e.g. with a DeleteCommand, EMF will remove the cross-references and then remove the element from its parent. In this case, you would just receive remove notifcations. Those are not automatically delete events. An element, which is moved in the containment hierarchy would trigger a remove and subsequently an add event. If you want to listen to delete events, we recommend you implement an explicit service (or method) to call in your application and trigger the ChangeBroker in this method.
Finally, you need to register your NotificationProvider as an OSGi service, so it can be picked-up by the ChangeBroker. We recommend to use declarative service for this purpose.
Once the NotificationProvider is set-up, you can use the ChangeBroker and register listeners to it. The ChangeProvider itself is an OSGi service, too, so you can retrieve it using declarative services, the OSGi API or dependency injection (in Eclipse 4).
The Change Broker supports the following types of listeners, which can registered to it:
- ChangeObserver Is notified, when a change is done on the observed model instance. ChangeObserver can either listen to all changes of a model instance or only to changes on certain EAttributes, EReferences or EClasses. We provide a more detailed description in the next section.
- ReadOnlyChangeObserver Are notified as ChangeObserver, but they are not allowed to do any changes on the model.
- VetoableDeleteObserver Is notified, before a delete operation is executed. The observer can veto on the delete by returning “false”. In this case, the delete will be aborted and no other delete observer will be notified.
- PreDeleteObserver Is notified before a delete operation is executed. The element is not yet deleted, therefore, the context of the element can be accessed in the observer.
- PostDeleteObsever Is notified after a delete operation is executed. The element is deleted but can be accessed in the observer. The Broker provides a fine-grained API to register listeners for particular events. As an example, the following registration will notify the listener only on changes on the EClass “myEClass”:
changeBroker.subscribeToEClass(myObserver, myEClass)
Analogously, it is also possible to register an observer to certain EFeatures (EAttributes or EReferences)
changeBroker.subscribeToFeature(observer, myEStructuralFeature);
Finally, you can also subscribe to a subtree of your model, more precisely to all changes which are done to an element of a certain EClass and its sub elements using:
changeBroker.subscribeToTree(observer, myEClass);
The ChangeBroker can also be turned off and on, in case you apply certain operations on a model instance, which should not trigger any notifications. As the ChangeBroker itself does not have any dependency except EMF, it can be used in various contexts and also without any other parts of the EMF Client Platform. We hope this component is of use for you. If you discover any issues or if you have feature requests, please use the newsgroup or the bug tracker to communicate those.