UI Plugin Services - BloomReach Experience - Open Source CMS

This article covers a Hippo CMS version 10. There's an updated version available that covers our most recent release.

12-05-2015

UI Plugin Services

Introduction

Each frontend plugin in itself is an independent component. All frontend plugins together however form a complete application. Within such an application context, plugins are no longer independent, and need to communicate with each other. One plugin might cause an event, on which certain other plugins might react (by performing whatever action). Yet other plugins may stay unaffected.

Sharing Models

A very simple communication mechanism is provided in the form of sharing models between plugins. When one plugin provides an IModelService (a Perspective will do this for you), others can use it to obtain their IModel and to receive "model change" notifications.

The straightforward way to use this mechanism is to subclass the RenderPlugin and override the onModelChanged() method. Whenever the model changes in one of the other plugins, it will be invoked. If the plugin needs to be redrawn in response to the model update, call redraw().

This occurs for example when the page contains a BrowserPlugin. When a node is selected on the (JCR) tree, other plugins are notified. This mechanism is e.g. used to show workflow plugins for nodes that have a workflow.

public class ExamplePlugin extends RenderPlugin {

    public ExamplePlugin(IPluginContext context, IPluginConfig config) { 
       super(context, config);
    } 

    @Override
    public void onModelChanged() { 
         // repaint the plugin when the model has changed. 
        redraw(); 
    }
}

Advanced Communication Patterns

More advanced interactions between plugins can be achieved by registering services and/or trackers. Any object that implements  IClusterable can be registered as a service. A number of patterns have emerged in the use of this basic premise.

Whiteboard Pattern

In the whiteboard pattern, the basic principle of "don't call us, we'll call you" is applied to a client/server situation. When several clients need to be notified, they don't register themselves directly with the server. Instead, they register a listener service with the plugin context. When the clients must be notified, the server retrieves the list of listeners and notifies them.

This pattern is actually used by the model sharing implementation. Each plugin that wants to be notified of model changes registers an  IModelListener. The  ModelService uses these listener services whenever a model changes.

Decorator Pattern

Sometimes it is desirable to extend services with extra interfaces. An example is the  ITitleDecorator; it is used by the Perspective to provide a title to display for the tabbed panel.

Available Services

Some common services are provided by the framework and can be retrieved under well-known names.

IDialogService

This service gives plugins, even those without any visual parts, the possibility to display modal dialogs. AbstractRenderService sub-classes (such as RenderPlugins) can use the #getDialogService() method to locate the service.  Other usages can leverage the plugin context with the service name  IDialogService.class.getName(). Showing a dialog is therefore as simple as:

IDialogService dialogService =
       context.getService(IDialogService.class.getName(), IDialogService.class);
dialogService.show(new ExampleDialog(context, flagService));

IPluginConfigService

The  IPluginConfigService makes configurations of clusters of plugins available. It can be found under the name  IPluginConfigService.class.getName() . It can be used to dynamically instantiate clusters of plugins.

As an example, consider the case of multiple editors in the CMS. Each editor has its own set of plugin instances and its own (node) model. To satisfy this last requirement, each editor uses a separate  ModelService, configured by the plugin that instantiates editors.

Did you find this page helpful?
How could this documentation serve you better?
On this page
    Did you find this page helpful?
    How could this documentation serve you better?