[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[ecf-dev] remote service callbacks

Hi Folks,

I want to describe a little work that I've been doing with OSGi remote services.

One of the things that remoting makes somewhat complicated is callbacks. In local/non-remote programs callbacks are easy...e.g. in Eclipse, for example, the IProgressMonitor is used as a callback to many methods that have the potential to block...e.g.:

IResource.copy(IPath destination,  boolean force, IProgressMonitor monitor)

The IProgressMonitor is a callback whose methods will be called as progress is made during the file/directory/workspace copy.

Another use of callbacks is the OSGi 'whiteboard' service pattern, where services are registered and then called by some caller under the appropriate conditions. A good example of this is the OSGi EventHandler interface [1], where receivers of events implement and register an EventHandler, and then the EventAdmin delivers a method (handleEvent) when an appropriate event is present.

I've recently been working on using OSGi RS for remote management [2]. This API can be used to remotely manage many aspects of an OSGi runtime (e.g. the framework, bundles, services, scr, applications, p2, ecf rsa, ecf core, others...). There are many cases, however, where it would be useful to be able allow a callback to be used to update the remote state of a managed framework. For example, consider remotely managing the set and state of the bundles running in a framework. First, one needs to get the current state of the remote bundles so that it can be presented. Soon however, that state can/could be made obsolete (e.g a bundle(s) get started and change their state from resolved to active). At that point the remote management agent's presentation of the state of at least some of the bundles is out of date and has to be refreshed. One way to refresh is to periodically poll the remote framework for it's current state, and update the state information once received. This has disadvantages, however, as polling can be both inaccurate and inefficient when the state is changing relatively rapidly.

Another way is to allow the framework to send 'update' events to the remote manager when the state changes. For example, the BundleContext allows one to iterate over all of the bundles and figure out their state. It's also possible, however, to register a BundleListener and be called back by the framework when a bundle changes it's state.

For remote management, it would be nice if a remote manager could get the initial state of all the bundles in a remote framework, and then receive events as the bundles changed state. This would allow it to keep it's information about the remotely running framework synchronized with the framework's actual state, without having to constantly poll for the current state. It would also be a much more efficient way (in terms of bandwidth usage) to keep the distributed state synchronized with theb actual state.

Now, in the org.eclipse.ecf.mgmt.framework bundle is an IBundleManager service [3]. This service allows a remote consumer to get the current state of all (or some) of the bundles in a framework. I've been working on the mechanism for associating this service with a 'callback' service called IBundleEventHandler [4]. Using RSA, it's possible to associate the import (by consumer) of an IBundleManager service with the export (by consumer) of an IBundleEventHandler...along with subsequent import of the IBundleEventHandler by the IBundleManager service host.

The sequencing is this:

1.  Framework A (being remotely managed) exports an IBundleManager

2. Framework B (remote manager) imports IBundleManager and calls remote method to get initial state

3.  Framework B *exports* IBundleEventHandler

4. Framework A *imports* IBundleEventHandler and calls handleBundleEvent to send state updates as they occur


This results in the following two remote service relationships

A B

IBundleManager host           <------- IBundleManager consumer

IBundleEventHandler consumer  ---->      IBundleEventHandler host

In effect the IBundleEventHandler is a callback for the IBundleManager remote service, allowing bundle state change events to be delivered to the remote manager as they occur allowing the bundlemanager consumer to keep its state up-to-date.

To implement this association, I've created two classes, one for the 'A' side called ServiceExporterCallbackImporter and one for the 'B' side called ServiceImporterCallbackExporter [5]. Note that these aren't bound in any way to IBundleManager/IBundleEventHandler specifically, and so can be used for other kinds of remote service<->callback relationships. But I have been testing the use of these classes specifically with IBundleManager and IBundleEventHandler for monitoring and dynamically updating a 'remote bundles view'...i.e. an Eclipse view that allows one to monitor the set of bundles in a remote framework, start/stop bundles, etc. It's all working quite well so far.

The use of this callback relationship between remote services can only be done if *both* A and B are able to both import and export remote services. This isn't by default provided with some Remote Service providers, however, because they might be asymmetric and unable to be both an importer and an exporter. For example, most rest-based clients (e.g. Jax-RS, etc [7]) are unable to be remote service exporters, as they are only http clients, and not http servers. This makes it impossible to create the callback relationship between two remote services as above with these rest providers.

But many of ECF's providers *do* support both A and B being able to export and import remote services (e.g. rosgi, generic, jms, mqtt, jgroups, others), and so can support this notion of remote service callbacks without modification (I've been testing on ECF generic and mqtt providers to start).

I'm going to next use this codebase to try a remote IServiceManager/IServiceEventHandler structure for managing services. Then my intention is to also use it for managing scr/ds, and others. Also testing it out on other appropriate distribution providers (jms, jgroups, etc).

I believe that this approach will be very helpful with remotely managing IoT frameworks in particular...as IoT frameworks (e.g. Kura) need some way to remotely monitor and manage the various parts and services dynamically, efficiently without a required binding to a particular networking transport.

Any thoughts/comments appreciated. I'm going to write something more in the wiki about this (with demo/pictures, etc) as soon as I am able.

Scott

[1] https://osgi.org/javadoc/r4v42/org/osgi/service/event/EventHandler.html

[2] https://github.com/ECF/OSGIRemoteManagement

[3] https://github.com/ECF/OSGIRemoteManagement/blob/master/bundles/org.eclipse.ecf.mgmt.framework/src/org/eclipse/ecf/mgmt/framework/IBundleManager.java

[4] https://github.com/ECF/OSGIRemoteManagement/blob/master/bundles/org.eclipse.ecf.mgmt.framework/src/org/eclipse/ecf/mgmt/framework/IBundleEventHandler.java

[5] https://github.com/ECF/OSGIRemoteManagement/tree/master/bundles/org.eclipse.ecf.osgi.services.remoteserviceadmin.callback/src/org/eclipse/ecf/osgi/services/remoteserviceadmin/callback

[6] https://github.com/ECF/OSGIRemoteManagement/tree/master/plugins/org.eclipse.ecf.remoteservice.ui.bundleview

[7] https://wiki.eclipse.org/Distribution_Providers