This is to document an initial proposal for design of the new @Asynchronous handling
required of EJB 3.1. Initially I'll describe the flow in prose until I get some good
diagrams. :)
I'm sure this will change a bunch as I start to prototype. I'm not a fan of
big-design-up-front and tend to work out the kinks while coding.
Overall Goals
* Every component should get an SPI and allow for pluggable/configurable implementations
* Remoting is a functional add-on, not baked into the API. Remoting impls may be
swapped.
Components Involved
Async Interceptor - Responsible for short-circuting the client invocation. Examines
invocation metadata, determines if it's targeted for async. If so, pushes the
invocation to an InvocationQueue and returns a j.u.c.Future implementation to the client.
Async Future - A (possibly) remotable handle for the client to obtain the result, check if
completed, request a cancellation, etc.
InvocationQueue - Acts both as a queue of Invocations and a queryable registry. Supports
isCancelled(Invocation uid), hasCompleted(Invocation uid), . Must be thread-safe.
Thread Pool - Used by AsyncExecutor. Possibly implemented by MC ThreadPool deployers
https://svn.jboss.org/repos/sandbox/david.lloyd/jboss-threads/trunk/
AsyncExecutor - A custom implementation of j.u.c.Executor which uses the configured Thread
Pool to run jobs.
InvocationSucker - Begs for a better name. Inspired by JBM "MessageSucker".
Runs in a loop, pulls the next Invocation off the queue (if present), and uses the
AsyncExecutor (and by extension the configured Thread Pool) to invoke upon the appropriate
SessionContainer.
Server's Future Invocation Endpoint - Serves invocations upon the Future object by the
client. May query upon the InvocationQueue, as well as register itself for callbacks when
state changes in the queue occur.
Control Flow
Client Invocation
* Client invokes upon a business method annotated with @Asynchronous
* Server's AsyncInterceptor determines this is an async invocation. Pushes the
invocation upon the InvocationQueue and returns a handle back to the client in form of the
AsyncFuture.
* InvocationSucker loops around and finds this new invocation on the queue. Makes a state
change on the queue to "processing" and invokes the Invocation upon the
Container via the AsyncExecutor.
* AsyncExecutor obtains either return value or Exception, and stores this back into the
InvocationQueue under a state of "completed"
Future.get() when result is available
* Client obtains Future result from AsyncInterceptor
* Client invokes Future.get()
* Server's Future Invocation Endpoint queries upon the InvocationQueue if the
invocation is done. Since it is, obtains the result and returns to the client.
Future.get() when result is not available
* Client obtains Future result from AsyncInterceptor
* Client invokes Future.get()
* Server's Future Invocation Endpoint queries upon the InvocationQueue if the
invocation is done. Since it is not, a callback is registered within the Queue.
* Future Invocation Endpoint blocks (Thread.wait() or NIO blocking)
* When the queue gets a state change on the invocation in question, queue notifies the
endpoint with the result
* Endpoint returns to client
S,
ALR
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4207242#...
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&a...