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:
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).
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
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
Hey - I am really glad to find this. great job!
Post a Comment