users@jersey.java.net

Async interfaces for client API take 2

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Fri, 14 Aug 2009 16:24:06 +0200

Hi,

After Marc sent a link to the JAX-WS async interfaces i also had some
discussion with Brian Goetz and the advice was it is better to pass a
Future to the listener as well as return a Future (the two may be the
same instance but does not have to be). So i have changed the
listeners to use a Future.

The low-level interfaces are at the end of the email and should now be
suitable for plugging into an async implementation.

The high-level way of async listening is as follows:

      AsyncWebResource r = ..
      Future<String> f = r.get(new TypeListener<String>(String.class) {
          public void onComplete(Future<String> f) throws
InterruptedException {
              try {
                  String s = f.get();
              } catch (ExecutionException ex) {
                  // Do error processing
                  if (t instanceof UniformInterfaceException) {
                      // Request/response error
                  } else
                      // Error making request e.g. timeout
                  }
              } catch (CancellationException ex) {
                  // Clean up on cancellation
              }
              // InterruptedException will never be thrown because the
Future is completed
          }
      });

The returned Future<String> instance can be used to cancel the request
and the listener will get invoked. A call to Future.get in the
listener will result in a CancellationException being thrown.

Paul.

/**
  * An asynchronous client handler for invoking asynchronous client
requests.
  *
  * @author Paul.Sandoz_at_Sun.Com
  */
public interface AsyncClientHandler {

     /**
      * Invoke an asynchronous client request. This method returns
without
      * waiting for the client response.
      *
      * @param r the client request.
      * @param l the future listener to receive a completed Future
with the
      * client response.
      * @return a future that may be used to wait until the future
completes and
      * obtain the client response state, or cancel the request.
      */
     Future<ClientResponse> handle(ClientRequest r,
FutureListener<ClientResponse> l);
}

/**
  * A future listener to receive an event when a Future has reached the
  * completed termination state of normal termination, an exception
  * or cancellation.
  *
  * @param <T> the type held by the future.
  * @author Paul.Sandoz_at_Sun.Com
  */
public interface FutureListener<T> {

     /**
      * Invoked when a Future has reached the completed termination
state.
      * <p>
      * The catching of a {_at_link ExecutionException} when
      * <code>Future.get</code> is invoked may be utilized to
determine if the
      * future terminated with an exception. The exception can be
obtained
      * by invoking {_at_link ExecutionException#getCause() }.
      * <p>
      * The catching of a {_at_link CancellationException} when
      * <code>Future.get</code> is invoked may be utilized to
determine if the
      * future terminated with a cancellation.
      *
      * @param f the completed Future. Invocation of {_at_link
Future#isDone() }
      * will return true. Since the future is complete
invocation of
      * {_at_link Future#get() } and {_at_link Future#get(long,
java.util.concurrent.TimeUnit) }
      * will not result in the throwing of an {_at_link
InterruptedException}.
      * @throws InterruptedException this exception is declared so
that the
      * developer does not need to catch it when invoking
      * <code>Future.get</code>.
      */
     void onComplete(Future<T> f) throws InterruptedException;
}