Wednesday, April 14, 2010

OSGi Remote Services and ECF - Asynchronous services

In a previous posting, I discussed/presented some of the support for asynchronous access to OSGi remote services that currently exists in ECF's implementation.

In a blog posting earlier this week, Peter Kriens discussed some of the efforts going on in the EEG on adding asynchronous support for remote (and even local) services. One of his comments in that blog posting was that ECF's asynchronous support could be considered awkward, because of the complexity/unfamiliarity of using the API.

I've been intending to add easier/more natural mechanisms for asynchronous remote access than what we already have, and what's going on in the EEG and Peter's blog was great incentive to complete some more of that work. The existing mechanisms are somewhat awkward, but they also make a very strong/flexible foundation...and so it's possible to build new mechanisms on the existing mechanisms.

Normal/Synchronous Proxies

In our 'hello' remote services example, we have this service interface:

public interface IHello {
public void hello(String from);
}

Consumers of this remote service receive a proxy that implements the IHello interface, and then clients can synchronously invoke the hello method to make a remote call:

proxy.hello{"slewis");

Since in java method calls are blocking, the thread that calls the hello method will block if (e.g.) the network is slow, the service host is slow (or blocks). It would be nice if we had a way (on the consumer/client) to call the hello method and guarantee that it will not block...while still somehow getting the result (if any)...when the remote call is successful...or getting information about the failure if things fail/go wrong (e.g. because of network failure).

Asynchronous Proxies

We've just added support for asynchronous proxies in ECF're remote services implementation. What this means is that if an interface is declared like this (and in the same package as the IHello interface):

public interface IHelloAsync extends IAsyncRemoteServiceProxy {

public void helloAsync(String from, IAsyncCallback callback);

public IFuture helloAsync(String from);

}

the ECF remote service distribution system will automatically create a proxy that implements the IHelloAsync interface on the consumer/client.

If the helloAsync(String,IAsyncCallback) method is called by the consumer:

proxy.helloAsync("slewis",new IAsyncCallback() {
void onSuccess(Object result) {
System.out.println("we got result="+result);
}
void onFailure(Throwable exception) {
System.out.println("oh no!");
exception.printStackTrace();
}
});

the consumer thread will not block, and success/result or failure will be asynchronously communicated to the caller via proxy calling the appropriate method on IAsyncCallback.

In addition to using the callback, futures (IFuture) are also supported. All that must be done to allow the consumer to use a future result is to declare a helloAsync method that returns an IFuture:

public IFuture helloAsync(String from);

The only thing required to get this to happen on the consumer/client is to declare the *Async interface (IHelloAsync). Then, at proxy creation time on the remote service consumer, if this *Async interface exists, it will be implemented by the proxy, and usable by the client.

Note that the *Async interface declaration is the only thing that's needed to get this to work with any service interface. The service host implementation doesn't need to actually implement the *Async interface, and the ECF remote services distribution will create a proxy that implements the *Async interface automatically. Further, like other things ECF, this is all done in a transport-independent way, so all the existing providers (JMS, XMPP, ECF generic, JavaGroups, Skype, REST, SOAP, etc., etc.) support this addition immediately with no further work.

Google Web Toolkit uses a very similar approach to support asynchronous remote procedure call. In addition to callbacks, however, ECF's asynchronous proxy also has support for futures. This allows the consumer/client to choose the desired invocation style: synchronous, asynchronous-callback, or asynchronous-futures.

4 comments:

Scott Lewis said...

I mistakenly rejected the following comment from Gunnar:

Too bad you don't allow generics.

Scott's response:

@Gunnar: We are (so far) allowing the remote service impl to run on EEs as small at CDC 1.1/Foundation 1.1, which doesn't support generics. That's the whole reason why we don't use generics in our classes.

Where/what class(es) are you specifically referring to that would benefit from generics in your view? My picks: IFuture (equinox concurrent) and IAsyncCallback (ecf remote services).

Anonymous said...

Hey,

Thanks for sharing this link - but unfortunately it seems to be not working? Does anybody here at eclipseecf.blogspot.com have a mirror or another source?


Thanks,
Alex

Scott Lewis said...

Alex:

What link are you saying is not working? ECF has released a new version recently (3.5), and you can download here:

http://www.eclipse.org/ecf/downloads.php

and see/find docs here

http://wiki.eclipse.org/ECF

Anonymous said...

Hey - I am really glad to find this. great job!