2 Replies Latest reply on May 4, 2009 10:04 PM by Enrico Goosen

    Do not start long-running conversations in direct calls to EJBs on async call

    Enrico Goosen Newbie

      I'm getting the above exception after a long running process completes on a Conversation scoped POJO.

      The process gets kicked off from a JSF page. I made it asynchronous because I'm using the a4j:progressBar, which polls this bean.

      1. Please advise me on when/how to start the conversation.

      2. How to handle exceptions thrown from an asynchronous call, currently no error appears to the user. (Added the try/catch now...so will test and see if it displays the error)

      3. I've packaged my application as an EAR running on JBoss-4.2.3GA, do I need to add the @Transcational annotation to the index() method?

      Here's the code

      public class IndexerBean  {
              private Log log;
              static final int BATCH_SIZE = 1000;
              private boolean enabled = false;
              private boolean buttonRendered = true;
              private float index;
              private long total;
              private long percentage = -1;
              EntityManager entityManager;
          FacesMessages facesMessages;
              private Stopwatch stopwatch = new Stopwatch();
              public String startProcess(IndexerBean indexerBean){
                      return null;
              public void index() {
                      Session session = (Session)entityManager.getDelegate();
                      session.setFlushMode(FlushMode.MANUAL); //Disable flush operations
                      session.setCacheMode(CacheMode.IGNORE); //Disable 2nd-level cache operations
                      final FullTextSession ftSession =
                              org.hibernate.search.Search.createFullTextSession( session );
                      indexAllClasses(ftSession, ProductInfo.class);
              @SuppressWarnings("unchecked") @End
              private void indexAllClasses(FullTextSession fullTextSession, Class... entityTypes){
                      try {
                              //First calculate the total records to index
                              for (Class entityType : entityTypes){
                                      Query query = entityManager.createQuery("select COUNT(e) from "+entityType.getName()+" e");
                                      total += (Long)query.getSingleResult();
                              //Perform indexing
                              for (Class entityType : entityTypes){
                                      //read the data from the database
                                      //Scrollable results will avoid loading too many objects in memory
                                      ScrollableResults results = fullTextSession.createCriteria( entityType )
                                      .scroll( ScrollMode.FORWARD_ONLY );
                                      while( results.next() ) {
                                              percentage = (long)((index / total) * 100);
                                              fullTextSession.index( results.get(0) );
                                              if (index % BATCH_SIZE == 0) {
                      } catch (Throwable t) {
                              log.error("Exception during indexing operation.", t);
                              facesMessages.add(Severity.ERROR, "Exception during indexing operation. See log for details.");
              public long getPercentage() {
                      return percentage;
              public long getRunningTime(){
                      return stopwatch.getRunningTime();
              public boolean isEnabled() {
                      return enabled;
              public void setEnabled(boolean enabled) {
                      this.enabled = enabled;
              public boolean isButtonRendered() {
                      return buttonRendered;
              public void setButtonRendered(boolean buttonRendered) {
                      this.buttonRendered = buttonRendered;

        • 1. Re: Do not start long-running conversations in direct calls to EJBs on async call
          Arbi Sookazian Master

          First of all, which component is the EJB?

          @Transactional defaults to REQUIRED, similar to tx support/semantics in EJB3.

          Have you tried moving the @Begin to the startProcess() method (wild guess here).

          If that doesn't work, try to start the LRC via the pages.xml or s:link, if possible (i.e. before the @Asynchronous method call).

          • 2. Re: Do not start long-running conversations in direct calls to EJBs on async call
            Enrico Goosen Newbie

            I'm not using an EJB, so I'm not sure why I got that error.

            I made some changes which seems to have fixed my problems.

            I removed the @Begin(join=true) annotation from the index() method.
            I'm starting the conversation when the user clicks the Start Process button.

            <s:button action="#{indexer.startProcess(indexer)}" rendered="#{indexer.buttonRendered}" value="Start Process" propagation="begin">
                 <a4j:support event="onclick" eventsQueue="async" requestDelay="200" ignoreDupResponses="true" reRender="progressPanel2" ajaxSingle="true"/>

            I kind of based my code around this example, but I didn't like the author's approach of starting the conversation with a button click, and then starting the process with a second button click...strange.

            I don't seem to need the @Transactional annotation, since the process worked fine without it.