3 Replies Latest reply on May 4, 2006 6:55 PM by Ronald van Kuijk

    Manually controlling execution of nodes

    michaelklem Newbie

      I created the following process definition

      <process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="test1">
       <start-state name="start">
       <transition name="step1" to="step1"/>
       </start-state>
       <end-state name="end"/>
       <state name="step1">
       <transition name="step2" to="step2"/>
       </state>
       <state name="step2">
       <transition name="step3" to="step3"/>
       </state>
       <state name="step3">
       <transition name="step4" to="step4"/>
       </state>
       <state name="step4">
       <transition name="step5" to="step5"/>
       </state>
       <state name="step5">
       <transition name="end" to="end"/>
       </state>
      </process-definition>
      


      I am trying to manually control which state gets executed next. For example, once the process is started, I am trying to execute the states in the following order:
      step1
      step1
      step4
      step3
      step3
      step2
      step5

      I am able to do so with the following code
       /**
       Sequence Control Test.
       Verify that we can specify which token to taken on a simple sequential process.
       TEST1_PROCESS is a sequential process definition of wait states.
       Once we start the process, we should be able to step to any node we want.
       */
      
       public void test1()
       {
      
       try {
       // Deploy the process definition
       init( TEST1_PROCESS );
      
       JbpmContext jbpmContext = sJbpmConfiguration.createJbpmContext();
       GraphSession graphSession = jbpmContext.getGraphSession();
       ProcessDefinition processDefinition = graphSession.findLatestProcessDefinition( "test1" );
       ProcessInstance processInstance = new ProcessInstance( processDefinition );
      
       long processDefId = processDefinition.getId();
       long processId = processInstance.getId();
       Token token = processInstance.getRootToken();
       assertTrue( processDefinition.getNode( "start" ).equals( token.getNode() ) );
      
       processInstance.signal();
       assertTrue( processDefinition.getNode( "step1" ).equals( token.getNode() ) );
       jbpmContext.close();
      
       Node n;
      
       // Go to step 1
       jbpmContext = sJbpmConfiguration.createJbpmContext();
       graphSession = jbpmContext.getGraphSession();
       processInstance = graphSession.loadProcessInstance( processId );
       processDefinition = graphSession.loadProcessDefinition( processDefId );
       n = processDefinition.getNode( "start" );
       token = processInstance.getRootToken();
       token.setNode( n );
       token.signal();
       assertTrue( processDefinition.getNode( "step1" ).equals( token.getNode() ) );
       jbpmContext.close();
      
      
       // Go to step 1
       jbpmContext = sJbpmConfiguration.createJbpmContext();
       graphSession = jbpmContext.getGraphSession();
       processInstance = graphSession.loadProcessInstance( processId );
       processDefinition = graphSession.loadProcessDefinition( processDefId );
       n = processDefinition.getNode( "start" );
       token = processInstance.getRootToken();
       token.setNode( n );
       token.signal();
       assertTrue( processDefinition.getNode( "step1" ).equals( token.getNode() ) );
       jbpmContext.close();
      
      
       // Go to step 4
       jbpmContext = sJbpmConfiguration.createJbpmContext();
       graphSession = jbpmContext.getGraphSession();
       processInstance = graphSession.loadProcessInstance( processId );
       processDefinition = graphSession.loadProcessDefinition( processDefId );
       n = processDefinition.getNode( "step3" );
       token = processInstance.getRootToken();
       token.setNode( n );
       token.signal();
       assertTrue( processDefinition.getNode( "step4" ).equals( token.getNode() ) );
       jbpmContext.close();
      
      
       // Go to step 3
       jbpmContext = sJbpmConfiguration.createJbpmContext();
       graphSession = jbpmContext.getGraphSession();
       processInstance = graphSession.loadProcessInstance( processId );
       processDefinition = graphSession.loadProcessDefinition( processDefId );
       n = processDefinition.getNode( "step2" );
       token = processInstance.getRootToken();
       token.setNode( n );
       token.signal();
       assertTrue( processDefinition.getNode( "step3" ).equals( token.getNode() ) );
       jbpmContext.close();
      
      
       // Go to step 3
       jbpmContext = sJbpmConfiguration.createJbpmContext();
       graphSession = jbpmContext.getGraphSession();
       processInstance = graphSession.loadProcessInstance( processId );
       processDefinition = graphSession.loadProcessDefinition( processDefId );
       n = processDefinition.getNode( "step2" );
       token = processInstance.getRootToken();
       token.setNode( n );
       token.signal();
       assertTrue( processDefinition.getNode( "step3" ).equals( token.getNode() ) );
       jbpmContext.close();
      
      
       // Go to step 2
       jbpmContext = sJbpmConfiguration.createJbpmContext();
       graphSession = jbpmContext.getGraphSession();
       processInstance = graphSession.loadProcessInstance( processId );
       processDefinition = graphSession.loadProcessDefinition( processDefId );
       n = processDefinition.getNode( "step1" );
       token = processInstance.getRootToken();
       token.setNode( n );
       token.signal();
       assertTrue( processDefinition.getNode( "step2" ).equals( token.getNode() ) );
       jbpmContext.close();
      
      
       // Go to step 5
       jbpmContext = sJbpmConfiguration.createJbpmContext();
       graphSession = jbpmContext.getGraphSession();
       processInstance = graphSession.loadProcessInstance( processId );
       processDefinition = graphSession.loadProcessDefinition( processDefId );
       n = processDefinition.getNode( "step4" );
       token = processInstance.getRootToken();
       token.setNode( n );
       token.signal();
       assertTrue( processDefinition.getNode( "step5" ).equals( token.getNode() ) );
       jbpmContext.close();
       }
       catch( Exception ex ) {
       ex.printStackTrace();
       fail();
       }
      
       } /* test1 */
      


      This code works but it seems like there must be a better/easier way to do this in jBPM. I read all the docs and searched the forums but was unable to find an answer that was obvious to me. Am I missing something here or is this something I should not be doing with jBPM?

      Thanks

        • 1. Re: Manually controlling execution of nodes
          Ronald van Kuijk Master

          Why does it seem that there must be an easier way to do this?

          The P in BPM stands for process (= defined sequence of tasks/states/etc..) What you try to do creating ad-hoc processes.

          Two possible 'solutions' come to mind however:

          If the number of tasks is limited, you could try to make a web (meaning connect every node via a transition to another node).

          If the number grows jou could try a hub-spoke model. Put a decision node in the middle, have a transition to each task and each task back to the decision. Then use a process variable (or something else) to decide which task to go to from the decision.

          Just some ideas

          • 2. Re: Manually controlling execution of nodes
            michaelklem Newbie

            Thanks for your quick response.

            As a jBPM newbie I wasn't sure if I was actually doing this the correct way. I didn't want to hack it but looking through the source I saw no other way.

            I have thought of the ideas you already posted and since they are similar I feel more confident that I am grasping jBPM.

            Thanks again.

            • 3. Re: Manually controlling execution of nodes
              Ronald van Kuijk Master

              another quick response:

              It is the first time I came across a question like this, so 'the correct way' is not the 'normal way' :-)

              Your solution is as good as mine with the difference that both my solutions visually represent what can happen.
              Your solution doesn't, but it is technically as good.