Version 9

    OK, this is a custom fork handler. In tyhis case I am hardcoding two attendees who have to respond to a meeting invite. However, you should be able to extrapolate that to generate child tasks based on an array which is arbitrary in length. In this particular case, I am passing in the attendees from a form with two fields.




    package org.jbpm.delegation.fork; 
    import java.util.*; 
    import org.jbpm.*; 
    import org.jbpm.delegation.*; 
    import org.jbpm.model.definition.*; 
    import org.jbpm.model.definition.impl.*; 
    import org.jbpm.model.execution.impl.*; 
    * @author marc_mulzer 
    public class MyForkHandler implements ForkHandler {
       public void fork(ForkContext forkContext) throws ExecutionException{ 
          String attendee1 = (String) forkContext.getVariable("attendee1"); 
          String attendee2 = (String) forkContext.getVariable("attendee2"); 
          JoinImpl correspondingJoin = (JoinImpl) ((Fork)forkContext.getNode()).getCorrespondingJoin(); 
          Iterator iter = forkContext.getNode().getLeavingTransitions().iterator(); 
          while( iter.hasNext() ) { 
             Transition transition = (Transition); 
             TokenImpl childToken = (TokenImpl) forkContext.createToken( transition, attendee1 ); 
             childToken.setName("You have a new invitation from "); 
             childToken.setReactivationJoin( correspondingJoin ); 
             TokenImpl childToken1 = (TokenImpl) forkContext.createToken( transition, attendee2 ); 
             childToken1.setName("You have a new invitation from "); 
             childToken1.setReactivationJoin( correspondingJoin ); 




    The process files looks like this. Someone requests a meeting and all I am doing here is to wait for any response. (You can add additional forks to branch if you care what the response is) Notice the custom fork handler class in there and the arbitrary actor. At runtime, the code overrides the actor in the custom fork handler.


    <?xml version="1.0" encoding="UTF-8"?> 
    <!DOCTYPE process-definition PUBLIC 
    "-//jBpm/jBpm Mapping DTD 2.0 beta3//EN" 
    <process-definition name="scheduling process">  
       <!-- SWIMLANES --> 
       <swimlane name="requester" ></swimlane> 
       <swimlane name="boss"> 
          <delegation class="org.jbpm.delegation.assignment.ActorAssignmentHandler">cg</delegation> 
       <swimlane name="approver list"> 
       <!-- START-STATE --> 
       <start-state name="request a meeting" swimlane="requester"> 
          <transition to="fork"></transition> 
       <!-- NODES --> 
       <fork name="fork"> 
          <delegation class="org.jbpm.delegation.fork.MyForkHandler">ae</delegation> 
          <transition to="custom fork" ></transition> 
       <state name="custom fork"> 
          <assignment swimlane="approver list" ></assignment> 
          <transition to="join" ></transition> 
       <join name="join"> 
          <transition to="notify" ></transition> 
       <state name="notify"> 
          <assignment swimlane="requester" ></assignment> 
          <transition to="done" ></transition> 
       <!-- END-STATE --> 
       <end-state name="done" ></end-state> 




    This is the associated form.xml. Here you can see how I am passing the variables. It could easily be an array or a complex type.

          <state-name>request a meeting</state-name> 
          <task-name>request a meeting</task-name> 
          <variable name="attendee1" ></variable> 
          <variable name="attendee2" ></variable> 
          <state-name>custom fork</state-name> 
          <task-name>meeting request received</task-name> 
          <variable name="attendee1" ></variable> 
          <variable name="attendee2" ></variable> 
          <task-name>all responses received</task-name> 
          <variable name="attendee1" ></variable> 
          <variable name="attendee2" ></variable> 




    Hope this helps!







    Note: This is valid only for Jbpm 2.0.


    For a valid Jbpm 3.0 implementation, see ForEachForkActionHandler.




    By Rodrigo Porto