Jump to: navigation, search

Difference between revisions of "EIG:Getting Started with OSGi Remote Services"

(Getting Started with Using Declarative Services (DS) with Remote Services)
(No difference)

Revision as of 19:00, 10 March 2011

Adding ECF' OSGi Remote Services Implementation to Your Target Platform

See Installing OSGi Remote Services

Getting the Example Code

See here for instructions on retrieving the source for the hello examples (both programmatic and declarative services-based examples).

Defining a Service Interface

As with any OSGi service, local or remote, you must first define your service interface. Here is the 'hello' service interface defined in the org.eclipse.ecf.examples.remoteservices.hello bundle:

package org.eclipse.ecf.examples.remoteservices.hello;
public interface IHello {
	public String hello(String from);

There is a trivial implementation of the IHello interface in the org.eclipse.ecf.examples.remoteservices.hello.impl.Hello class in the org.eclipse.ecf.examples.remoteservices.hello bundle

Service Host: Registering the Remote Service

To distribute a remote service all that is required is to set some OSGi standard service properties and register the service via the OSGi service registry. When these service properties are present, the distribution system kicks in to distribute the service upon service registration.

Here, for example, is the code in the hello example host (class: org.eclipse.ecf.internal.examples.remoteservices.hello.host.HelloHostApplication in org.eclipse.ecf.examples.remoteservices.host bundle):

Properties props = new Properties();
// add OSGi service property indicated export of all interfaces exposed by service (wildcard)
// add OSGi service property specifying config
props.put(IDistributionConstants.SERVICE_EXPORTED_CONFIGS, containerType);
// register remote service
helloRegistration = bundleContext.registerService(IHello.class.getName(), new Hello(), props);

The first service property, i.e.:


is a required property that says that all the interfaces that are registered should be exported.

The second service property i.e.:

props.put(IDistributionConstants.SERVICE_EXPORTED_CONFIGS, containerType);

uses the OSGi config type property ("service.exported.configs") set to the value of the containerType variable. In this application, this variable is the ECF container type/container factory name for the desired provider. For example, for the ECF generic provider, this is set to 'ecf.generic.server'. For the ECF r-OSGi provider it is set to 'ecf.r_osgi.peer'. To use *any* other ECF remote services provider, all that's needed is to change this variable to the appropriate value.

The following line registers and automatically distributes the remote service

// register remote service
helloRegistration = bundleContext.registerService(IHello.class.getName(), new Hello(), props);
  1. The registration uses a new instance of the hello implementation class (i.e. new Hello()). As per the OSGi registerService contract, the IHello interface must be implemented by the object given in the second parameter.
  2. As described above, upon service registration the use of the standard remote service properties (props) means that a remote service implementation (in this case ECF) is automatically triggered to distribute the service. With ECF, this results in the following sequence
    1. An ECF container of the given containerType is created
    2. The container instance is used to register and distribute the remote service. This is done via the ECF Remote Services API
    3. The remote service is published for network discovery by the ECF Discovery API

Running the Example Hello Service Host

In the org.eclipse.ecf.examples.remoteservices.hello.host plugin are the following Eclipse product definition files:

products/Hello Service Host (edef,generic).product
products/Hello Service Host (zeroconf,generic).product
products/Hello Service Host(zeronconf,r-osgi).product
products/Hello Service Host (zookeeper,generic).product
products/Hello Service Host (zookeeper,r-osgi).product

These products all run the HelloHostApplication...and provide a different value for the containerType variable that appears in the code. As described above, the value of the containerType variable determines which provider is used to distribute the remote service.

To launch the generic host, for example, first double click on the Hello Service Host (generic).product definition file, to open the PDE product definition editor. Then in the product definition editor Overview tab, in the lower left, click on Launch and Eclipse application link to run or Launch an Eclipse application in Debug mode to debug.

Once run the following output should go to the console

<log warning>
Host: Hello Service Registered

At this point the service is available for remote discovery and usage by consumers/clients.

Service Consumer: Discovering and Using the Remote Service

In the example, the service consumer code is in the org.eclipse.ecf.examples.remoteservices.hello.consumer bundle. Specifically, there is a ServiceTracker used to track the remote service in the org.eclipse.ecf.internal.examples.remoteservices.hello.consumer.HelloConsumerApplication.

// Create ECF container of appropriate type. The container instance
// can be created in a variety of ways...e.g. via code like the line below, 
// via the new org.eclipse.ecf.container extension point, or automatically 
// upon discovery via the IProxyContainerFinder/DefaultProxyContainerFinder.  
// Create service tracker to track IHello instances that have the 'service.imported'
// property set (as defined by OSGi 4.2 remote services spec).
helloServiceTracker = new ServiceTracker(bundleContext,createRemoteFilter(), this);

This is all the client code that is required. Note that the remote service can be accessed in a variety of ways...e.g. by using a ServiceTracker (as above), by using the BundleContext.getServiceReference methods, or injection via declarative services. Because a proxy to the remote service is made available in the consumer's OSGi service registry, the consumer need not even be aware that the service is remote.

In this example, the HelloConsumerApplication.addingService method is called by the service tracker when the remote service is discovered. The example implementation of the addingService method (see line 131 of HelloConsumerApplication) demonstrates various ways of accessing the remote service...via the proxy, or via the ECF IRemoteService instance associated with the proxy...which allows asynchronous messaging with the remote service in addition. This flexibility to use either synchronous/proxy-based remote access, or asynchronous messaging to access the remote service is unique to ECF's remote service API.

Running the Example Hello Service Consumer

In the org.eclipse.ecf.examples.remoteservices.hello.consumer plugin are the following Eclipse product definition files:

products/Hello Service Consumer (edef,generic).product
products/Hello Service Consumer (zeroconf,generic).product
products/Hello Service Consumer (zeronconf,r-osgi).product
products/Hello Service Consumer (zookeeper,generic).product
products/Hello Service Consumer (zookeeper,r-osgi).product

These products all run the HelloConsumerApplication...and provide a different value for the containerType variable that appears in the code. As described above, the value of the containerType variable determines which provider is used to consumer the remote service.

Assuming that the host was started with the generic provider as described above, the consumer product to start is the Hello Service Consumer (generic, local discovery).product. This uses the local File-based Discovery to read the endpoint meta-data from a service description xml file, connect to and use the IHello remote service. See the File-based Discovery page for details of how to setup/use File-based discovery.

It's also possible to use other discovery protocols for dynamic network discovery using zeroconf, Service-Locator Protocol (SLP), Zoodiscovery, or your own discovery protocol. ECF has a complete Discovery API, and this API can support arbitrary discovery protocols. The ECF implementation of the OSGi remote services uses the abstract ECF discovery API only, so any discovery provider can be used transparently for the OSGi remote service discovery.

If Hello Service Consumer (generic, local discovery).product is run/started, after the remote service host has been started on localhost (as described above) the client will show the following output:

osgi> IHello service proxy being added
Completed hello remote service invocation using proxy
Completed hello remote service invocation using future
Completed hello remote service invocation using async

On the service host console the following is output

Host: Hello Service Registered
hello from=org.eclipse.ecf.examples.remoteservices.hello.consumer
hello from=org.eclipse.ecf.examples.remoteservices.hello.consumer future
hello from=org.eclipse.ecf.examples.remoteservices.hello.consumer async

This indicates that the remote service was discovered, the proxy subsequently added to the OSGi service registry, and the code executed in HelloConsumerApplication.addingService that uses the remote service.

Getting Started with Using Declarative Services (DS) with Remote Services

An even easier way to export and import remote services is provided via the use of OSGi Declarative Services (DS). With declarative services, very little actual java code is required, because the service can be both registered (host) and injected (consumer) declaratively via declarative services. See the following two example host and consumer example projects:

Host: org.eclipse.ecf.examples.remoteservices.hello.host.ds, located in git here

Consumer: org.eclipse.ecf.examples.remoteservices.hello.consumer.ds, located in git here

Related Topics

File-based Discovery
Remote Services Admin
Creating ECF Providers

Eclipse Communication Framework
API DocumentationJavadocProvidersECF/Bot Framework
Development GuidelinesIntegrators Guide