7 Replies Latest reply on Mar 6, 2008 11:17 AM by ffernandez

    Successfuly configuring JobExecutorServlet

    mavrides

      Successfuly configuring JobExecutorServlet

      Hi all, firstly let me say that I have been trying to successfuly do this for the past 2 days. I have searched the forums multiple times as well as JIRA and google but nothing seems to serve as a guide for doing this. Through looking at the jpdl-suite console files, I have found a series of steps that seem to work BUT when I try to run a simple process with a fork that has all its nodes marked as "async='true'" I get a series of exceptions.

      Versions:
      JPDL 3.2.2 (jbpm-enterprise.ear)
      JBOSS 4.0.5GA


      I have made the following changes:

      [jbpm-console.war]/WEB-INF/web.xml

      I have changed this:

      <!-- JbpmJobExecutorServlet BEGIN ===
       <servlet>
       <servlet-name>JobExecutorServlet</servlet-name>
       <servlet-class>org.jbpm.job.executor.JobExecutorServlet</servlet-class>
       <load-on-startup>1</load-on-startup>
       </servlet>
       <servlet-mapping>
       <servlet-name>JobExecutorServlet</servlet-name>
       <url-pattern>/jobs</url-pattern>
       </servlet-mapping>
       === JbpmJobExecutorServlet END -->
      


      to this:

      <!-- JbpmJobExecutorServlet BEGIN -->
       <servlet>
       <servlet-name>JobExecutorServlet</servlet-name>
       <servlet-class>org.jbpm.job.executor.JobExecutorServlet</servlet-class>
       <load-on-startup>1</load-on-startup>
       </servlet>
       <servlet-mapping>
       <servlet-name>JobExecutorServlet</servlet-name>
       <url-pattern>/jobs</url-pattern>
       </servlet-mapping>
       <!-- JbpmJobExecutorServlet END -->
      
      


      therefore enabling the JobExecutorServlet.

      Then, in [jbpm-enterprise.ear]\lib\jbpm-configs.jar I changed jbpm.cfg.xml as follows:

      I removed:

       <!-- note that the default job executor needs to be overwritten with a null value -->
       <null name="jbpm.job.executor" />
      


      with this:

      <bean name="jbpm.job.executor" class="org.jbpm.job.executor.JobExecutor">
       <field name="jbpmConfiguration"><ref bean="jbpmConfiguration" /></field>
       <field name="name"><string value="JbpmJobExecutor" /></field>
       <field name="nbrOfThreads"><int value="1" /></field>
       <field name="idleInterval"><int value="5000" /></field>
       <field name="maxIdleInterval"><int value="3600000" /></field> <!-- 1 hour -->
       <field name="historyMaxSize"><int value="20" /></field>
       <field name="maxLockTime"><int value="600000" /></field> <!-- 10 minutes -->
       <field name="lockMonitorInterval"><int value="60000" /></field> <!-- 1 minute -->
       <field name="lockBufferTime"><int value="5000" /></field> <!-- 5 seconds -->
       </bean>
      


      After making these changes I am able to successfully start the server and log into the jbpm console without any exceptions. When I try to run my simple process I get this exception on the first node which is not even part of the fork but it IS marked as "async='true'":

      INFO [com.sample.action.StartActionHandler] Node Name: start
      2007-09-19 17:07:42,359 INFO [com.sample.action.DummyActionHandler] Node Name: node1
      2007-09-19 17:07:42,656 INFO [com.sample.action.DummyTwoActionHandler] Node Name: node2
      2007-09-19 17:07:42,656 INFO [com.sample.action.DummyTwoActionHandler] Number of threads = 1
      2007-09-19 17:07:42,734 INFO [com.sample.action.DummyTwoActionHandler] Node Name: node3
      2007-09-19 17:07:42,765 INFO [com.sample.action.DummyTwoActionHandler] Number of threads = 1
      ERROR [org.hibernate.event.def.AbstractFlushingEventListener] Could not synchronize database state with session
      org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.graph.exe.Token#24]
       at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1699)
       at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2342)
       at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2242)
       at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2542)
       at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92)
       at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
       at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
       at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
       at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
       at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
       at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
       at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
       at org.hibernate.transaction.CacheSynchronization.beforeCompletion(CacheSynchronization.java:59)
       at org.jboss.tm.TransactionImpl.doBeforeCompletion(TransactionImpl.java:1491)
       at org.jboss.tm.TransactionImpl.beforePrepare(TransactionImpl.java:1110)
       at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:324)
       at org.jboss.tm.TxManager.commit(TxManager.java:240)
       at org.jboss.jms.asf.StdServerSession.onMessage(StdServerSession.java:351)
       at org.jboss.mq.SpyMessageConsumer.sessionConsumerProcessMessage(SpyMessageConsumer.java:905)
       at org.jboss.mq.SpyMessageConsumer.addMessage(SpyMessageConsumer.java:170)
       at org.jboss.mq.SpySession.run(SpySession.java:323)
       at org.jboss.jms.asf.StdServerSession.run(StdServerSession.java:194)
       at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:743)
       at java.lang.Thread.run(Thread.java:619)
      2007-09-19 17:07:42,875 ERROR [org.jboss.jms.asf.StdServerSession] failed to commit/rollback
      org.jboss.tm.JBossRollbackException: Unable to commit, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=emma/44, BranchQual=, localId=44] status=STATUS_NO_TRANSACTION; - nested throwable: (org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.graph.exe.Token#24])
       at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:372)
       at org.jboss.tm.TxManager.commit(TxManager.java:240)
       at org.jboss.jms.asf.StdServerSession.onMessage(StdServerSession.java:351)
       at org.jboss.mq.SpyMessageConsumer.sessionConsumerProcessMessage(SpyMessageConsumer.java:905)
       at org.jboss.mq.SpyMessageConsumer.addMessage(SpyMessageConsumer.java:170)
       at org.jboss.mq.SpySession.run(SpySession.java:323)
       at org.jboss.jms.asf.StdServerSession.run(StdServerSession.java:194)
       at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:743)
       at java.lang.Thread.run(Thread.java:619)
      Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.graph.exe.Token#24]
       at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1699)
       at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2342)
       at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2242)
       at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2542)
       at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92)
       at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
       at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
       at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
       at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
       at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
       at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
       at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
       at org.hibernate.transaction.CacheSynchronization.beforeCompletion(CacheSynchronization.java:59)
       at org.jboss.tm.TransactionImpl.doBeforeCompletion(TransactionImpl.java:1491)
       at org.jboss.tm.TransactionImpl.beforePrepare(TransactionImpl.java:1110)
       at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:324)
       ... 8 more
      


      Here is the process definition I am using:

      <?xml version="1.0" encoding="UTF-8"?>
      
      <process-definition
       xmlns="urn:jbpm.org:jpdl-3.2" name="AsyncProcessFork">
       <start-state name="start">
       <transition name="" to="node1"></transition>
       </start-state>
       <node name="node1" async='true'>
       <action class="com.sample.action.DummyActionHandler"></action>
       <transition name="" to="fork1"></transition>
       </node>
       <fork name="fork1">
       <transition name="" to="node2"></transition>
       <transition name="tr2" to="node3"></transition>
       </fork>
       <join name="join1">
       <transition name="" to="node4"></transition>
       </join>
       <node name="node2" async='true'>
       <action class="com.sample.action.DummyTwoActionHandler"></action>
       <transition name="" to="join1"></transition>
       </node>
       <node name="node3" async='true'>
       <action class="com.sample.action.DummyTwoActionHandler"></action>
       <transition name="" to="join1"></transition>
       </node>
       <end-state name="end1"></end-state>
       <node name="node4" async='true'>
       <action class="com.sample.action.DummyTwoActionHandler"></action>
       <transition name="" to="end1"></transition>
       </node>
      </process-definition>
      



      The DummyTwoActionHandler code is this:

      public class DummyTwoActionHandler implements ActionHandler {
      
       static Logger log;
      
       public void execute(ExecutionContext executionContext) throws Exception {
      
       log = Logger.getLogger(this.getClass());
      
       log.info("Node Name: " + executionContext.getNode().getName());
      
      
       //FAILS - JobExecutor is NULL
       JbpmConfiguration jbpmc = JbpmConfiguration.getInstance();
       log.info("Number of threads = " + jbpmc.getJobExecutor().getNbrOfThreads());
      
       executionContext.getNode().leave(executionContext);
       }
      }
      


      The main problem is that this exact process works fine in the jbpm3.2.2-Suite but not on my configured JBOSS4.0.5GA with JPDL3.2.2. This is why I think I have made some error on configuring the JobExecutorServlet. Let me note that I have checked every configuration file between the Suite and my installation and the only difference in that the EJBLocalTimerService in jbpm.cfg.xml in the Suite is commented out. If I do that in my configuration i get a EJB exceptions.

      If anyone has any suggestions on what I am doing wrong in configuring the JobExecutorServlet or any other comments I would appreciate it.

      I can post any other information you may find useful, I just didn't want to make this post even longer!
      Thanks for your help.

        • 1. Re: Successfuly configuring JobExecutorServlet
          kukeltje

          afaik, the suite does not use the enterprise version, but the plain version. The plain version uses the jobexcutor, the enterprise version jms queues (again, afaik)

          So it should not be necessary to use the jobexecutor and post the exceptions you get when running the enterprise version on your JBoss AS

          • 2. Re: Successfuly configuring JobExecutorServlet
            mavrides

            Fair enough. However, is there a reason I am getting the same exceptions no matter if I use the JobExecutor or Jms Queues? Is there a way to overcome the fact that whenever I have a fork with asynchronous nodes I get the stack trace shown above?

            • 3. Re: Successfuly configuring JobExecutorServlet
              mavrides

              Honestly, does no one have any suggestions? Is this such a strange question after all?

              • 4. Re: Successfuly configuring JobExecutorServlet
                msandoz

                Not 100% sure on this but I've had similar problems - I think that on async a job is put in the database for execution to start at the given node. The job executor servlet then picks it up and wants to run it. But since there is already a token lock from the instance running from the console thread, it is unable to perform the needed activities on the token. anyone else come across this?

                • 5. Re: Successfuly configuring JobExecutorServlet

                  Has somebody resolve this issue?

                  Is it not possible the fork/join with the intermediate nodes in async way?

                  Thanks

                  • 6. Re: Successfuly configuring JobExecutorServlet
                    kukeltje

                     

                    Is it not possible the fork/join with the intermediate nodes in async way?


                    You mean async nodes between the fork and the join? If you think this is a problem, please make a unittest for it that demonstrates the problem

                    • 7. Re: Successfuly configuring JobExecutorServlet

                      Here the process:

                      ...
                      <fork name="fork1">
                       <transition to="ibk-df-classifier" name="1"></transition>
                       <transition to="bayes-wf-classfier" name="2"></transition>
                       <transition to="svm-df-classifier" name="3"></transition>
                      </fork>
                      
                      <node name="node1" async="true">
                       <action class="DoHeavyJob1"/>
                       <transition to="join1"></transition>
                      </node>
                      
                      <node name="node2" async="true">
                       <action class="DoHeavyJob2"/>
                       <transition to="join1"></transition>
                      </node>
                      
                      <node name="node3" async="true">
                       <action class="DoHeavyJob3"/>
                       <transition to="join1"></transition>
                      </node>
                      
                      <join name="join1">
                       <transition to="finish"></transition>
                      </join>
                      
                      <node name="finish">
                       <action class="Result"/>
                      </node>
                      ...
                      


                      In have this scene: Intermediate nodes takes long time executing, so I need the async="true" for their concurrent execution, and I cannot execute the "finish" node until ALL intermediate nodes had finished.

                      In the DoHeavyJob1, DoHeavyJob2 and DoHeavyJob3 ActionHandlers, I have coded the
                      executionContext.leaveNode();
                      at the end of the execute method.

                      class DoHeavyJob1{
                       public void execute( ExecutionContext executionContext ) {
                       //Time task Simulation
                       Thread.sleep ( 100000 );
                      
                       executionContext.leaveNode();
                       }//execute
                      }
                      


                      These actions are executed fine with JobExecutor, and I see that are executed in a concurrent way.

                      But, the known org.hibernate.StaleObjectStateException occurs when the last actionHandler makes the leaveNode.

                      Please, is there any way to implement this issue?

                      Thanks