11 Replies Latest reply on Mar 12, 2009 1:40 PM by Ronald van Kuijk

    spawning multiples subprocess instances

    Kristof Vanbecelaere Newbie

      Hi,

      The user guide explains how to use process-state to start a subprocess. To me this looks like starting a single subprocess instance. Is there a way to decide at runtime to start multiple instances of a subprocess?

      Thanks.

        • 1. Re: spawning multiples subprocess instances
          James Depoorter Novice

          jBpm will say: "You can create a custom node for this" :-)

          • 2. Re: spawning multiples subprocess instances
            Ronald van Kuijk Master

            how do you no that? :-) But yes, it is true. If someone developes such a node we can always publish it somewhere for others to re-use.

            You can also use a for that has a dynamic number of outgoing transitions but it ís fairly the same issue. There isn't a fork yet for this, so jBPM says: "You can create a custom node for this" :-)

            • 3. Re: spawning multiples subprocess instances
              Stephane Malbequi Newbie

              Hi,

              I propose this solution based on an event type "node-enter" on the fork node.

              <process-definition name="parent-process">
              
               <swimlane name="tester">
               <assignment expression="user(ernie)" />
               </swimlane>
              
               <start-state name="start">
               <task name="start-task" swimlane="tester">
               <controller>
               <variable name="my-fork.leaving-transitions-count" />
               </controller>
               </task>
               <transition to="my-fork" />
               </start-state>
              
               <fork name="my-fork">
               <event type="node-enter">
               <action name="spawning" class="xxx.SpawningMultipleTransitions"/>
               </event>
               <transition to="sub-process-state" />
               </fork>
              
               <process-state name="sub-process-state">
               <sub-process name="sub-process" />
               <transition to="join"/>
               </process-state>
              
               <join name="join">
               <transition to="end" />
               </join>
              
               <end-state name="end" />
              
              </process-definition>
              


              package xxx;
              
              import java.util.List;
              
              import org.jbpm.graph.def.ActionHandler;
              import org.jbpm.graph.def.Transition;
              import org.jbpm.graph.exe.ExecutionContext;
              import org.jbpm.graph.node.Fork;
              
              public class SpawningMultipleTransitions implements ActionHandler {
              
               public void execute(ExecutionContext executionContext) throws Exception {
               Fork fork = (Fork) executionContext.getNode();
               String varName = new StringBuffer(fork.getName()).append(".leaving-transitions-count").toString();
               String leavingTransitionCount = (String) executionContext.getVariable(varName);
               if (leavingTransitionCount == null) {
               throw new RuntimeException("The variable " + varName + " must have an integer value");
               }
               int n;
               try {
               n = Integer.parseInt(leavingTransitionCount);
               }
               catch (NumberFormatException e) {
               throw new RuntimeException("The variable " + varName + " must have an integer value");
               }
              
               List transitions = fork.getLeavingTransitions();
               if (transitions.size() == 0) {
               throw new RuntimeException("The fork node " + fork.getName() +
               " must have a transition. Check your processdefinition.xml");
               }
               else if (transitions.size() > 1) {
               throw new RuntimeException("The fork node " + fork.getName() +
               " must have only one transition. Check your processdefinition.xml");
               }
               Transition transition = (Transition) fork.getLeavingTransitions().remove(0);
               if (transition.getTo() == null) {
               throw new RuntimeException("The transition " + transition.getName() + " of the fork node " +
               fork.getName() + " must have a destination. Check your processdefinition.xml");
               }
               String name = transition.getName();
               name = new StringBuffer(name != null ? name : "transition").append("-").toString();
               for (int i = 1; i <= n; i++) {
               Transition trans = new Transition(new StringBuffer(name).append(i).toString());
               trans.setProcessDefinition(fork.getProcessDefinition());
               trans.setFrom(fork);
               trans.setTo(transition.getTo());
               fork.addLeavingTransition(trans);
               }
               }
              }
              


              • 4. Re: spawning multiples subprocess instances
                Chris OBrien Novice

                Couldn't you also just use a fork, have n transitions to the sub process node and then a single transition from the join?

                Like this:

                <?xml version="1.0" encoding="UTF-8"?>
                
                <process-definition name="process">
                 <!-- START-STATE --> <start-state name="start">
                 <task name="task"></task>
                 <transition name="" to="fork1"></transition> </start-state>
                
                 <!-- NODES -->
                 <process-state name="process1">
                 <transition name="" to="join2"></transition>
                 </process-state>
                 <join name="join2">
                 <transition name="" to="end1"></transition>
                 </join>
                 <end-state name="end1"></end-state>
                 <fork name="fork1">
                 <transition name="tr1" to="process1"></transition>
                 <transition name="tr2" to="process1"></transition>
                 <transition name="tr3" to="process1"></transition>
                 </fork>
                </process-definition>



                Oh wait, nevermind, you want to decide at runtime how many to make. The above code solution from smalbequi is better then :)

                • 5. Re: spawning multiples subprocess instances
                  Stephane Malbequi Newbie

                  Hi,

                  the solution I have proposed DON'T work because the code modifies the process definition, not only the process instance. In fact there is no concept of transition instance, only transition. So bad.

                  I will think about a solution based on a custom fork and certainly a custom join.


                  I think this feature, offered by some others bpm softwares, is very important and I hope the JBpm team will include it in a future version.

                  Thanks.

                  • 6. Re: spawning multiples subprocess instances
                    Chris OBrien Novice

                    You could always delete those transitions after you go to them.

                    Could you just create new child tokens from the root, and then just do the token.setNode( yourNode ); for each of them to force them on there without changing the process definition?

                    • 7. Re: spawning multiples subprocess instances
                      Stephane Malbequi Newbie

                      concerning the solution to delete the transition, i think the join will never do it's job.

                      • 8. Re: spawning multiples subprocess instances
                        Stephane Malbequi Newbie

                        finally I will do that :

                        <?xml version="1.0" encoding="UTF-8"?>
                        
                        <process-definition xmlns="urn:jbpm.org:jpdl-3.1"
                         name="super-process">
                        
                         <swimlane name="tester">
                         <assignment expression="user(ernie)" />
                         </swimlane>
                        
                         <start-state name="start">
                         <task name="start-task" swimlane="tester">
                         <controller>
                         <variable name="an-other-sub-process.counter" />
                         </controller>
                         </task>
                         <transition name="" to="an-other-sub-process" />
                         </start-state>
                        
                         <decision name="an-other-sub-process">
                         <handler class="com.traceone.bpm.ext.decision.CounterDecision" />
                         <transition name="no" to="join" />
                         <transition name="yes" to="my-fork" />
                         </decision>
                        
                         <fork name="my-fork">
                         <transition to="sub-process-state" />
                         <transition name="to-an-other" to="an-other-sub-process" />
                         </fork>
                        
                         <process-state name="sub-process-state">
                         <sub-process name="sub-process" />
                         <transition to="join" />
                         </process-state>
                        
                         <join name="join">
                         <transition to="end" />
                         </join>
                        
                         <end-state name="end" />
                        
                        </process-definition>
                        

                        public class CounterDecision implements DecisionHandler {
                        
                         public String decide(ExecutionContext executionContext) throws Exception {
                         Decision decision = (Decision) executionContext.getNode();
                         String varName = new StringBuffer(decision.getName()).append(".counter").toString();
                         String tmp = (String) executionContext.getVariable(varName);
                         int counter = Integer.parseInt(tmp);
                         String transition = counter > 0 ? "yes" : "no";
                         executionContext.setVariable(varName, String.valueOf(--counter));
                         return transition;
                         }
                        
                        }
                        


                        • 9. Re: spawning multiples subprocess instances
                          Chris OBrien Novice

                           

                          "smalbequi" wrote:
                          concerning the solution to delete the transition, i think the join will never do it's job.


                          As long as the join receives all of the child tokens created in the fork, the join will complete. Since your subprocess will finish X number of times, then all those tokens should move along.

                          But, since it is editing the processdefinition, what happens if someone else happens to be iterating at that point at the same time? You could have crazy collisions, so still not the best of ideas.



                          • 10. Re: spawning multiples subprocess instances
                            Margot Media Newbie

                            And If the join must to wait all subprocess's end????

                            • 11. Re: spawning multiples subprocess instances
                              Ronald van Kuijk Master

                              see my resonse on your other post... it *will* wait if all your process is designed properly