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