Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Getting Started with ECF's RFC119 Implementation"

(added warning about duplicate/potentially not-up-to-date content)
Line 1: Line 1:
 +
{{warning|Outdated and/or duplicate information|This page seems to contain information which is also available at [[EIG:Getting Started with OSGi Remote Services]]. It also seems to be related to ECF 3.0 whereby the other page references a target platform using ECF 3.5.}}
 +
 +
 
Install ECF 3.0. See [http://www.eclipse.org/ecf/downloads.php ecf download].
 
Install ECF 3.0. See [http://www.eclipse.org/ecf/downloads.php ecf download].
  

Revision as of 05:32, 18 January 2013

Warning2.png
Outdated and/or duplicate information
This page seems to contain information which is also available at EIG:Getting Started with OSGi Remote Services. It also seems to be related to ECF 3.0 whereby the other page references a target platform using ECF 3.5.


Install ECF 3.0. See ecf download.

In addition you will need Equinox in your target platform (either the Equinox 3.5 SDK or the parts that come with Eclipse).

To see how the ECF RFC119 implementation fits into the overall picture of supporting Distributed OSGi, see Distributed OSGi Services with ECF.

Service Interface

As with any OSGi service, you must first define your service interface. Here is a trivial example 'hello' service interface:

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

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

Registering the Service (Host)

Here is the code in org.eclipse.ecf.internal.examples.remoteservices.hello.host.Activator that registers a remote service with the ECF RFC119 implementation:

	public void start(BundleContext context) throws Exception {
		this.context = context;
		// Create R-OSGi Container
		IContainerManager containerManager = getContainerManagerService();
		containerManager.getContainerFactory().createContainer("ecf.r_osgi.peer");
 
		Properties props = new Properties();
		// add OSGi service property indicating this
		props.put(REMOTE_INTERFACES, REMOTE_INTERFACES_WILDCARD);
		// register remote service
		helloRegistration = context.registerService(IHello.class.getName(), new Hello(), props);
		System.out.println("Host: Hello Service Registered");
	}

This code does the following:

  1. Creates an r-osgi ECF container to do the distribution
  2. Sets the RFC119-specified REMOTE_INTERFACES ('osgi.remote.interfaces') service property to REMOTE_INTERFACES_WILDCARD ('*')
  3. Creates a new Hello instance and registers it as a remote service (via the service props).

Here is the expected output to the console for this host

[log;-0700 2009.06.02 13:37:45:421;WARNING;org.eclipse.ecf.osgi.services.distribution;org.eclipse.core.runtime.Status[plugin=org.eclipse.ecf.osgi.services.distribution;code=4;message=org.eclipse.ecf.internal.osgi.services.distribution.DiscoveredServiceTrackerImpl:handleDiscoveredServiceAvailable:No RemoteServiceContainerAdapters found for description=ServiceEndpointDescriptionImpl[;providedinterfaces=[org.eclipse.ecf.examples.remoteservices.hello.IHello];location=null;serviceid=ServiceID[type=ServiceTypeID[typeName=_osgiservices._tcp.default._iana];location=osgiservices://10.0.1.18:9279;full=_osgiservices._tcp.default._iana@osgiservices://10.0.1.18:9279];osgiEndpointID=null;ecfEndpointID=r-osgi://TILAPIA:9279;ecfTargetID=null;ecfFilter=null;props={ecf.rsvc.ns=ecf.namespace.r_osgi.remoteservice, osgi.remote.service.interfaces=org.eclipse.ecf.examples.remoteservices.hello.IHello, ecf.sp.cns=ecf.namespace.r_osgi, ecf.rsvc.id=[B@1950e0a, ecf.sp.cid=[B@ccd21c}];severity4;exception=null;children=[]]]
Host: Hello Service Registered

You should ignore the warning...this just indicates that the server discovered it's own published service and did not create a proxy for it.

If, however, you get the following warning when starting the host:

osgi> WARNING: Port 9278 already in use. This instance of R-OSGi is running on port 9279

This means that there is some other R-OSGi instance running on that same system, and that port 9278 is not available for use by the host. In this case, you need to stop the host, and disable the other R-OSGi instance before running the host again. To disable R-OSGI, see Disabling R-OSGi and R-OSGi_Properties.

Using the Service (Consumer)

The service consumer first discovers the published service, and then when discovered it creates a proxy and registers the proxy in the local service registry.

Here is code from org.eclipse.ecf.internal.examples.remoteservices.hello.consumer.Activator

	public void start(BundleContext context) throws Exception {
		this.context = context;
		// Create R-OSGi Container
		IContainerManager containerManager = getContainerManagerService();
		containerManager.getContainerFactory().createContainer("ecf.r_osgi.peer");
		// Create service tracker to track IHello instances that are REMOTE
		helloServiceTracker = new ServiceTracker(context,createRemoteFilter(),this);
		helloServiceTracker.open();
	}

Like the service host, this code also must create an R-OSGi peer container instance. Note that to switch to another/different provider (than R-OSGi), all that must be changed is the string "ecf.r_osgi.peer" in both the host and consumer.

After creating the container, a ServiceTracker is created to track the discovery and registration of remotely published services. This allows discovery to happen asynchronously, and when the remote service matching the filter returned from createRemoteFilter(), the 'serviceAdded' method will be called by the service tracker sometime after the service tracker is created. Here is the serviceAdded method:

	public Object addingService(ServiceReference reference) {
		System.out.println("IHello service proxy being added");
		IHello hello = (IHello) context.getService(reference);
		// Call it
		hello.hello(CONSUMER_NAME);
		System.out.println("Called hello() on proxy successfully");
		return hello;
	}

This method:

  1. Gets the hello instance for the reference (which is actually a proxy)
  2. Calls hello() on the hello instance, just like it was a local service.

Asynchronous Remote Method Invocation

Sometimes it's desirable to invoke remote methods asynchronously, without blocking until the remote method call completes. This is sometimes desirable, for example, if your user interface thread is doing the calling, as remote methods can/could block for a much longer time than would be acceptable for users.

ECF provides an API to invoke remote methods with a guarantee that they will be executed asynchronously, in some other thread, and allowing the calling thread not to be blocked.

For ECF the value of the REMOTE property (i.e. 'osgi.remote') is a non-null instance of IRemoteService. IREmoteService provides the consumer with more flexibility in how they can remotely call methods exposed by the IHello service interface.

Here's an example that fires an asynchronous message to invoke the 'hello' method on the remote service.

IRemoteService remoteService = (IRemoteService) reference.getProperty(REMOTE);
remoteService.fireAsync(new IRemoteCall() {
 
    public String getMethod() {
        return "hello";
    }
 
    public Object[] getParameters() {
        return new Object[] { CONSUMER_NAME };
    }
 
    public long getTimeout() {
        return 30000;
    }});

Notice that it is not necessary to have even the IHello service interface class present to use this technique.

For another example, here's code that uses the IRemoteService to return a future result. The future result is provided immediately, without blocking, and then sometime later can be accessed to either get the result (if already complete) or wait for the result to complete.

// Now get remote service reference and use asynchronous 
// remote invocation
IRemoteService remoteService = (IRemoteService) reference.getProperty(REMOTE);
// This futureExec returns immediately
IFuture future = RemoteServiceHelper.futureExec(remoteService, "hello", new Object[] { CONSUMER_NAME });
// ...do other computation here...
// This method blocks until a return 
future.get();
System.out.println("Called future.get() successfully");

Related Documentation

Distributed OSGi Services with ECF

Getting Started with Using the ECF Remote Services API

Disabling R-OSGi

R-OSGi_Properties

ECF API Docs

API Javadocs

Distributed EventAdmin Service

Eclipse Communication Framework
API
API DocumentationJavadocProviders
Development
Development GuidelinesIntegrators Guide

Back to the top