Discovery of Remote Services
There's been some more work on examples...this time an example that combines the use of the ECF discovery API with the use of the ECF remote services API. This makes it possible to automatically discover and remotely access arbitrary OSGi services.
Here is a screen shot of the ECF service discovery view, after having discovered a remote service:
Note that in this case the discovery is being done by the ECF zeroconf/bonjour/rendevous provider. The UI and the code that uses the discovery, is, however, discovery protocol independent, so that it can (and will) also be used with SLP discovery...with no changes to the middleware or application code.
Here is an expanded view of the info about the service provided by service host via the discovery API:
Now, the ECF discovery view UI has an extension point called 'serviceAccessHandler' that allows context menu contributions to be optionally added by extensions, based upon the discovered service info. For the client there is a serviceAccessHandler defined for the 'remotesvcs' type (defined in the schema here as extension point org.eclipse.ecf.discovery.ui.serviceAccessHandler) that presents the following when the user opens the context menu for the service
If the user is not already connected to the given service, then it allows the connection to be established as above. If already connected, however, the context menu presents options for invoking a remote 'getProperty' method (part of the Equinox EnvironmentInfo service)
This menu provides access to four different ways of invoking the 'getProperty' method remotely...and is just an example UI (a better UI for selecting a remote method and providing parameters is forthcoming). The four ways are
- (s) = synchronously -- block calling thread until service host responds
- (a) = asynchronously -- calling thread does not block and result is provided via notification to a listener
- (f) = future -- calling thread does not block, and an instance of IAsynchResult is returned immediately Receiver can inspect IAsynchResult for completion.
- (p) = proxy -- calling thread calls a proxy instance of service interface) with normal call/return semantics
These access methods are made available via the ECF IRemoteService.
Note that the proxy can also be accessed directly in the OSGi service registry via BundleContext.getServiceReference() or a ServiceTracker. In this way, if complete API transparency is desired, then it can be done this way.
So, if the proxy is selected it brings up an example UI for getting the relevant parameter
The remote call is then actually made, and presents the result in another ugly UI (the result is the 'user.dir' directory on the remote service host)
Here's another example, just to show that the key provided as a parameter to the getProperty call is doing it's thing
Note that the client gets/receives all the information necessary to connect to and access the remote service via the service discovery (i.e. via the ECF discovery API)...the user doesn't have to provide any extra information in order to find and use the remote service. Further, the middleware and UI code is completely transport independent...allowing the use of ECF generic, r-OSGi, JMS, javagroups, XMPP, or other/proprietary providers without the need to modify the middleware and/or UI.
This example consists of three bundles
- org.eclipse.ecf.examples.remoteservices.common. This bundle has the service interface class org.eclipse.ecf.examples.remoteservices.common.IRemoteEnvironmentInfo. Note that this interface is very much like the Equinox EnvironmentInfo service, and essentially all the service host implementation does is turn around and call the local EnvironmentInfo service.
- org.eclipse.ecf.examples.remoteservices.server. An extremely simple Equinox-based server that registers the remote service, publishes the service discovery info, and implements the remote requests. Source is here.
- org.eclipse.ecf.examples.remoteservice.client. A very simple client that implements the discovery view extension point. Here is the class implementing the serviceAccessHandler. This also has the ugly UI code for getting the getProperty parameter and showing the result.
Note that the client and server processes do not need each other's bundles...they only need the org.eclipse.ecf.examples.remoteservices.common bundle.
Here are the project set files for these three bundles