5 Replies Latest reply on Feb 23, 2012 1:34 PM by Jan Uhlir

    How to create a simple waiting workflow

    Jan Uhlir Newbie

      How to create a simple testing workflow in jBPM5/BPMN with a simple wait state, waiting for my explicit signal to continue.

      The simplest solution possible.

      Reason: I am learning jBPM5 and I want to play with things like ksession.getProcessInstances() etc. but so far all my workflows run through before I can do any run time inspection on them.

      What is the closest to jPDL State node?

      I have something like this workflow in my mind:

       

      Ecllipse bpmn2 designer screenshot wait state.png

       

      I tryed "Wait State" from my jBPM plugin palette, as is on my screenshot above, but there is no documentation to it. By probing workflow source code I found it maps to BPMN intermediateCatchEvent and it expect some Drools (?) condition. Angain, there is only a little documentation to it.

       

      Any help welcome!

      Espinosa

        • 1. Re: How to create a simple waiting workflow
          Mauricio Salatino Master

          You have an old plugin that's why you are seeing a Wait State there..

          You need to add a <task> -> service task node and then write an implementation of the WorkItemHandler class and do not complete the workitem inside the implementation. That will cause your process to wait until you finally decide to complete it.

          Cheers

          1 of 1 people found this helpful
          • 2. Re: How to create a simple waiting workflow
            Maciej Swiderski Master

            In my opinion the most sutiable node in BPMN2 for state node from jBPM v4 would be catch intermediateSignalEvent which will wait for an external signal, that should be done either through process instance or session that contains the process instance.

             

            Exanle of BPMN2 file you can find here and sample code that operates on this can be found in testIntermediateCatchEventSignal() method here

             

            HTH

            1 of 1 people found this helpful
            • 3. Re: How to create a simple waiting workflow
              Jan Uhlir Newbie

              Mauricio Salatino wrote:

               

              ..You need to add a <task> -> service task node and then write an implementation of the WorkItemHandler class and do not complete the workitem inside the implementation. That will cause your process to wait until you finally decide to complete it...

              Good tip. Thank you.

              Now I am stuck on how to signalize the custom task (MyWaitTask1WorkItemHandler aka MyWaitTask1) to complete and continue to the next task.

              According to this forum post, it is not possible to signalize Tasks, only Events:
              In general you cannot just signal any node directly ... however normally you have to model this as a signal event. (by Tihomir Surdilovic)

              Please, how should I here apply signal event?

              Put an Event element after the MyWaitTask1? Or before? Neither give sense.

              At the start of a new process "line"? I saw it in some examples. I puzzles me. See my post below.

               


              • 4. Re: How to create a simple waiting workflow
                Jan Uhlir Newbie

                Maciej Swiderski wrote:

                 

                Exanle of BPMN2 file you can find here and sample code that operates on this can be found in testIntermediateCatchEventSignal() method here

                Thank you.

                However it brings more questions then answers

                Here is the diagram of that process model:

                (/jbpm-examples/src/main/resources/junit/BPMN2-IntermediateCatchEventSignal.bpmn2)

                jbpm screenshot wait state examples.png

                Why there are two lanes? One process, but two lanes. How they are supposed to influence each other?

                 

                Note: The "User Task" is a custom task mapped to DoNothingWorkItemHandler, which does nothing, empty handler, but in the task properties is selected "Wait for Completion = true"

                The "event" (beginning of the second "line") is the mentioned intermediateCatchEvent task.

                 

                I made a bit modified version of this example:

                jbpm screenshot wait state examples my modification.png

                When I re-run test now:

                When I start the process, "Print something 1" is printed as expected.

                When I send signal to the process, the "Print something 3" is printed, as expected.

                And there is end of process.

                The "Print something 2" is never reached.

                More interestingly, the test is evaluated as "completed" even, despite the process still did not finished the "first line".

                Puzzling I have to say.

                 

                Yes, I have my wait state, but still no idea how to signalize it to move to the next task.

                • 5. Re: How to create a simple waiting workflow
                  Jan Uhlir Newbie

                  OK, I hope I solved it. Any objections against this solution? Any hidden catches?

                   

                  This works (6a):

                  jbpm screenshot wait state working 6a.png

                   

                  This works too (6b):

                  jbpm screenshot wait state working 6b.png

                   

                  BPMN2 Code 6a:

                   

                  <definitions ...>
                    <process processType="Private" isExecutable="true" id="SimpleProcess6a"
                             name="SimpleProcess6a" tns:packageName="defaultPackage" >
                  
                      <!-- nodes -->
                      <startEvent id="_1" name="StartProcess" />
                  
                      <task id="_4" name="JavaTask6" tns:taskName="JavaTask6" >
                      </task>
                  
                      <intermediateCatchEvent id="_5" name="WaitForSignal" >
                        <signalEventDefinition signalRef="fooSignal"/>
                      </intermediateCatchEvent>
                  
                      <endEvent id="_3" name="EndProcess" />
                  
                      <!-- connections -->
                      <sequenceFlow id="_5-_3" sourceRef="_5" targetRef="_3" />
                      <sequenceFlow id="_1-_4" sourceRef="_1" targetRef="_4" />
                      <sequenceFlow id="_4-_5" sourceRef="_4" targetRef="_5" />
                    </process>
                  </definitions>
                  


                   

                   

                  BPMN2 Code 6b:

                   

                  <definitions ...>
                    <process processType="Private" isExecutable="true" id="SimpleProcess6b"
                             name="SimpleProcess6b" tns:packageName="defaultPackage" >
                  
                      <!-- nodes -->
                      <startEvent id="_1" name="StartProcess" />
                  
                      <task id="_4" name="JavaTask6" tns:taskName="JavaTask6" >
                      </task>
                  
                      <intermediateCatchEvent id="_5" name="Event" >
                        <signalEventDefinition signalRef="fooSignal"/>
                      </intermediateCatchEvent>
                  
                      <parallelGateway id="_6" name="Join" gatewayDirection="Converging" />
                  
                      <endEvent id="_3" name="EndProcess" />
                  
                      <!-- connections -->
                      <sequenceFlow id="_6-_3" sourceRef="_6" targetRef="_3" />
                      <sequenceFlow id="_1-_4" sourceRef="_1" targetRef="_4" />
                      <sequenceFlow id="_4-_6" sourceRef="_4" targetRef="_6" />
                      <sequenceFlow id="_5-_6" sourceRef="_5" targetRef="_6" />
                    </process>
                  </definitions>
                  

                   

                  Code for class behind JavaTask task node:

                  public class JavaTask6WorkItemHandler implements WorkItemHandler {
                      @Override
                      public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
                          System.out.println("Inside JavaTask : " + workItem.getName());
                          // notify manager that work item has been completed
                          // Essential! Custom tasks are by default set "wait for completion = true", this makes them "false"
                          manager.completeWorkItem(workItem.getId(), null);
                      }
                  
                      @Override
                      public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
                          // do nothing
                      }
                  }
                  

                   

                  Test run code, start and signalize the process:

                  public class SimpleProcess6aRun {
                      
                      public static void main(String[] args) {
                          KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
                          kbuilder.add(ResourceFactory.newClassPathResource("simple_process_6a.bpmn"), ResourceType.BPMN2);
                          KnowledgeBase kbase = kbuilder.newKnowledgeBase();
                          StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
                          ksession.getWorkItemManager().registerWorkItemHandler("JavaTask6", new JavaTask6WorkItemHandler());
                          
                          ProcessInstance processInstance = ksession.startProcess("SimpleProcess6a");
                          Assert.assertNotNull(processInstance);
                          
                          // print all running processes
                          Collection<ProcessInstance> allProcesses = ksession.getProcessInstances();
                          for (ProcessInstance p : allProcesses) {
                              System.out.println("Running - " + p);
                          }
                          
                          // test wait state
                          Assert.assertEquals(ProcessInstance.STATE_ACTIVE, processInstance.getState());
                          
                          // send signal
                          // ksession.signalEvent("fooSignal", "fooSignal"); // global signal
                          processInstance.signalEvent("fooSignal", null); // process specific signal
                          
                          // test successful finish (test state)
                          Assert.assertEquals(ProcessInstance.STATE_COMPLETED, processInstance.getState());
                      }
                  }
                  // the code for SimpleProcess6bRun (6b process) is analogous
                  

                   

                  This forum thread is related too. I found Esteban Aliverti comment very helpful and so his examples on github.

                   

                  Is there any real difference between 6a and 6b? Otherwise I am going to use the simpler variant, without Gateway.

                   

                  If I have, let's say, process with 20 wait nodes, I have to add 20 more Event nodes after every task?