3 Replies Latest reply on Dec 26, 2007 3:41 PM by pmuir

    TransactionCompletionEvent and @Asynchronous

    cpopetz

      I have:

      Events.instance().raiseTransactionSuccessEvent("doLongWorkAfterTxIsDone");

      and

      @Observer("doLongWorkAfterTxIsDone")
      public void doWork() {
      aSLSB.anAsyncMethod();
      }

      where anAsyncMethod() is a method marked @Aysnchronous. (I'd mark the observer itself as @Asynchronous, but that gets ignored.) However, anAsyncMethod() isn't called asynchronously, because TransactionCompletionEvent is an AsynchronousEvent, and seam disallows spawning one asynchronous call from another. But in my case, the CMT tx is committing (and the event is being fired) upon return of a SFSB method that is executed within a web request, i.e. very synchronously as far as the browser is concerned.

      I'm not completely clear on the logic behind disallowing chained async calls, so this may be misguided. But it seems to me that Asynchronous.execute() should only set EXECUTING_ASYNCHRONOUS_CALL if it indeed sets up a new set of contexts. That would allow the above code to work. Of course, it might break something else :)

      I have a workaround, which is to raise another asynchronous event from the observer of the transactionComplete event, but that's rather convoluted.


      Thanks for any input,
      -Clint

        • 1. Re: TransactionCompletionEvent and @Asynchronous
          pmuir

           

          "cpopetz" wrote:
          where anAsyncMethod() is a method marked @Aysnchronous. (I'd mark the observer itself as @Asynchronous, but that gets ignored.)


          There is an open feature request for this to be supported (I think it makes good sense).

          However, anAsyncMethod() isn't called asynchronously, because TransactionCompletionEvent is an AsynchronousEvent, and seam disallows spawning one asynchronous call from another.


          This was a bug which we fixed for 2.0.0.GA - what version are you using?

          You certainly should be able to schedule async calls from other async calls.

          • 2. Re: TransactionCompletionEvent and @Asynchronous
            cpopetz

             

            "pete.muir@jboss.org" wrote:
            "cpopetz" wrote:
            where anAsyncMethod() is a method marked @Aysnchronous. (I'd mark the observer itself as @Asynchronous, but that gets ignored.)


            There is an open feature request for this to be supported (I think it makes good sense).


            Wonderful, thanks.

            "pete.muir@jboss.org" wrote:
            "cpopetz" wrote:
            However, anAsyncMethod() isn't called asynchronously, because TransactionCompletionEvent is an AsynchronousEvent, and seam disallows spawning one asynchronous call from another.


            This was a bug which we fixed for 2.0.0.GA - what version are you using?

            You certainly should be able to schedule async calls from other async calls.


            Indeed, and the above example is working for me since moving to 2.0.0GA. I now have a similar situation that's a little more complicated than above. My @Observer and the @Asynchronous method it invokes are in the same SLSB. (And once @Observers can be @Asynchronous, this will all be moot, because that's what I'm working around.) I had done the following from within the @Observer method:

            @Observer("doLongWorkAfterTxIsDone")
            public void doWork() {
            // this.anAsynchMethod(); //doesn't work; no interceptors
            ejbContext.getBusinessObject(AttachmentStorer.class).anAsynchMethod();
            }
            
            //this is annotated @Asynchronous in the @Local interface
            public void anAsynchMethod() {
            ...
            }
            


            But this causes seam to use the SERVER set of interceptors, which does not include AsynchronousInterceptor. I also tried doing Component.getInstance("myComponentName") to obtain an intercepted version of "this", but the method context contains "this" and just returns it, and no interceptors are used on the invocation of anAsynchMethod() in that case either.

            It seems that @Asynchronous works well between objects, but not so well for method calls within an object, which is unfortunate, but perhaps that's by design. I can refactor to move the asynchronous code into a different bean, but that's a bit artificial. So I'll probably just use Seam's Work() { } construct.

            This is similar to the problem I faced with @TransactionAttribute and intra-bean calls. I think it's a common use-case for a session bean to want to invoke methods upon itself, but in order to have CMT work correctly in the non-default case of having an outer method be non-transactional and repeatedly invoke an inner method which gets its own transaction, this means using getBusinessObject(), which is just plain ugly.

            But that's not seam's issue :)

            • 3. Re: TransactionCompletionEvent and @Asynchronous
              pmuir

              Yes, inter bean async calls aren't supported.