3 Replies Latest reply on May 26, 2009 2:14 PM by David D

    Asynchronous + Future.get() = null

    Gabriel Goïc Newbie

      Hello all


      I'm currently trying to use Seam's built-in async support with Seam 2.0.2 SP1 inside a JBoss 4.2.2 GA.


      Having read seam-reference.pdf, I didn't change my components.xml as I wanted to use default asynchronicity configuration.


      I have an EJB 3 bean in which I changed a method definition to this:


      import java.util.concurrent.Future;
      
      @Local
      public interface A {
        @Asynchronous
        public Future<A> foo();
      }
      



      and its implementation is as follows:


      @Stateless
      @Name("asyncBean")
      public class Aimpl implements A {
        public Future<A> foo() {
          // some endless processing
          return null;
        }
      }



      The caller class acts like this:


      @Stateless
      @Name("callerBean")
      public class Bimpl implements B {
        
        @In(create=true)
        A asyncBean;
      
        Future<A> task = asyncBean.foo();
      
        while(!task.isDone()){
          Thread.sleep(10);
        } //try-catch omitted
      
        A result = task.get();
      }



      This is pretty simple but though 'result' is always null. I can see logs showing that the task is actually processed, no errors that I can see, but it looks like Seam cannot provide a pointer to the resulting bean implementation in a processed state.


      I then looked at the async XSD, figured out what the only option (apart from EJB 3 Timer and Quartz) was and tried to add this in my components.xml:


      <async:thread-pool-dispatcher thread-pool-size="5"/>



      but still no luck.


      What am I doing wrong? the doc isn't very clear on the default async behaviour, and it seems nobody tried it before, according to google having no clue on the subject.


      Any help would be greatly appreciated.

        • 1. Re: Asynchronous + Future.get() = null
          Gabriel Goïc Newbie

          I made it even simpler by using a POJO instead of an EJB, but still Future.get() returns null.


          What's fun is that when I replace Future by Timer and add this in components.xml:


          <async:timer-service-dispatcher/>



          then it works fine and I get a bean in a processed state which contains any data I need.


          Doing some other tests, I removed any async tag from components.xml and took a look at Seams' startup log, which shows this interesting part:


          2008-10-27 13:22:21,297 INFO  [org.jboss.ejb3.JmxKernelAbstraction] installing MBean: jboss.j2ee:ear=mat.ear,jar=jboss-seam.jar,name=TimerServiceDispatcher,service=EJB3 with dependencies: (ScannerThread)
          2008-10-27 13:22:21,355 INFO  [org.jboss.ejb3.EJBContainer] STARTED EJB: org.jboss.seam.async.TimerServiceDispatcher ejbName: TimerServiceDispatcher (ScannerThread)



          This makes me think that everytime I try to make the thread pool dispatcher work, this is actually the EJB3 Timer dispatcher which gets started.
          I guess this happens because jboss-seam.jar is mentioned in my application.xml file as an ejb module, and thus all of its EJBs are deployed at startup. The problem is, TimerServiceDispatcher (EJB) and ThreadPoolDispatcher (POJO) have the same @Name(org.jboss.seam.async.dispatcher) and thus are mutually exclusive. I guess having the wrong dispatcher activated is what makes Seam unable to link to the result of a Future.


          Is there a way to make ThreadPoolDispatcher have the higher precedence or anything that would cause it to prevail in this dispatchers war?


          • 2. Re: Asynchronous + Future.get() = null
            Gabriel Goïc Newbie

            Well I was wrong, a ThreadPoolDispatcher instance is what is returned when calling:


            Component.getInstance("org.jboss.seam.async.dispatcher");



            Upgrading to Seam 2.1 GA had no effect. I was able to add an asynchronous exception handler as advised by the doc:


            @Scope(ScopeType.STATELESS)
            @Name("org.jboss.seam.async.asynchronousExceptionHandler")
            public class MyAsynchronousExceptionHandler extends AsynchronousExceptionHandler {
            
                @Logger
                Log log;
                @In
                Future timer;
            
                @Override
                public void handleException(Exception exception) {
                    log.debug(exception);
                    timer.cancel(false);
                }
            }



            But it did not get anything in its net. Future.get() still returns null without an error.


            No idea where this mystery comes from.



            I filed a JIRA for this problem:
            https://jira.jboss.org/jira/browse/JBSEAM-3641

            • 3. Re: Asynchronous + Future.get() = null
              David D Newbie

              Hi,
              Did you solve your problem ? As far as I understand the Seam code, one cannot get back a value from an asynchronous method sine internally it uses a runnable and not a callable...
              Thanks