0 Replies Latest reply on Feb 5, 2009 4:28 AM by alrubinger

    Design of EJB 3.1 @Asynchronous

    alrubinger

      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 http://anonsvn.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