1 2 Previous Next 24 Replies Latest reply on Sep 10, 2009 4:20 PM by kukeltje

    JBPM Nested Fork/Joins Doesn't seem to work

      I am using nested fork/joins, I have 1 within the other. The Fork works, and i get two open tasks visible. However, neither join seems to work and I cannot work out why. Is this a restriction within JBPM? Is there any way to have nested fork/joins?

      When I remove the internal fork/joins and just have a normal start -> fork -> 2 tasks in parallel -> join -> task -> end, it proceeds just fine. But with the inner f/j, it seems to wait on the join, rather than proceeding to the next task.

      Any ideas?

      Many thanks
      Phil

        • 1. Re: JBPM Nested Fork/Joins Doesn't seem to work
          kukeltje

          Should work. Can you make a unittest that demonstrates the problem? Please make the unittest like: http://fisheye.jboss.com/browse/~raw,r=4398/JbpmSvn/jbpm3/trunk/modules/core/src/test/java/org/jbpm/job/executor/JobExecutorDbTest.java

          • 2. Re: JBPM Nested Fork/Joins Doesn't seem to work

            Hi,

            Thanks for the feedback, I will build the junit and get back to you, tho i may have spotted something. Do the internal fork/joins have to be totally self contained? At the moment I have transitions from within the internal f/j that goes to the outer one. Would this cause the issue? Is there anywhere to find a definitive do's/dont's list?

            • 3. Re: JBPM Nested Fork/Joins Doesn't seem to work
              kukeltje

              yes, that is what fully contained/nested means....

              Regarding do's/dont's, this is the most important one, together with 'do not loop for polling the existence of a file' kind of things.

              • 4. Re: JBPM Nested Fork/Joins Doesn't seem to work

                It seems that within my Junit test i can have non-fully contained fork/joins, and that provided i get the correct child token (and childs-child etc) to signal, then it works succesfully.

                Is there any documentation on how taskInstance signalling works? Since I think maybe the problem is more to do with the taskInstance signal, than the token signal.

                • 5. Re: JBPM Nested Fork/Joins Doesn't seem to work
                  kukeltje

                  If you manually signal tokens, a non fully nested fork/join might work, but that behaviour is not guaranteed to stay/be the same over versions.

                  What do you mean by 'how task signalling works'? You end a task and the token continues if the other attributes on the task node allow it to. By default, ending the task makes it take the specified transition. So nothing special to it.

                  • 6. Re: JBPM Nested Fork/Joins Doesn't seem to work

                    Im not sure whether the signalling of tasks ie task.signal has the save behaviour as the direct signalling on the token object. Also, is the token object uniquely identified by something other than its name? ie its path parent/child? I am trying to work out thru junits what the constraints are, but it doesnt seem to be limited to fully nested f/j's.

                    It is all rather bizarre. Since, I have managed to see that all child tokens of a parent token are at the join, yet the parent is still at the fork. I didnt think that this should happed.

                    Finally, I have seen instances where the child tokens go past the join, yet the parent token is still at the fork...

                    • 7. Re: JBPM Nested Fork/Joins Doesn't seem to work
                      kukeltje

                      if you have the unittest, please post it. Then I can see what you do instead of guessing or reading text ;-)

                      • 8. Re: JBPM Nested Fork/Joins Doesn't seem to work

                        Thanks, Junit and jbpm xml file are below.


                        package com.jpmorgan.orion.workflow.ny;

                        import org.jbpm.graph.def.ProcessDefinition;
                        import org.jbpm.graph.exe.ProcessInstance;
                        import org.junit.Test;

                        import com.jpmorgan.orion.workflow.service.BaseManagerTestCase;

                        /**
                        * Phil Segal
                        * @date @14 May 2009
                        */
                        public class JoinsTest extends BaseManagerTestCase {

                        @Test
                        public void testNoAdjustments() throws Exception {
                        ProcessDefinition def = ProcessDefinition.parseXmlResource("workflow/ny-workflow-2/processdefinition.xml");

                        assertNotNull("Definition should not be null", def);

                        ProcessInstance instance = new ProcessInstance(def);
                        assertEquals("Def should be at start",
                        "start-daily-pnl",
                        instance.getRootToken().getNode().getName());

                        instance.signal("default");

                        instance.getRootToken().getChild("signoff").signal("signoff pnl");
                        instance.getRootToken().getChild("propose").signal("cancel fork1");

                        assertEquals("Def should be at auto approve",
                        "auto-signoff-adj",
                        instance.getRootToken().getNode().getName()
                        );
                        instance.signal("leave-asa");

                        assertEquals("Def should be at ds feeds",
                        "downstream-feeds",
                        instance.getRootToken().getNode().getName());
                        instance.signal("leave-dsf");

                        assertEquals("Def should be at fork 3",
                        "fork3",
                        instance.getRootToken().getNode().getName());

                        instance.getRootToken().getChild("reviewed").signal("review");
                        instance.getRootToken().getChild("unsignoff").signal("cancel");

                        // instance.signal();

                        assertTrue("Instance has ended", instance.hasEnded());
                        }

                        @Test
                        public void testWithAdjustmentsProcessNoApprove() throws Exception
                        {
                        ProcessDefinition def = ProcessDefinition.parseXmlResource("workflow/ny-workflow-2/processdefinition.xml");

                        assertNotNull("Definition should not be null", def);

                        ProcessInstance instance = new ProcessInstance(def);
                        assertEquals("Def should be at start",
                        "start-daily-pnl",
                        instance.getRootToken().getNode().getName());

                        instance.signal("default");

                        instance.getRootToken().getChild("propose").signal("propose an adjustment");

                        assertEquals("Def should be at fork2",
                        "fork2",
                        instance.getRootToken().getChild("propose").getNode().getName());

                        instance.getRootToken().getChild("propose").getChild("propose").signal("cancel");
                        instance.getRootToken().getChild("propose").getChild("approve").signal("cancel");

                        assertEquals("child should be at join1",
                        "join1",
                        instance.getRootToken().getChild("propose").getNode().getName());
                        assertEquals("parent should be at fork1",
                        "fork1",
                        instance.getRootToken().getNode().getName());

                        instance.getRootToken().getChild("signoff").signal("signoff pnl");

                        assertEquals("Def should be at auto approve",
                        "auto-signoff-adj",
                        instance.getRootToken().getNode().getName()
                        );

                        }
                        @Test
                        public void testWithMultipleAdjustmentsProcessNoApprove() throws Exception
                        {
                        ProcessDefinition def = ProcessDefinition.parseXmlResource("workflow/ny-workflow-2/processdefinition.xml");

                        assertNotNull("Definition should not be null", def);

                        ProcessInstance instance = new ProcessInstance(def);
                        assertEquals("Def should be at start",
                        "start-daily-pnl",
                        instance.getRootToken().getNode().getName());

                        instance.signal("default");

                        instance.getRootToken().getChild("propose").signal("propose an adjustment");

                        assertEquals("Def should be at fork2",
                        "fork2",
                        instance.getRootToken().getChild("propose").getNode().getName());

                        instance.getRootToken().getChild("propose").getChild("propose").signal("propose an adjustment");

                        // Use either just cancel, or both approve and default signals for approve signalling...
                        // instance.getRootToken().getChild("propose").getChild("approve").signal("cancel");
                        instance.getRootToken().getChild("propose").getChild("approve").signal("approve");
                        instance.getRootToken().getChild("propose").getChild("approve").signal("default");


                        instance.getRootToken().getChild("propose").getChild("propose").getChild("propose").signal("cancel");
                        instance.getRootToken().getChild("propose").getChild("propose").getChild("approve").signal("cancel");

                        assertEquals("propose/propose should be at join1",
                        "join1",
                        instance.getRootToken().getChild("propose").getChild("propose").getNode().getName());
                        assertEquals("propose/approve should be at join2",
                        "join2",
                        instance.getRootToken().getChild("propose").getChild("approve").getNode().getName());

                        assertEquals("parent should be at fork1",
                        "fork1",
                        instance.getRootToken().getNode().getName());

                        assertEquals("propose should be at join1",
                        "join1",
                        instance.getRootToken().getChild("propose").getNode().getName());


                        instance.getRootToken().getChild("signoff").signal("signoff pnl");
                        assertEquals("signoff should be at join1",
                        "join1",
                        instance.getRootToken().getChild("signoff").getNode().getName());

                        // instance.getRootToken().getChild("propose").getChild("propose").getChild("propose").signal("cancel");
                        // instance.getRootToken().getChild("propose").getChild("propose").getChild("propose").signal("propose an adjustment");
                        // instance.getRootToken().getChild("propose").getChild("propose").getChild("propose").getChild("propose").signal("cancel fork1");
                        // instance.getRootToken().getChild("propose").getChild("propose").getChild("approve").signal("cancel fork1");
                        // instance.getRootToken().getChild("propose").getChild("propose").getChild("propose").getChild("approve").signal("cancel fork1");

                        assertEquals("Def should be at auto approve",
                        "auto-signoff-adj",
                        instance.getRootToken().getNode().getName()
                        );

                        }

                        }


                        ____________________________________________________
                        processdefinition

                        <?xml version="1.0" encoding="UTF-8"?>

                        <process-definition xmlns="" name="ny-workflow-2">

                        <start-state name="start-daily-pnl">

                        </start-state>

                        <task-node name="signoff-pnl">

                        <!-- timer name="signoff-timer" duedate="1 minute" repeat="true">
                        <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                        signOffTimerAction
                        jbpmConfiguration

                        </timer-->
                        <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                        pnlSignOffMOAssignmentHandler
                        jbpmConfiguration


                        <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                        signOffMultiAction
                        jbpmConfiguration




                        <!-- cancel-timer name="signoff-timer"/-->

                        </task-node>

                        <task-node name="propose-adjustments">

                        <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                        proposeAdjustmentAssignmentHandler
                        jbpmConfiguration


                        <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                        proposeAdjustmentsAction
                        jbpmConfiguration






                        </task-node>

                        <task-node name="approve-reject-adj">

                        <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                        approveRejectAdjustmentAssignmentHandler
                        jbpmConfiguration






                        </task-node>

                        <!-- Reject select adjustment(s) -->

                        <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                        rejectAdjustmentsAction
                        jbpmConfiguration




                        <task-node name="review">

                        <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                        reviewPnlAssignmentHandler
                        jbpmConfiguration


                        <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                        reviewPnlAction
                        jbpmConfiguration




                        </task-node>


                        <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                        autoApproveAdjustmentsAction
                        jbpmConfiguration















                        <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                        approveAdjustmentsAction
                        jbpmConfiguration









                        <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                        downstreamFeedsAction
                        jbpmConfiguration




                        <task-node name="unsignoff-pnl">

                        <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                        pnlSignOffMOAssignmentHandler
                        jbpmConfiguration


                        <action config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                        unsignoffAction
                        jbpmConfiguration


                        <!-- timer name="unsignoff-timer" duedate="1 business second" repeat="true">
                        <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                        unsignOffTimerAction
                        jbpmConfiguration

                        </timer-->


                        <!--cancel-timer name="unsignoff-timer"/-->


                        <!--cancel-timer name="unsignoff-timer"/-->

                        </task-node>














                        <end-state name="end-daily-pnl"></end-state>

                        </process-definition>

                        • 9. Re: JBPM Nested Fork/Joins Doesn't seem to work

                          2nd time lucky...

                          <?xml version="1.0" encoding="UTF-8"?>

                          <process-definition xmlns="" name="ny-workflow-2">

                          <start-state name="start-daily-pnl">

                          </start-state>

                          <task-node name="signoff-pnl">

                          <!-- timer name="signoff-timer" duedate="1 minute" repeat="true">
                          <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                          signOffTimerAction
                          jbpmConfiguration

                          </timer-->
                          <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                          pnlSignOffMOAssignmentHandler
                          jbpmConfiguration


                          <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                          signOffMultiAction
                          jbpmConfiguration




                          <!-- cancel-timer name="signoff-timer"/-->

                          </task-node>

                          <task-node name="propose-adjustments">

                          <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                          proposeAdjustmentAssignmentHandler
                          jbpmConfiguration


                          <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                          proposeAdjustmentsAction
                          jbpmConfiguration






                          </task-node>

                          <task-node name="approve-reject-adj">

                          <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                          approveRejectAdjustmentAssignmentHandler
                          jbpmConfiguration






                          </task-node>

                          <!-- Reject select adjustment(s) -->

                          <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                          rejectAdjustmentsAction
                          jbpmConfiguration




                          <task-node name="review">

                          <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                          reviewPnlAssignmentHandler
                          jbpmConfiguration


                          <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                          reviewPnlAction
                          jbpmConfiguration




                          </task-node>


                          <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                          autoApproveAdjustmentsAction
                          jbpmConfiguration















                          <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                          approveAdjustmentsAction
                          jbpmConfiguration









                          <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                          downstreamFeedsAction
                          jbpmConfiguration




                          <task-node name="unsignoff-pnl">

                          <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                          pnlSignOffMOAssignmentHandler
                          jbpmConfiguration


                          <action config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                          unsignoffAction
                          jbpmConfiguration


                          <!-- timer name="unsignoff-timer" duedate="1 business second" repeat="true">
                          <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                          unsignOffTimerAction
                          jbpmConfiguration

                          </timer-->


                          <!--cancel-timer name="unsignoff-timer"/-->


                          <!--cancel-timer name="unsignoff-timer"/-->

                          </task-node>














                          <end-state name="end-daily-pnl"></end-state>

                          </process-definition>

                          • 10. Re: JBPM Nested Fork/Joins Doesn't seem to work

                            sorry, im new to all this :)

                            <?xml version="1.0" encoding="UTF-8"?>
                            
                            <process-definition xmlns="" name="ny-workflow-2">
                            
                             <start-state name="start-daily-pnl">
                             <transition to="fork1" name="default"></transition>
                             </start-state>
                            
                             <task-node name="signoff-pnl">
                             <task name="Sign Off Daily PNL" description="signoff">
                             <!-- timer name="signoff-timer" duedate="1 minute" repeat="true">
                             <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                             <beanName>signOffTimerAction</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </action>
                             </timer-->
                             <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                             <beanName>pnlSignOffMOAssignmentHandler</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </assignment>
                             <event type="task-end">
                             <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                             <beanName>signOffMultiAction</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </action>
                             </event>
                             </task>
                             <transition to="join1" name="signoff pnl">
                             <!-- cancel-timer name="signoff-timer"/-->
                             </transition>
                             </task-node>
                            
                             <task-node name="propose-adjustments">
                             <task name="Propose Adjustments" description="proposeAdjustment">
                             <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                             <beanName>proposeAdjustmentAssignmentHandler</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </assignment>
                             <event type="task-end">
                             <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                             <beanName>proposeAdjustmentsAction</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </action>
                             </event>
                             </task>
                             <transition name="propose an adjustment" to="fork2"></transition>
                             <transition name="cancel fork1" to="join1"></transition>
                             <transition name="cancel" to="join2"></transition>
                             </task-node>
                            
                             <task-node name="approve-reject-adj">
                             <task name="Approve Adjustments" description="adjustmentDecision">
                             <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                             <beanName>approveRejectAdjustmentAssignmentHandler</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </assignment>
                             </task>
                             <transition to="reject-adjustment" name="reject"></transition>
                             <transition to="approve-adjustment" name="approve"></transition>
                             <transition to="join1" name="cancel fork1"></transition>
                             <transition to="join2" name="cancel"></transition>
                             </task-node>
                            
                             <!-- Reject select adjustment(s) -->
                             <node name="reject-adjustment">
                             <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                             <beanName>rejectAdjustmentsAction</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </action>
                             <transition name="default" to="join2"></transition>
                             </node>
                            
                             <task-node name="review">
                             <task name="Review Daily PnL" description="reviewPNL">
                             <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                             <beanName>reviewPnlAssignmentHandler</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </assignment>
                             <event type="task-end">
                             <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                             <beanName>reviewPnlAction</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </action>
                             </event>
                             </task>
                             <transition name="review" to="join3"></transition>
                             </task-node>
                            
                             <node name="auto-signoff-adj">
                             <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                             <beanName>autoApproveAdjustmentsAction</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </action>
                             <transition name="leave-asa" to="downstream-feeds"></transition>
                             </node>
                            
                             <fork name="fork1">
                             <transition name="propose" to="propose-adjustments"></transition>
                             <transition name="signoff" to="signoff-pnl"></transition>
                             </fork>
                            
                             <fork name="fork2">
                             <transition name="propose" to="propose-adjustments"></transition>
                             <transition name="approve" to="approve-reject-adj"></transition>
                             </fork>
                            
                             <node name="approve-adjustment">
                             <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                             <beanName>approveAdjustmentsAction</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </action>
                             <transition name="default" to="join2"></transition>
                             </node>
                            
                             <join name="join1">
                             <transition name="default" to="auto-signoff-adj"></transition>
                             </join>
                            
                             <node name="downstream-feeds">
                             <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                             <beanName>downstreamFeedsAction</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </action>
                             <transition name="leave-dsf" to="fork3"></transition>
                             </node>
                            
                             <task-node name="unsignoff-pnl">
                             <task name="Unsignoff PNL" description="signoff">
                             <assignment config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                             <beanName>pnlSignOffMOAssignmentHandler</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </assignment>
                             <event type="task-end">
                             <action config-type="bean" class="org.springmodules.workflow.jbpm31.JbpmHandler">
                             <beanName>unsignoffAction</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </action>
                             </event>
                             <!-- timer name="unsignoff-timer" duedate="1 business second" repeat="true">
                             <action class="org.springmodules.workflow.jbpm31.JbpmHandler" config-type="bean">
                             <beanName>unsignOffTimerAction</beanName>
                             <factoryKey>jbpmConfiguration</factoryKey>
                             </action>
                             </timer-->
                             </task>
                             <transition to="join3" name="cancel">
                             <!--cancel-timer name="unsignoff-timer"/-->
                             </transition>
                             <transition to="fork1" name="unsignoff">
                             <!--cancel-timer name="unsignoff-timer"/-->
                             </transition>
                             </task-node>
                            
                             <fork name="fork3">
                             <transition to="unsignoff-pnl" name="unsignoff"></transition>
                             <transition to="review" name="reviewed"></transition>
                             </fork>
                            
                             <join name="join3">
                             <transition to="end-daily-pnl" name="default"></transition>
                             </join>
                            
                             <join name="join2">
                             <transition to="join1" name="default"></transition>
                             </join>
                            
                             <end-state name="end-daily-pnl"></end-state>
                            
                            </process-definition>


                            • 11. Re: JBPM Nested Fork/Joins Doesn't seem to work
                              kukeltje

                              nope, not even the second time : -)

                              Use [ c o d e ] [ / c o d e ] tags around it, without the spaces.

                              Ont small thing though. If it is not to much trouble, the example I referred to had everyting in one file. The processdefinition as a string and the actionhandlers as inner classes. That way I only have to create one file, not multiple, with possible typos etc.

                              • 12. Re: JBPM Nested Fork/Joins Doesn't seem to work
                                kukeltje

                                ah, sorry, I missed the thrid time :-)

                                • 13. Re: JBPM Nested Fork/Joins Doesn't seem to work
                                  kukeltje

                                  oh, and one more thing, it would be nice if you could reduce the test to a minimal one. Just showing this one issue.

                                  • 14. Re: JBPM Nested Fork/Joins Doesn't seem to work

                                    Here is the 1 failing test, the other 2 work.

                                     @Test
                                     public void testWithMultipleAdjustmentsProcessNoApprove() throws Exception
                                     {
                                     ProcessDefinition def = ProcessDefinition.parseXmlResource("workflow/ny-workflow-2/processdefinition.xml");
                                    
                                     assertNotNull("Definition should not be null", def);
                                    
                                     ProcessInstance instance = new ProcessInstance(def);
                                     assertEquals("Def should be at start",
                                     "start-daily-pnl",
                                     instance.getRootToken().getNode().getName());
                                    
                                     instance.signal("default");
                                    
                                     instance.getRootToken().getChild("propose").signal("propose an adjustment");
                                    
                                     assertEquals("Def should be at fork2",
                                     "fork2",
                                     instance.getRootToken().getChild("propose").getNode().getName());
                                    
                                     instance.getRootToken().getChild("propose").getChild("propose").signal("propose an adjustment");
                                     instance.getRootToken().getChild("propose").getChild("approve").signal("cancel");
                                    
                                     instance.getRootToken().getChild("propose").getChild("propose").getChild("propose").signal("cancel");
                                     instance.getRootToken().getChild("propose").getChild("propose").getChild("approve").signal("cancel");
                                    
                                     assertEquals("propose/propose should be at join1",
                                     "join1",
                                     instance.getRootToken().getChild("propose").getChild("propose").getNode().getName());
                                     assertEquals("propose/approve should be at join2",
                                     "join2",
                                     instance.getRootToken().getChild("propose").getChild("approve").getNode().getName());
                                    
                                     assertEquals("parent should be at fork1",
                                     "fork1",
                                     instance.getRootToken().getNode().getName());
                                    
                                     assertEquals("propose should be at join1",
                                     "join1",
                                     instance.getRootToken().getChild("propose").getNode().getName());
                                    
                                    
                                     instance.getRootToken().getChild("signoff").signal("signoff pnl");
                                     assertEquals("signoff should be at join1",
                                     "join1",
                                     instance.getRootToken().getChild("signoff").getNode().getName());
                                    
                                     assertEquals("Def should be at auto approve",
                                     "auto-signoff-adj",
                                     instance.getRootToken().getNode().getName()
                                     );
                                    
                                     }
                                    
                                    


                                    1 2 Previous Next