12 Replies Latest reply on Feb 6, 2009 12:49 PM by Ronald van Kuijk

    Process State in a Fork not executing correctly

    Phil OMalley Newbie

      Hi, I have a test running that contains multiple nodes including two Process States. JPEG of the Process Definition is at:

      http://picasaweb.google.com/lh/sredir?uname=phil.omalley&target=ALBUM&id=5287822354390912129&authkey=uuhzGmyCK8M&invite=CNzcsOsJ&feat=email

      Process State 1 (LoadSubProcess1) is on the main path of execution. Process State 2 (LoadSubProcess2) is in a fork with two paths. I find I can execute my test fine up to the Process State in the Fork (LoadSubProcess2). My test can traverse fine through the first process State (LoadSubProcess1). When execution gets to the Fork alls well, child tokens are created OK but when execution is called on the transition into LoadSubProcess2 the Sub Process is not entered and the only available transition to this token is "fromLoadSubProcess2" (the transition after LoadSubProcess2). So it looks like the child tokens execution path cannot execute the Sub Process. For this test I've made LoadSubProcess1 & 2 point to the same ProcessDefinition xml so I know the xml is OK. The two other child paths execute fine and complete ok into the join node. The only difference I can see is one Process State call is made from the main execution path and the failing one is made from a child execution path. Does anyone have an idea what I'm doing wrong here? Many thanks for your time & effort.


      The Main Process Definition xml

      <?xml version="1.0" encoding="UTF-8"?>
      <process-definition xmlns="urn:jbpm.org:jpdl-3.2urn:jbpm.org:jpdl-3.2"
       name="SampleProcess">
       <start-state name="Start">
       <transition to="task-node1" name="to task-node1">
       </transition>
       </start-state>
       <task-node name="task-node1" signal="never">
       <task name="taskNametask-node1" />
       <transition to="state0" name="to-state0"></transition>
       </task-node>
       <state name="state0">
       <transition to="LoadSubProcess1" name="toLoadSubProcess1"></transition>
       </state>
       <fork name="fork1">
       <transition to="state1" name="toState1"></transition>
       <transition to="state2" name="to state2"></transition>
       <transition to="state3" name="to state3"></transition>
       </fork>
       <state name="state1">
       <event type="node-leave">
       <action
       class="com.meridianp2p.stf.impl.workflow.ProcessChangeEventNotifier"></action>
       </event>
       <transition to="task-node2" name="to task-node2"></transition>
       </state>
       <state name="state2">
       <event type="node-leave">
       <action
       class="com.meridianp2p.stf.impl.workflow.ProcessChangeEventNotifier"></action>
       </event>
       <transition to="task-node3" name="to task-node3"></transition>
       </state>
       <task-node name="task-node2" signal="never">
       <task name="taskNametask-node2" />
       <transition to="LoadSubProcess2" name="toLoadSubProcess2"></transition>
       </task-node>
       <task-node name="task-node3" signal="never">
       <task name="taskNametask-node3" />
       <transition to="join1" name="from task-node3"></transition>
       </task-node>
       <state name="state3">
       <event type="node-leave">
       <action
       class="com.meridianp2p.stf.impl.workflow.ProcessChangeEventNotifier"></action>
       </event>
       <transition to="task-node4" name="to task-node4"></transition>
       </state>
       <task-node name="task-node4" signal="never">
       <task name="taskNametask-node4" />
       <transition to="state4" name="to state4"></transition>
       </task-node>
       <join name="join1">
       <transition to="taskNode6" name="toTaskNode6"></transition>
       </join>
       <task-node name="task-node5" signal="never">
       <task name="taskNametask-node5" />
       <transition to="join1" name="from task-node5"></transition>
       </task-node>
       <state name="state4">
       <event type="node-enter">
       <action
       class="com.meridianp2p.stf.impl.workflow.ProcessChangeEventNotifier"></action>
       </event>
       <transition to="task-node5" name="to task-node5"></transition>
       </state>
       <process-state name="LoadSubProcess2">
       <sub-process name="LoadSubProcess" />
       <transition to="join1" name="fromLoadSubProcess2"></transition>
       </process-state>
       <task-node name="taskNode6" signal="never">
       <task name="taskNametask-node6" />
       <transition to="End" name="toEnd"></transition>
       </task-node>
       <process-state name="LoadSubProcess1">
       <sub-process name="LoadSubProcess" />
       <transition to="task-nodeA" name="to task-nodeA"></transition>
       </process-state>
      
       <state name="stateA">
       <transition to="fork1" name="toFork1"></transition>
       </state>
      
       <task-node name="task-nodeA" signal="never">
       <task name="taskNametask-nodeA" />
       <transition to="stateA" name="toStateA"></transition>
       </task-node>
       <end-state name="End"></end-state>
      </process-definition>
      


      Sub Process XML
      <?xml version="1.0" encoding="UTF-8"?>
      
      <process-definition xmlns="" name="LoadSubProcess">
      
      
       <start-state name="Start">
       <event type="node-enter" >
       <action class="com.meridianp2p.stf.impl.workflow.ProcessChangeEventNotifier"></action>
       </event>
       <transition to="LoadIncomplete" name="toLoadIncomplete"></transition>
       </start-state>
      
      
       <state name="LoadIncomplete">
       <event type="node-enter" >
       <action class="com.meridianp2p.stf.impl.workflow.ProcessChangeEventNotifier"></action>
       </event>
       <transition to="CreateOrUpdateDoc" name="toCreateOrUpdateDoc"></transition>
       <transition to="CancelTrip" name="toCancelTrip"></transition>
       <transition to="CreateDoc" name="toCreateDoc"></transition>
       <transition to="TripCompleted" name="toTripCompleted"></transition>
       </state>
      
       <task-node name="CreateDoc" signal="never">
       <event type="node-enter" >
       <action class="com.meridianp2p.stf.impl.workflow.WorkflowTaskExecuterImpl"></action>
       </event>
       <task name ="taskCreateDoc" />
       <transition to="LoadIncomplete" name="fromCreateDocToLoadIncomplete"></transition>
       </task-node>
      
       <task-node name="CreateOrUpdateDoc" signal="never">
       <event type="node-enter" >
       <action class="com.meridianp2p.stf.impl.workflow.WorkflowTaskExecuterImpl"></action>
       </event>
       <task name ="taskCreateOrUpdateDoc" />
       <transition to="LoadIncomplete" name="fromCreateOrUpdateDocToLoadIncomplete"></transition>
       </task-node>
      
       <task-node name="CancelTrip" signal="never">
       <event type="node-enter" >
       <action class="com.meridianp2p.stf.impl.workflow.WorkflowTaskExecuterImpl"></action>
       </event>
       <task name ="taskCancelTrip" />
       <transition to="TripConcelled" name="toTripCancelled"></transition>
       </task-node>
      
       <task-node name="TripCompleted" signal="never">
       <event type="node-enter" >
       <action class="com.meridianp2p.stf.impl.workflow.WorkflowTaskExecuterImpl"></action>
       </event>
       <task name ="taskTripCompleted" />
       <transition to="LoadCompleted" name="toLoadCompleted"></transition>
       </task-node>
      
       <state name="LoadCompleted">
       <description>
       Had to add this state node here because the running tests we see the end state is never rested on when this process is used
      as a subprocess
       </description>
       <transition to="LoadEnd" name="toLoadEnd"></transition>
       </state>
      
       <state name="TripConcelled">
       <transition to="TripCancelEnd" name="toTripCancelEnd"></transition>
       </state>
      
      
       <end-state name="TripCancelEnd">
       <event type="node-enter" >
       <action class="com.meridianp2p.stf.impl.workflow.ProcessChangeEventNotifier"></action>
       </event>
       </end-state>
      
       <end-state name="LoadEnd" >
       <event type="node-enter" >
       <action class="com.meridianp2p.stf.impl.workflow.ProcessChangeEventNotifier"></action>
       </event>
       </end-state>
      
      </process-definition>
      


        • 1. Re: Process State in a Fork not executing correctly
          Phil OMalley Newbie

          I should have said I am using jBPM 3.2.3. Thanks, Phil

          • 2. Re: Process State in a Fork not executing correctly
            Ronald van Kuijk Master

            Phill,

            First one thing... if you want things to happen on each node-enter of each node, you can make ONE action/event on the process level (not on the node level. Saves you a lot of typing etc...

            Secondly please create a minimal testcase (unittest) with embedded processes (as a strings) that I can execute and that demonstrates the problem. I've no clue what is going on and do not have the time to create a testcase.

            • 4. Re: Process State in a Fork not executing correctly
              Phil OMalley Newbie

              Hi Ronald thanks for your reply. I've noted your comment about events & actions above node level,very useful thanks.

              Please disregard the previous post as I've simplied the Process Definitions to:


              Main Process Definition (ExpenseReport4)


              And the Sub Process (ClaimVat)

              I've pulled out my code into a simple test block as below. This code goes through the transitions in both the main Proc Def & its two sub processes. The sub processes use the same proc def (ClaimVat.xml). I've included in the codes comments what I would expect to see versus what I am seeing. Any help would be greatly appreciated.
              Best regards, Phil

              String expenseReport4ProcDef="<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
               "<process-definition xmlns=\"urn:jbpm.org:jpdl-3.1\" name=\"ExpenseReport4\">"+
               "<swimlane name=\"Initiator\"></swimlane>"+
               "<start-state name=\"Start SubProcess\">"+
               "<task swimlane=\"Initiator\"></task>"+
               "<transition to=\"ClaimVat1\" name=\"toClaimVat1\"></transition>"+
               "</start-state>"+
               "<process-state name=\"ClaimVat1\">"+
               "<sub-process name=\"ClaimVat\"></sub-process>"+
               "<transition to=\"fork1\" name=\"toFork\"></transition>"+
               "</process-state>"+
              
               "<fork name=\"fork1\">"+
               "<transition to=\"state2\" name=\"toState2\"></transition>"+
               "<transition to=\"state1\" name=\"toState1\"></transition>"+
               "</fork>"+
              
               "<process-state name=\"ClaimVat2\">"+
               "<sub-process name=\"ClaimVat\"/>"+
               "<transition to=\"join1\" name=\"fromClaimVat2\"></transition>"+
               "</process-state>"+
              
               "<task-node name=\"taskNode1\">"+
               "<transition to=\"join1\" name=\"fromTaskNode1\"></transition>"+
               "</task-node>"+
              
               "<join name=\"join1\">"+
               "<transition to=\"End\" name=\"toEnd\"></transition>"+
               "</join>"+
              
               "<state name=\"state1\">"+
               "<transition to=\"taskNode1\" name=\"toTaskNode1\"></transition>"+
               "</state>"+
              
               "<state name=\"state2\">"+
               "<transition to=\"ClaimVat2\" name=\"toClaimVat2\"></transition>"+
               "<transition to=\"join1\" name=\"fromState1\"></transition>"+
               "</state>"+
               "<end-state name=\"End\"></end-state>"+
               "</process-definition>";
              
               String claimVatProcDef="<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
              
               "<process-definition xmlns=\"\" name=\"ClaimVat\">"+
              
               "<start-state name=\"ClaimSubmitted\">"+
               "<transition to=\"ReviewClaim\" name=\"toReviewClaim\"></transition>"+
               "</start-state>"+
              
              
               "<task-node name=\"ReviewClaim\" signal=\"never\" >"+
               "<task name =\"taskReviewClaim\" ></task>"+
               "<transition to=\"ClaimReviewed\" name=\"toClaimReviewed\"></transition>"+
               "</task-node>"+
              
               "<state name=\"ClaimReviewed\" >"+
               "<transition to=\"ClaimArchived\" name=\"toClaimArchived\"></transition>"+
               "</state>"+
              
               "<end-state name=\"ClaimArchived\" >"+
               "</end-state>"+
              
               "</process-definition>";
              
               ProcessDefinition processDefinition = null;
              
               processDefinition = ProcessDefinition.parseXmlString(expenseReport4ProcDef);
               context.deployProcessDefinition(processDefinition);
              
               processDefinition = ProcessDefinition.parseXmlString(claimVatProcDef);
               context.deployProcessDefinition(processDefinition);
              
               ProcessInstance procInstance = context.newProcessInstanceForUpdate("ExpenseReport4");
              
               String[] processTransitions = {"toClaimReviewed", "toClaimArchived", "toClaimVat2","toTaskNode1" ,"toClaimReviewed", "toClaimArchived"};
              
               procInstance.signal("toClaimVat1");
               procInstance.getRootToken().getSubProcessInstance().getRootToken().getAvailableTransitions(); //This returns transition "toClaimReviewed" as expected. This is correct.
               procInstance.getRootToken().getSubProcessInstance().signal("toClaimReviewed");
               procInstance.getRootToken().getSubProcessInstance().signal("toClaimArchived");
               procInstance.getRootToken().getChild("toState1").signal("toTaskNode1");
               procInstance.getRootToken().getChild("toState2").signal("toClaimVat2");
               procInstance.getRootToken().getChild("toState2").getAvailableTransitions();//this should contain "toClaimReviewed" but only contains the transition "fromClaimVat2" after
               // Sub Process. The only difference I can see between the execution of this sub process and the one above is this
              // sub process is being executed from a child
               // execution path,whereas the sub process that works as expected is the one that is executed from the root execution path.
              


              • 6. Re: Process State in a Fork not executing correctly
                Phil OMalley Newbie

                Hi Ronald, I don't wish to appear pushy but have you had a chance to look at this? Thanks, Phil

                • 9. Re: Process State in a Fork not executing correctly
                  Ronald van Kuijk Master

                  ok, first of all, next time make a real unittest by extending AbstractDBTestCase (took me 15 minutes now including correcting things like first deploying the subprocess and then the main process.)

                  Secondly, you describe something in text where there is no code for... make real assertions so I can explicitly see what you expect.

                  Ok, now the results of the jury... Why do you expect the transition of a subprocess be in the transitions list of the process-state node? That is at least what I think you expect....

                  • 10. Re: Process State in a Fork not executing correctly
                    Phil OMalley Newbie

                    Thanks Ronald, sorry, I didn't know about AbstractDBTestCase , I'll add the assertions asap and get back to you, my problem will hopefully be clearer then. Thanks, Phil

                    • 11. Re: Process State in a Fork not executing correctly
                      Phil OMalley Newbie

                      Hi Ronald, I had a think about what you said and its pointed me to the solution, I was looking for the transitions in the wrong Token, When I get the sub process at the token and get that token the transitions are present and correct. many thanks for you time and patience. Phil