Jump to: navigation, search

EIG:Getting Started with OSGi Remote Services

Revision as of 01:53, 27 January 2010 by Slewis.composent.com (Talk | contribs) (Service Consumer: Discovering and Accessing the Remote Service)

Adding ECF 3.2 to Your Target Platform

When ECF 3.2 is released (expected release date: Feb 19, 2010) it will be available on the ecf download page. Until the release, however, to work with ECF 3.2 you will need to get one of the recent daily builds of the ECF SDK (available here...see the C-HEAD-sdk_feature or the N-HEAD-sdk_feature), OR get the ECF source code and build/run from your local workspace.

Note that you only need the ECF SDK in your target platform.

You will also need Eclipse 3.6M5 in your target platform. See here to download Eclipse 3.6M5 (or newer).

Getting the Example Code

Click here for instructions on retrieving all the Hello Example source into your local workspace

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 void 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 (activemq).product
products/Hello Service Host (generic).product
products/Hello Service Host(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.