My real goal is I would like to write client code that can efficiently manage large sets results from async methods, or long running async mehtods. Currently the only way to get a result for a anync method is to block (Future.get()) or to poll (Future.get(long timeout, TimeUnit units), both of which eat up a precious thread resources (or on an IBM mainframe computation resources).

What I'd like to see an interface like this in EJB or as a second maybe the EE concurrent spec:

    public interface ManagedFuture<T> extends Future<T> {
        void onComplete(Runnable runnable);
void onComplete(Runnable runnable, ExecutorService executorService);
    }

The is would allow me to write client code that is notified when the async result is ready. This interface could even be an optional interface the server could return, and I could simply wrap it as follows:

    public class FakeManagedFuture<T> implements ManagedFuture<T> {
        private final Future<T> future;

        public FakeManagedFuture(Future<T> future) {
            this.future = future;
        }

        public boolean cancel(boolean mayInterruptIfRunning) {
            return future.cancel(mayInterruptIfRunning);
        }

        public boolean isCancelled() {
            return future.isCancelled();
        }

        public boolean isDone() {
            return future.isDone();
        }

public T get() throws InterruptedException, ExecutionException {
            return future.get();
        }

public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
            return future.get(timeout, unit);
        }

        public void onComplete(Runnable runnable) {
            onComplete(runnable, getDefaultExecutorService());
        }

public void onComplete(final Runnable runnable, ExecutorService executorService) {
            if (future instanceof ManagedFuture) {
                ManagedFuture managedFuture = (ManagedFuture) future;
                managedFuture.onComplete(runnable);
            } else {
                executorService.submit(new Runnable() {
                    public void run() {
                        try {
                            future.get();
                        } catch (Exception ignored) {
                        }
                        runnable.run();
                    }
                });
            }
        }

        private ExecutorService getDefaultExecutorService() {
            return null;
        }
    }

Alternatively, the spec could define a CompletionService (injectable or via JNDI) link this:

    public interface CompletionService {
        void onComplete(Future future, Runnable runnable);
void onComplete(Future future, Runnable runnable, ExecutorService executorService);
    }

For servers that don't implement async client notifications, they could simply poll or block under the covers.

Regardless, I think we should provide something like this in OpenEJB, but I'd like to be able to write apps that are both efficient and portable.

-dain

On Aug 7, 2008, at 1:23 PM, Jarek Gawor wrote:

On Wed, Aug 6, 2008 at 1:43 PM, Dain Sundstrom <[EMAIL PROTECTED]> wrote:
On Aug 6, 2008, at 10:14 AM, Jarek Gawor wrote:

On Wed, Aug 6, 2008 at 1:00 PM, Dain Sundstrom <[EMAIL PROTECTED]> wrote:

On Aug 5, 2008, at 1:25 PM, David Jencks wrote:

Is there something similar in the ee concurrency spec?

Never heard of that spec.  Do you have any details?

Here's some info on the spec:

http://gee.cs.oswego.edu/dl/concurrencyee-interest/index.html

http://www.jcp.org/en/jsr/detail?id=236

and in Geronimo (trunk) we have a basic implementation of the draft spec.

Interesting. It would be nice if there were something like this for the client side. One big I issue I see with EJB async methods is there is no way to be notified when the result of an async method is ready. This API is
very close to being what we would need.  Specifically this method on
ManagedExecutorService:

      submit(Callable<T> task, ManagedTaskListener taskListener)

which adds a task to run with a listener for it's completion. For async
result support we would need something like this:

waitForResult(Future<?> future, ManagedTaskListener taskListener)

There is ManagedExecutorService.invokeAll(Collection<Callable> tasks,
ManagedTaskListener listener) function which effectively does two
things: 1) it submits the tasks and 2) waits until they all finish.
Pretty much the same as ExecutorService.invokeAll() except the
listener which you could use to figure out which task completed so
far.

of maybe

      submit(new WaitForCallable(myFuture), taskListener)

If the future instance implemented a special "notifiable" interface, the Executor service would simply add the listener to the future. If it didn't implement that interface, it would use a thread to block (or periodically
poll) for the result.

I don't know the OpenEJB code very well, but what if it returned a
Callable object instead of a Future. That way, I think, it would fit
nicely with either ExecutorService or ManagedExecutorService. And as
you mentioned, you could always wrap a Future into a Callable or
Runnable.

That is an interesting idea. If an async method could optionally return Callable<T> instead of Future<T>, the callable could be the special "notifiable" interface I talk about above. Assuming the Callable returned and the ManagedExecutorService are supplied by the same vendor, the ManagedExecutorService could detect the callable is for ansync result and wait for results without assigning a thread

Unfortunately, it would mean that the coder of the aync method would need to decide if the caller wanted a Future or a Callable which kind of stinks.




Something like this would allow users to write efficient and spec compliant
async clients.

David (Jencks), are you working on this spec?  Any chances on getting
something like this in?

I'm working on the spec and the implementation in Geronimo and just
joined the Expert Group so if you have any comments or specific
proposals please let me know.

Jarek

Reply via email to