4 Replies Latest reply on Dec 16, 2009 8:55 PM by T. Chaudhri

    Asynchronous Method and AJAX call to the result

    Christian Zeidler Newbie

      Hello,


      I've got a situation where I want to run multiple asynchronous methods (calls to webservices that take between 1 and 10 seconds to respond) and render the results on the page as they are ready.


      Now, I've got no problem calling my asynchronous methods, and from the debug-output, I can see that they are doing what they should do, but I've had no luck in accessing the results they provide (usualy lists that they provide via getMethods), these alway return empty lists.


      In the section on Asynchronous Methods, the seam tutorial states This pattern works very well in applications which use AJAX, where the client can automatically poll the server for the result of the work this is exactly what I'd like to do. I just seem to have a problem with The asynchronous method is processed in a completely new event context and does not have access to the session or conversation context state of the caller. The seam debug page also shows no content in the List. I've tried passing the List to be filled to the asynchronous Method, and then accessing it, again, no luck.


      Here are some sniplets from my code:


      components.xml:


      <async:timer-service-dispatcher/> 



      The class with the async method:


      @Stateful 
      @Name("flickrSearcher")
      @Scope(ScopeType.CONVERSATION)
      public class Searcher implements SearcherHome  {
      
           @Logger private Log log;
          private List<Result> resultList = new ArrayList<Result>();
           
           
           @Asynchronous
           public void search(String keyword) {
                log.info(" searching ");
                
                // do stuff that takes a while
                
                //write results to resultList
                log.info(" result count after processing: " + resultList.size());
           }
           
           public List<Result> getResultList() {
                log.info("getting results ajax " + resultList.size());
                return resultList;
           }
      
      



      Calling search() shows correct behaviour, calling getResultList after that always returns an empty list...


      Any Help is highly appreciated

        • 1. Re: Asynchronous Method and AJAX call to the result
          Jukka Kaijansinkko Newbie

          Hi Christian,


          I'm having the same problem, we're you able to solve this? I have a conversation scoped pojo, which calls an asynchronous method. I would need some solution (or compromise) to display the results of this asynchronous method in the conversation.


          Best regards,
          Jukka


          • 2. Re: Asynchronous Method and AJAX call to the result
            Christian Zeidler Newbie

            Hi There,


            The Problem is: The asynchronous method is processed in a completely new event context and does not have access to the session or conversation context state of the caller.
            So what I did when I was working on this, was to create an application-scoped bean that acts as a data-store. I passed a reference to the bean and a unique id to the asynchronous method, when it finishes its work, the result gets written to the bean. Per Ajax, I then polled a method on the application scoped bean that would check if the result for the given id was done, and would serve it if available.


            We had a similar problem just the other day and solved it by starting our own threads from a bean (not recomended - and even not allowed by J2EE specs I belive - but couldn't realy find a clean explanation on why)


            Hope that helps.


            Best regards,
            Christian

            • 3. Re: Asynchronous Method and AJAX call to the result
              Jukka Kaijansinkko Newbie

              MANY THANKS Christian,
              this was very helpful!


              I now have a conversation scoped stateful EJB session bean which calls an asynchronous method on another (autocreated) component. This asynchronous method does the background process, while the user can continue browsing the page, still in the long-running conversation. Once the background process is complete, its results will be put in an application scoped data-store component like you described, hereafter called result holder, using a map, where the key is the conversationId which was passed earlier to the asynchronous method by the calling conversation component. After storing the results, the asynchronous method raises an asynchoronous event. The observer of this event (also in the result holder) fires an pushEventLister event. The results are then pushed to the view, to avoid any page reload. The conversation can find the results belonging to it from the result holder by using the conversationId and clean up the map entry after it's no longer needed.


              Seems to work alright, but a thing that worries me is the scalability of this solution (the application scoped component and the manual clean up it requires).



              Thanks again,
              Jukka

              • 4. Re: Asynchronous Method and AJAX call to the result
                T. Chaudhri Newbie

                Click HELP for text formatting instructions. Then edit this text and check the preview.


                Yeah guys, I've been doing this same thing for some time now. I had started down the path of creating my own thread that did the background JMX calls. The thread ran in an application scoped bean but then I realized that creating your own threads violates container management and that explains why no Seam services were available in this separate thread. Basically, @Asynchronous does this but Seam knows that it did it and manages the thread.


                Am converting my code to use @Asynchronous (which works well) - but yes, the explanation about this thread running in a different context is still a roadblock - and I'm deciding the only way to SAVE my data after the JMX background process is to put it into the same application scoped bean (i'll use uniqueIDs like you guys have done - good idea). But all this is pretty nasty for a longterm scalable solution (at least I think). I think we could also make use of a Seam Cache and put stuff in there (there is a Seam Cache chapter after the Asynchrous chapter - chapter 23 I believe).


                Mainly, I'm glad that I am doing something that you guys have also done and been playing with - that gives a little assurance :)


                Thanks, later-