5 Replies Latest reply on Feb 4, 2008 3:38 AM by Danielius Jurna

    Error in leaveNode and SubProcess

    Danielius Jurna Newbie

      I'm having strange error while using sub proces and leaveNode in actions. Here is simplified example.
      Main process definition:

      <?xml version="1.0" encoding="UTF-8"?>
      <process-definition name="testParent">
       <start-state name="start">
       <transition to="state"/>
       </start-state>
       <state name="state">
       <event type="node-enter">
       <action class="org.mule.providers.bpm.jbpm.actions.Continue"/>
       </event>
       <transition to="subProcess"/>
       </state>
       <process-state name="subProcess">
       <sub-process name="testSubProcess"/>
       <transition to="end"/>
       </process-state>
       <end-state name="end"/>
      </process-definition>
      

      Sub process definition:
      <?xml version="1.0" encoding="UTF-8"?>
      <process-definition name="testSubProcess">
       <start-state name="start">
       <transition to="testState"/>
       </start-state>
       <state name="testState">
       <event type="node-enter">
       <action class="org.mule.providers.bpm.jbpm.actions.Continue"/>
       </event>
       <transition to="end"/>
       </state>
       <end-state name="end"/>
      </process-definition>
      

      org.mule.providers.bpm.jbpm.actions.Continue implementation:
       public void execute(ExecutionContext executionContext) throws Exception
       {
       executionContext.leaveNode();
       }
      


      When executing this process, engine throws an error:
      org.jbpm.JbpmException: can't continue execution on locked tokens. signalling the same token that executes an action is not allowed
       at org.jbpm.graph.exe.Token.signal(Token.java:168)
       at org.jbpm.graph.exe.Token.signal(Token.java:154)
       at org.jbpm.graph.exe.ProcessInstance.end(ProcessInstance.java:274)
       at org.jbpm.graph.exe.ProcessInstance.end(ProcessInstance.java:248)
       at org.jbpm.graph.exe.Token.notifyParentOfTokenEnd(Token.java:275)
       at org.jbpm.graph.exe.Token.end(Token.java:247)
       at org.jbpm.graph.exe.Token.end(Token.java:197)
       at org.jbpm.graph.node.EndState.execute(EndState.java:46)
       at org.jbpm.graph.def.Node.enter(Node.java:316)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:157)
       at org.jbpm.graph.def.Node$$EnhancerByCGLIB$$9bffe16d.enter(<generated>)
       at org.jbpm.graph.def.Transition.take(Transition.java:119)
       at org.jbpm.graph.def.Node.leave(Node.java:383)
       at org.jbpm.graph.def.Node.leave(Node.java:347)
       at org.jbpm.graph.exe.ExecutionContext.leaveNode(ExecutionContext.java:120)
       at org.mule.providers.bpm.jbpm.actions.Continue.execute(Continue.java:26)
       at org.jbpm.graph.def.Action.execute(Action.java:123)
       at org.jbpm.graph.def.GraphElement.executeAction(GraphElement.java:235)
       at org.jbpm.graph.def.GraphElement.executeActions(GraphElement.java:212)
       at org.jbpm.graph.def.GraphElement.fireAndPropagateEvent(GraphElement.java:182)
       at org.jbpm.graph.def.GraphElement.fireEvent(GraphElement.java:166)
       at org.jbpm.graph.def.Node.enter(Node.java:301)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:157)
       at org.jbpm.graph.def.Node$$EnhancerByCGLIB$$9bffe16d.enter(<generated>)
       at org.jbpm.graph.def.Transition.take(Transition.java:119)
       at org.jbpm.graph.def.Node.leave(Node.java:383)
       at org.jbpm.graph.node.StartState.leave(StartState.java:70)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:157)
       at org.jbpm.graph.def.Node$$EnhancerByCGLIB$$9bffe16d.leave(<generated>)
       at org.jbpm.graph.exe.Token.signal(Token.java:178)
       at org.jbpm.graph.exe.Token.signal(Token.java:123)
       at org.jbpm.graph.exe.ProcessInstance.signal(ProcessInstance.java:217)
       at org.jbpm.graph.node.ProcessState.execute(ProcessState.java:141)
       at org.jbpm.graph.def.Node.enter(Node.java:316)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:157)
       at org.jbpm.graph.def.Node$$EnhancerByCGLIB$$9bffe16d.enter(<generated>)
       at org.jbpm.graph.def.Transition.take(Transition.java:119)
       at org.jbpm.graph.def.Node.leave(Node.java:383)
       at org.jbpm.graph.def.Node.leave(Node.java:347)
       at org.jbpm.graph.exe.ExecutionContext.leaveNode(ExecutionContext.java:120)
       at org.mule.providers.bpm.jbpm.actions.Continue.execute(Continue.java:26)
       at org.jbpm.graph.def.Action.execute(Action.java:123)
       at org.jbpm.graph.def.GraphElement.executeAction(GraphElement.java:235)
       at org.jbpm.graph.def.GraphElement.executeActions(GraphElement.java:212)
       at org.jbpm.graph.def.GraphElement.fireAndPropagateEvent(GraphElement.java:182)
       at org.jbpm.graph.def.GraphElement.fireEvent(GraphElement.java:166)
       at org.jbpm.graph.def.Node.enter(Node.java:301)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:157)
       at org.jbpm.graph.def.Node$$EnhancerByCGLIB$$9bffe16d.enter(<generated>)
       at org.jbpm.graph.def.Transition.take(Transition.java:119)
       at org.jbpm.graph.def.Node.leave(Node.java:383)
       at org.jbpm.graph.node.StartState.leave(StartState.java:70)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:157)
       at org.jbpm.graph.def.Node$$EnhancerByCGLIB$$9bffe16d.leave(<generated>)
       at org.jbpm.graph.exe.Token.signal(Token.java:178)
       at org.jbpm.graph.exe.Token.signal(Token.java:123)
       at org.jbpm.graph.exe.ProcessInstance.signal(ProcessInstance.java:217)
       at net.metasite.bdm.router.test.TestSubProcessBug.testBug(TestSubProcessBug.java:16)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at junit.framework.TestCase.runTest(TestCase.java:154)
       at junit.framework.TestCase.runBare(TestCase.java:127)
       at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:69)
       at junit.framework.TestResult$1.protect(TestResult.java:106)
       at junit.framework.TestResult.runProtected(TestResult.java:124)
       at junit.framework.TestResult.run(TestResult.java:109)
       at junit.framework.TestCase.run(TestCase.java:118)
       at junit.framework.TestSuite.runTest(TestSuite.java:208)
       at junit.framework.TestSuite.run(TestSuite.java:203)
       at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
       at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
       at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
      


      Is this a bug in JBpm or I'm doing something wrong?

        • 1. Re: Error in leaveNode and SubProcess
          Jiri Pechanec Apprentice

          Hi,

          what exactly do you want to achieve? Did you tried not to call the method?

          J.

          • 2. Re: Error in leaveNode and SubProcess
            Danielius Jurna Newbie

            Yes, if I don't call leaveNode, everything works fine. But we are having this error in our real workflow.
            his is only sample workflow, which reproduces the same error we are having. It does nothing.
            The main idea is that if process doesn't enter wait state (all actions call leaveNode()), parent token is locked and you get this exception.

            • 3. Re: Error in leaveNode and SubProcess
              Danielius Jurna Newbie

              Here is unit test case which reproduces this error:

              public class TestSubProcessBug extends TestCase{
              
               public void testBug() {
               ProcessDefinition subDefinition = ProcessDefinition.parseXmlString("<?xml version='1.0' encoding='UTF-8'?>"+
               "<process-definition name='testSubProcess'>"+
               " <start-state name='start'>"+
               " <transition to='testState'/>"+
               " </start-state>"+
               " <state name='testState'>"+
               " <event type='node-enter'>"+
               " <script>"+
               " executionContext.leaveNode();"+
               " </script>"+
               " </event>"+
               " <transition to='end'/>"+
               " </state>"+
               " <end-state name='end'/>"+
               "</process-definition>");
               ProcessDefinition definition = ProcessDefinition.parseXmlString("<?xml version='1.0' encoding='UTF-8'?>"+
               "<process-definition name='testParent'>"+
               " <start-state name='start'>"+
               " <transition to='state'/>"+
               " </start-state>"+
               " <state name='state'>"+
               " <event type='node-enter'>"+
               " <script>"+
               " executionContext.leaveNode();"+
               " </script>"+
               " </event>"+
               " <transition to='subProcess'/>"+
               " </state>"+
               " <process-state name='subProcess'>"+
               " <sub-process name='testSubProcess'/>"+
               " <transition to='end'/>"+
               " </process-state>"+
               " <end-state name='end'/>"+
               "</process-definition>");
               ProcessState processState = (ProcessState) definition.getNode("subProcess");
               processState.setSubProcessDefinition(subDefinition);
               ProcessInstance processInstance = new ProcessInstance(definition);
               processInstance.signal();
               }
              
              }
              


              • 4. Re: Error in leaveNode and SubProcess
                Jiri Pechanec Apprentice

                Hi,

                this is a feature, not a bug, see JavaDoc
                http://docs.jboss.com/jbpm/v3/javadoc/org/jbpm/graph/exe/ExecutionContext.html#leaveNode()


                leaveNode
                public void leaveNode()
                leave this node over the default transition. This method is only available on node actions. Not on actions that are executed on events. Actions on events cannot change the flow of execution.


                • 5. Re: Error in leaveNode and SubProcess
                  Danielius Jurna Newbie

                  Thank you very much for your reply. After changing process definition as you suggested, everything works fine. Here is changed unit test, which completes successfuly:

                  public class TestSubProcessBug extends TestCase{
                  
                   public void testBug() {
                   ProcessDefinition subDefinition = ProcessDefinition.parseXmlString("<?xml version='1.0' encoding='UTF-8'?>"+
                   "<process-definition name='testSubProcess'>"+
                   " <start-state name='start'>"+
                   " <transition to='testState'/>"+
                   " </start-state>"+
                   " <node name='testState'>"+
                   " <script>"+
                   " executionContext.leaveNode();"+
                   " </script>"+
                   " <transition to='end'/>"+
                   " </node>"+
                   " <end-state name='end'/>"+
                   "</process-definition>");
                   ProcessDefinition definition = ProcessDefinition.parseXmlString("<?xml version='1.0' encoding='UTF-8'?>"+
                   "<process-definition name='testParent'>"+
                   " <start-state name='start'>"+
                   " <transition to='state'/>"+
                   " </start-state>"+
                   " <node name='state'>"+
                   " <script>"+
                   " executionContext.leaveNode();"+
                   " </script>"+
                   " <transition to='subProcess'/>"+
                   " </node>"+
                   " <process-state name='subProcess'>"+
                   " <sub-process name='testSubProcess'/>"+
                   " <transition to='end'/>"+
                   " </process-state>"+
                   " <end-state name='end'/>"+
                   "</process-definition>");
                   ProcessState processState = (ProcessState) definition.getNode("subProcess");
                   processState.setSubProcessDefinition(subDefinition);
                   ProcessInstance processInstance = new ProcessInstance(definition);
                   processInstance.signal();
                   }
                  
                  }