-
1. Re: Reintroducing Asynchronous Support
alrubinger Oct 24, 2008 2:41 AM (in response to alrubinger)In addition to the simplicity argument, another motivation I have is to make the APIs between our support and that defined by EJB3.1 as close as possible.
Even though EJB3.1 spec says that the decision to invoke async or not lies w/ the bean provider; I say it should be the caller's choice. So that's why we'll keep our implementation as well.
S,
ALR -
2. Re: Reintroducing Asynchronous Support
dmlloyd Oct 24, 2008 12:17 PM (in response to alrubinger)Does EJB 3.1 specify use of java.util.concurrent.Future? I only ask because I've discovered a couple of problems with it for remove invocation use that I ran into when working on Remoting:
1) It is not entirely clear if .cancel() should block until it knows whether or not the cancel succeeded. The designers clearly did not expect there to be any time lag between the invocation of the .cancel() method and the ability to determine the result. With remote invocation one wishes to be able to cancel asynchronously; you could always return false but the docs clearly state that false means "the task could not be cancelled, typically because it has already completed normally".
2) It should not be the client's decision whether or not the server interrupts the task thread. Nevertheless, .cancel() accepts a boolean parameter which indicates whether the task should be cancelled. It's clear that this interface was meant to be used from code that has authority over the thread pool which is executing the task.
3) The API itself lends very little power to the end-user (no methods to await interruptibly, no way to receive failure or cancellation notifications other than catching exceptions).
4) There is no mechanism for users to register a callback which can be invoked when the operation is done.
For Remoting and XNIO I ended up creating a new future interface (within XNIO) specifically designed for I/O and remote invocation operations:
http://anonsvn.jboss.org/repos/xnio/xnio-base/trunk/api/src/main/java/org/jboss/xnio/IoFuture.java
In addition I provide abstract implementations, and a utility method to create a java.util.concurrent.Future for interfaces which require it. Semantically, the wrapper Future will ignore the "interruptIfRunning" parameter to .cancel(), and .cancel() blocks until it is known whether the operation was successfully cancelled.
I'm not saying you should introduce an XNIO or Remoting 3 dependency - well, unless you want to :) - but I think it's safe to say that java.util.concurrent.Future isn't an acceptable mechanism for getting the result of a remote invocation. Been there, tried that. :-) -
3. Re: Reintroducing Asynchronous Support
dmlloyd Oct 24, 2008 12:18 PM (in response to alrubinger)In #2 above I mean "cancel() accepts a boolean parameter which indicates whether the task should be interrupted", not cancelled...
-
4. Re: Reintroducing Asynchronous Support
dmlloyd Oct 24, 2008 12:19 PM (in response to alrubinger)...and for #3 I mean "uninterruptibly", not "interruptibly".... :-|
-
5. Re: Reintroducing Asynchronous Support
dmlloyd Oct 24, 2008 12:37 PM (in response to alrubinger)It occurs to me that the javadoc is a better link:
http://docs.jboss.org/xnio/latest/api/org/jboss/xnio/IoFuture.html -
6. Re: Reintroducing Asynchronous Support
alrubinger Oct 25, 2008 12:04 PM (in response to alrubinger)"david.lloyd@jboss.com" wrote:
Does EJB 3.1 specify use of java.util.concurrent.Future?
Yes."EJB 3.1 Core Specification 4.5.2" wrote:
The client return type of an asynchronous method is either void or java.util.concurrent.Future<V>, where V is the result value type."david.lloyd@jboss.com" wrote:
I only ask because I've discovered a couple of problems with it for remove invocation use that I ran into when working on Remoting...
Clearly I'd like to take advantage of your experience here, but not at the expense of confusing users with more nonstandard APIs. So perhaps I can take a hybrid approach."david.lloyd@jboss.com" wrote:
1) It is not entirely clear if .cancel() should block until it knows whether or not the cancel succeeded. The designers clearly did not expect there to be any time lag between the invocation of the .cancel() method and the ability to determine the result. With remote invocation one wishes to be able to cancel asynchronously; you could always return false but the docs clearly state that false means "the task could not be cancelled, typically because it has already completed normally".
Though not explicitly stated, to fulfill the JavaDoc's requirements of j.u.c.Future, we'd have to block until we knew whether the operation would be cancelled.
In the case of EJB, a call to "cancel" is a request by the client. The bean must be written to support cancellation, and "mayInterruptIfRunning" would have to be ignored as that context is not available to the bean provider to check."EJB 3.1 Core Spec, 4.5.2.2" wrote:
A client can request that an asynchronous invocation be cancelled by calling the Future<v>.cancel(boolean mayInterruptIfRunning) method. A Bean Developer can check whether the client has requested cancellation by calling the SessionContext.isCancelled() method within the context of the asynchronous method.
Now, if the bean provider chooses to honor the request to cancel, there's a missing mechanism to let the client to know whether the request was fulfilled. So what should be the proper return value of "cancel()"?
I'll pose this question to the JSR318 EG."david.lloyd@jboss.com" wrote:
2) It should not be the client's decision whether or not the server interrupts the task thread. Nevertheless, .cancel() accepts a boolean parameter which indicates whether the task should be cancelled. It's clear that this interface was meant to be used from code that has authority over the thread pool which is executing the task.
From the spec above, this flag is lost and not available in SessionContext anyway."david.lloyd@jboss.com" wrote:
3) The API itself lends very little power to the end-user (no methods to await interruptibly, no way to receive failure or cancellation notifications other than catching exceptions).
4) There is no mechanism for users to register a callback which can be invoked when the operation is done.
True story. The implementation I'm looking to replace/simplify also provides blocking to "get" via the Oswego concurrent utils. And only the XNIO impl provides for callbacks.
At first glance I'd approach this by using a XNIO Future impl under the hood, and wrapping w/ j.u.c.Future to return to the client. This would also pave the way to provide for more than one async interface to the client, who could choose his view (XNIO, j.u.c, etc). I'm weary of drawing in another dependency unless it's already brought into AS somewhere?
Then again, eventually we're gonna need Remoting 3 which depends on XNIO, so worst case is we'd be tacking on this library prematurely...
S,
ALR -
7. Re: Reintroducing Asynchronous Support
dmlloyd Oct 27, 2008 9:00 AM (in response to alrubinger)"ALRubinger" wrote:
Now, if the bean provider chooses to honor the request to cancel, there's a missing mechanism to let the client to know whether the request was fulfilled. So what should be the proper return value of "cancel()"?
I'll pose this question to the JSR318 EG.
Yeah, it seems to me there's really no gray area in the javadoc for Future - "true" means cancelled, "false" means not cancelled. There's no answer that means "outcome unknown" - you pretty much would have to throw a RuntimeException in that case to strictly fulfill the contract (though in practice, returning "false" is probably good enough... that's what I do with my wrapper class anyway). Not only that but the method is (implicitly) blocking but not interruptible. Blah.
A good client use case that I measure against is a Swing client. For a long-running task, they'll want to have a "cancel" button for sure. Also, in a Swing client you don't want to block the EDT. Using a non-blocking .cancel() method is perfect for this case. The close button can map directly to the .cancel() method, with no intervening logic, and the future's callback (or a separate waiting thread) can be used to retrieve the result. Using j.u.c.Future you'd need to execute the .cancel() in another thread just in case it blocks (and manually prevent multiple button presses as well). I think that the AJAX world will also see similar behavior."ALRubinger" wrote:
At first glance I'd approach this by using a XNIO Future impl under the hood, and wrapping w/ j.u.c.Future to return to the client. This would also pave the way to provide for more than one async interface to the client, who could choose his view (XNIO, j.u.c, etc). I'm weary of drawing in another dependency unless it's already brought into AS somewhere?
It will be, for Remoting to start with, and other projects going forward. -
8. Re: Reintroducing Asynchronous Support
alrubinger Nov 12, 2008 8:53 PM (in response to alrubinger)A note as I go through this:
Previous implementation was not Thread-safe, as it backed the Future result in a ThreadLocal. So if a client cached a Proxy and used it in a multithreaded environment, the wrong results could be obtained.
S,
ALR -
9. Re: Reintroducing Asynchronous Support
alrubinger Nov 12, 2008 8:55 PM (in response to alrubinger)"ALRubinger" wrote:
Previous implementation was not Thread-safe, as it backed the Future result in a ThreadLocal.
Attention everyone paying attention:
The above is clearly the dumbest thing I've ever said. From now on, no more working while sick and on NyQuil.
S,
ALR -
10. Re: Reintroducing Asynchronous Support
anil.saldhana Nov 13, 2008 12:10 AM (in response to alrubinger)"ALRubinger" wrote:
"ALRubinger" wrote:
Previous implementation was not Thread-safe, as it backed the Future result in a ThreadLocal.
Attention everyone paying attention:
The above is clearly the dumbest thing I've ever said. From now on, no more working while sick and on NyQuil.
S,
ALR
Maybe you intended to take "Dayquil". Nyquil would have tucked you in bed. -
11. Re: Reintroducing Asynchronous Support
alrubinger Nov 14, 2008 2:28 PM (in response to alrubinger)This is done as part of https://jira.jboss.org/jira/browse/EJBTHREE-1591.
The underlying mechanism now decouples async invocations from jboss-ejb3-proxy; the client can add async support at runtime via a j.l.f.Proxy mixin. So as the Unit Tests in jboss-ejb3-common show, this isn't at all specific to EJB3.
S,
ALR