8 Replies Latest reply on Dec 9, 2009 10:52 AM by Alan Nisbet

    async fork

    Peter Schrammel Newbie

      Hi,

      I've got a problem to get async nodes right. I read on JIRA ther once was an issue with this but got resolved. So I wonder where my mistake is.
      JBPM Version is 3.2.3

      The process definition:

      <?xml version="1.0" encoding="UTF-8"?>
      <process-definition xmlns="" name="TestThreadSkript">
       <start-state name="start-state1">
       <transition to="fork1"></transition>
       </start-state>
       <fork name="fork1">
       <transition to="node1" name="to node1"></transition>
       <transition to="node2" name="to node2"></transition>
       <transition to="node3" name="to node3"></transition>
       </fork>
       <node name="node1" async="true">
       <script name="do it1">
       <expression>
       String nodename=executionContext.getNode().getName();
       for(int i=0;i<=7;i++){
       Thread.currentThread().sleep(1000);
       System.out.println(nodename + " is waiting (" +i+")");
       }
       System.out.println("loop done");
      
       executionContext.leaveNode();
       </expression>
       </script>
       <transition to="join1"></transition>
       </node>
      
       <node name="node2" async="true">
       <script name="do it2">
       <expression>
       String nodename=executionContext.getNode().getName();
      
       for(int i=0;i<=7;i++){
       Thread.currentThread().sleep(1000);
       System.out.println(nodename + " is waiting (" +i+")");
       }
       System.out.println("loop done");
      
       executionContext.leaveNode();
       </expression>
       </script>
       <transition to="join1"></transition>
       </node>
      
       <node name="node3" async="true">
       <script name="do it3">
       <expression>
       String nodename=executionContext.getNode().getName();
      
       for(int i=0;i<=7;i++){
       Thread.currentThread().sleep(1000);
       System.out.println(nodename + " is waiting (" +i+")");
       }
       System.out.println("loop done");
      
       executionContext.leaveNode();
       </expression>
       </script>
       <transition to="join1"></transition>
       </node>
      
      
       <join name="join1" >
       <transition to="end-state1"></transition>
       </join>
      
       <end-state name="end-state1"></end-state>
      
      </process-definition>
      
      


      This throws an exception
      org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)

      This happens when the second thread enters the join node and hibernate tries to update a token.

      I tested this with MYSQL and transaction-isolation = REPEATABLE-READ and READ-COMMITTED but nothing helped.

      Where am I wrong?

      Thanks for your help



        • 1. Re: async fork
          Peter Schrammel Newbie

          Ok,
          it seems nobody has an answer (yet).
          But is anybody able to reproduce this?

          I'll give edge a try and report here...

          Peter

          • 2. Re: async fork
            Rainer Buss Newbie

            I have the same problem with a similar small fork- join- process.

            <process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="SimpleFork">
             <start-state name="start-state1">
             <transition to="fork1"></transition>
             </start-state>
             <fork name="fork1">
             <transition to="node1"></transition>
             <transition to="node2" name="to node2"></transition>
             </fork>
             <node name="node1" async="true">
             <action name="action" class="com.sample.action.ContinueActionHandler">
             <message>In Node 1</message>
             </action>
             <transition to="join1" name="to join1"></transition>
             </node>
             <node name="node2" async="true">
             <action name="action" class="com.sample.action.ContinueActionHandler">
             <message>In Node 2</message>
             </action>
             <transition to="join1" name="to join1"></transition>
             </node>
             <join name="join1">
             <transition to="node3"></transition>
             </join>
             <node name="node3">
             <action name="action" class="com.sample.action.ContinueActionHandler" async="false">
             <message>In Node 3</message>
             </action>
             <transition to="end-state1" name="to end-state1"></transition>
             </node>
             <end-state name="end-state1"></end-state>
            </process-definition>
            


            StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.context.exe.ContextInstance#275]
            


            My example uses a simple actionhandler instead of the scripting you use, but that should not matter.

            public class ContinueActionHandler implements ActionHandler {
             private static final long serialVersionUID = 1L;
             String message;
            
             public void execute(ExecutionContext context) throws Exception {
             context.getContextInstance().setVariable("message", message);
             System.out.println("In Message: "+ message);
             if("In Node 1".equals(message)) {
             this.spendSomeTime();
             System.out.println("After spent some time: "+ message);
             }
             System.out.println("Before leaving: "+ message);
             context.leaveNode();
             }
             private void spendSomeTime() {
             for(int i=0; i< 2000000;i++) {
             String dd = "do something";
             }
             }
            }
            

            In my opinion this problem is an essential one, because using async- nodes in fork- join should be AFAIK the way to execute actions asynchronously.

            I started using jBPM a year ago with version 3.2.1 (AS 4.2.1) implementing a non interactive workflow executing several activities. I had problems with parallel executions and implemented a custom fork- join mechanism as a workaround. (I assumed I did not understand jBPM correctly especially because the suite was delivered with AS 4.0). Unfortunately my solution is neither compatible with 3.2.2 nor with 3.2.3, because the behaviour of the standard join- node was modified.
            Now our workflow implementation has to be extended and I want to refactor the code using only standards.

            I started tests with a small process as you did and installed it in a new clean environment: I use a customized enterprise- ear delivered with jbpm-jpdl-3.2.3, a fresh installed jboss 4.2.3 GA server and a new schema on a Oracle xe database. (The same error I got using the hsql- database configured in the Jboss- server of the jpdl- suite)

            Unfortunately I did not find any jpdl- example describing the scenario. The chapters in manuals about 'Asynchronous continuations' are a little bit vague. Similar scenarios use a node and a task inside the different execution pathes.
            I wonder if nobody uses parallel executions in background or if there is another standard way to solve this with jBPM.

            Has anybody experiences with those items or any idea ? If you want to know more about my environment, I would like to send my configuration files.

            Thanks in advance

            Rainer



            • 3. Re: async fork
              Ronald van Kuijk Master

              Guys,

              In both your async nodes you do the same thing, so they both take the same amount of time to do their work. So both tokens enter the join virtually the same. Can you see what happens if both nodes take a different amount of time?

              • 4. Re: async fork
                Rainer Buss Newbie

                Hi,

                I dont think that both calls of the actionhandler take the same amout of time, only call in first node executes a loop. I tried several things with Thread .. sleep etc. with same result. Writing into database should synchronize concurrent accesses.

                cu

                Rainer

                • 5. Re: async fork
                  Ronald van Kuijk Master

                  yes, I see now... sorry... In tests I never use one class to do two different things.... makes it easier to read....

                  • 6. Re: async fork
                    Alan Nisbet Newbie

                    Bump

                    Has there been any further work on this, I too am seeing the SOE

                    Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.graph.exe.Token#740]
                     at org.hibernate.persister.entity.AbstractEntityPersister.forceVersionIncrement(AbstractEntityPersister.java:1235)
                     at org.hibernate.event.def.AbstractLockUpgradeEventListener.upgradeLock(AbstractLockUpgradeEventListener.java:82)
                     at org.hibernate.event.def.DefaultLockEventListener.onLock(DefaultLockEventListener.java:64)
                     at org.hibernate.impl.SessionImpl.fireLock(SessionImpl.java:584)
                     at org.hibernate.impl.SessionImpl.lock(SessionImpl.java:576)
                     at org.jbpm.graph.node.Join.execute(Join.java:116)
                     at org.jbpm.graph.def.Node.enter(Node.java:319)


                    I have a process with a fork, under which there are 3 sub-processes.

                    I have updated to 3.2.6.SP1 as suggested in previous post.

                    3.2.6.SP1
                    Oracle 10g XE
                    Jboss 4.2.3

                    Any help appreciated!

                    • 7. Re: async fork
                      Alan Nisbet Newbie

                      Also, I have a unit-test which test the process outside the container, without the persistence, it seems to work fine.

                      I'm getting a couple of failure points according to the stacktraces,

                      1 in action handler in the main process (leave node method) - before entering fork.

                      1 in action handler in sub-process (leave node method).

                      Are these SEOs I should be trying to suppress/ignore?

                      • 8. Re: async fork
                        Alan Nisbet Newbie

                        Fixed by updating to 3.3.1.GA and adding lock="pessimistic" to join.

                        Thanks for your help!