9 Replies Latest reply on Jun 9, 2008 8:43 AM by Ronald van Kuijk

    replication of task at runtime

    Walter Taus Newbie

      Hello,

      I want to replicate one task in my process n times. However, the number n is only known at runtime. At the end all n tasks should be synchronized and only when all tasks have been completed further process navigation should take place.

      Ideally it would be:
      1) fork
      2) n times the same task
      3) join

      Furthermore, I must not modify the process definition as for the next instance of this process the number n will be different. I.e. I really want to replicate the tasks only for the current process instance.

      I would be grateful to get your ideas how to solve this scenario.

      Walter

        • 1. Re: replication of task at runtime
          null null Newbie

          Does it involves different actors or same actors? I am just asking as I have a same problem. but i require that the task to be associated with different actors

          Thanks in advance

          CSJakharia

          • 2. Re: replication of task at runtime
            Ronald van Kuijk Master

            look in the wiki... there is a 'dynamic fork' example

            • 3. Re: replication of task at runtime
              Walter Taus Newbie

              Hi,
              in my example the same actors are involved.
              I looked in Wiki and found a MultiChoiceForkAH and a ForEachForkAh. Is this what you are referring to as "Dynamic Fork" ?

              Thanks,
              Walter

              • 5. Re: replication of task at runtime
                Walter Taus Newbie

                Hi,

                I have now implemented this ForEachForkHandler and it works. However, I have now come up with an extended scenario.
                In my ForEachForkHandler I create 4 tasks. However, in specific situations I want already to continue when the first two tasks are completed. Therefore, I have tried to implement a kind of housekeeping handler which I call from the join to get rid of the "unnecessary" tasks.

                My process consists of
                1) fork
                2) 4 activities which have been generated by the ForEachForkHandler
                3) join

                When entering the join I call setNOutOfM with an appropriate value. Secondly I invoke the handler listed below:

                ublic class MultiinstanceHouseKeepingHandler implements ActionHandler {
                
                 @Override
                 public void execute(ExecutionContext ctx) throws Exception {
                 // TODO Auto-generated method stub
                 Token t = ctx.getToken();
                 Collection til = ctx.getTaskMgmtInstance().getTaskInstances();
                 Map childTokenList = t.getParent().getChildren();
                 Set ks = childTokenList.keySet();
                 Iterator it = ks.iterator();
                 while (it.hasNext()) {
                 Token ct = (Token)childTokenList.get(it.next());
                 if (ct == t)
                 continue;
                 Iterator itil = til.iterator();
                 while (itil.hasNext()) {
                 TaskInstance ti = (TaskInstance)itil.next();
                 if (ti.getToken() == ct) {
                 ti.cancel();
                 ct.end();
                 break;
                 }
                 }
                 }
                 }
                }
                

                The process continues correctly with the task following the join. However, I cannot get rid of the other unwanted tasks and they stay forever on my worklist.
                What am I doing wrong here?

                Thanks,
                Walter

                • 6. Re: replication of task at runtime
                  Ronald van Kuijk Master

                  you mean the ti.cancel() and ct.end() do not get called because the 'itil' is is empty or do they get called but do not work?

                  • 7. Re: replication of task at runtime
                    Walter Taus Newbie

                    Hi,

                    I was not aware that the call to ti.cancel also invokes my MultiinstanceHouseKeepingHandler. ANd in this second (i.e. nested) call to my Handler it blew up and hence did not eliminate anything from my worklist. I am now setting an indication that I am within a nested call so that my handler knows what to do.
                    Thanks,
                    Walter

                    • 8. Re: replication of task at runtime
                      Walter Taus Newbie

                      Hi,
                      for the sake of completeness, here is now my complete code.

                      public class MultiinstanceLoopForkHandler implements ActionHandler {
                       private String loopMaxValue;
                       private String loopId;
                       private int loopType;
                      
                       @Override
                       public void execute(ExecutionContext ctx) throws Exception {
                       // TODO Auto-generated method stub
                      
                       Token token = ctx.getToken();
                       Fork fork = (Fork)ctx.getNode();
                       int i;
                       try {
                       i = Integer.parseInt(loopMaxValue);
                       }
                       catch (Exception e) {
                       try {
                       if (ctx.getVariable(loopMaxValue) != null)
                       i = (Integer)ctx.getVariable(loopMaxValue);
                       else
                       i = 1;
                       }
                       catch(Exception e1) {
                       e1.printStackTrace();
                       i = 1;
                       }
                       }
                       if (loopType == 1)
                       ctx.setVariable(loopId + "MaxCount", 1);
                       else
                       ctx.setVariable(loopId + "MaxCount", i);
                       Transition leavingTrans = (Transition)fork.getLeavingTransitions().get(0);
                       for (int j = 1; j<i; j++) {
                       String newTokenName = loopId + j;
                       String transitionName = leavingTrans.getName();
                       Token newToken = new Token(token, newTokenName);
                       ctx.getJbpmContext().getSession().save(newToken);
                       fork.leave(new ExecutionContext(newToken), transitionName);
                       }
                       }
                      
                      }
                      


                      public class MultiinstanceLoopJoinHandler implements ActionHandler {
                       private String loopId;
                       @Override
                       public void execute(ExecutionContext ctx) throws Exception {
                       // TODO Auto-generated method stub
                       if (ctx.getVariable(loopId + "Housekeeping") != null)
                       return;
                       ctx.setVariable(loopId + "Housekeeping", 1);
                       Token t = ctx.getToken();
                       Collection til = ctx.getTaskMgmtInstance().getTaskInstances();
                       Map childTokenList = t.getParent().getChildren();
                       Set ks = childTokenList.keySet();
                       Iterator it = ks.iterator();
                       while (it.hasNext()) {
                       Token ct = (Token)childTokenList.get(it.next());
                       if (ct.getName().equals(t.getName()) && ct.getId() == t.getId())
                       continue;
                       if (ct.getName() != null && !ct.getName().startsWith(loopId))
                       continue;
                       Iterator itil = til.iterator();
                       while (itil.hasNext()) {
                       TaskInstance ti = (TaskInstance)itil.next();
                       if (ti.getToken() == ct) {
                       ti.cancel();
                       ct.end();
                       break;
                       }
                       }
                       }
                       }
                      
                      }
                      
                      


                      And here is an example process.
                      <fork name="ForkOne">
                      <event type="node-enter">
                      <action class="com.pi.bpm.workflow.jbpm.MultiinstanceLoopForkHandler">
                      <loopMaxValue>3</loopMaxValue>
                      <loopId>MultinstanceOne</loopId>
                      <loopType>1</loopType>
                      </action>
                      </event>
                      <transition name="MultinstanceOne" to="MultinstanceOne"></transition>
                      </fork>
                      <task-node name="MultinstanceOne">
                      <transition name="ToJoinOne" to="JoinOne"></transition>
                      <task name="MultinstanceOne"></task>
                      </task-node>
                      <join name="JoinOne">
                      <event type="node-enter">
                      <script><expression>
                      if (executionContext.getVariable("MultinstanceOneMaxCount") > 1) executionContext.getNode().setNOutOfM(executionContext.getVariable("MultinstanceOneMaxCount"));
                      else executionContext.getNode().setDiscriminator(true);
                      </expression></script>
                      <action class="com.pi.bpm.workflow.jbpm.MultiinstanceLoopJoinHandler">
                      <loopId>MultinstanceOne</loopId>
                      </action>
                      </event>
                      <transition name="To_cF5fADE6Ed2C6L5mprqn1w" to="../UserTask5/UserTask5">
                      </transition>
                      </join>
                      </super-state>
                      


                      BTW with this sequence I can handle the BPMN constructs of Multiinstance Loop All and Multiinstance Loop One.

                      ANy suggestions and improvements are highly welcome.

                      Walter


                      • 9. Re: replication of task at runtime
                        Ronald van Kuijk Master

                        nice, congratulations... on a sidenote, could you make a wiki page for this. I'm sure others are interested.