cancel
Showing results for 
Search instead for 
Did you mean: 

jump to a user task

joelyu
Champ in-the-making
Champ in-the-making
I have an activiti process that has numerous user task and system task.  I want to have the ability anywhere within the process to jump to a certain user task.  How can I use the Activiti API or Designer to accomplish this.  I'm trying to avoid having a executive gateway coming out of every user or system task for routing to this certain user task.

Thanks in advance.
11 REPLIES 11

trademak
Star Contributor
Star Contributor
BPMN is not that flexible I'm afraid. You could change the execution pointer, but that is not something we support via the Activiti API currently.

Best regards,

jamiechow
Champ in-the-making
Champ in-the-making
is there any solution , i have the same problem

martin_grofcik
Confirmed Champ
Confirmed Champ
Yes, there is.
But you have to know what you are doing. (It is similar to use of goto in some programming languages - I would prefer to do not use it)
Just set activityId in the execution in DB.

Regards
Martin

windfighter
Champ in-the-making
Champ in-the-making
<code>
       ExecutionEntity executionEntity = commandContext
                .getExecutionEntityManager().findExecutionById(executionId);
        ProcessDefinitionImpl processDefinition = executionEntity
                .getProcessDefinition();
        ActivityImpl activity = processDefinition.findActivity(activityId);
      executionEntity.executeActivity(activity);
</code>
in my case, all the task assignee is set by variable
my flow tempalte is : start->user task1->user task2->user task3->end

suppose the user task2 's assignee variable is `user`
Multi instance collection is ${users} ,element variable is `user`

if work flow is at  user task 3 , and I want jump to the user task2, how to make sure the assignee is set correctly?

martin_grofcik
Confirmed Champ
Confirmed Champ
Hi,

changing execution's activityId does not create user task. Create user task and set assignee as you want.

Regards
Martin

hi,
could you pls tell me
how to set the assignee? and make sure the user task work as multi-instance when flow jump to the target activiti( user task2)

thanks

windfighter
Champ in-the-making
Champ in-the-making
hi, thanks for replying.

how to set the assignee , and make sure that the `user task2` work as multi-instances?

jbarrez
Star Contributor
Star Contributor
"how to set the assignee"

This is covered in the user guide … use the activiti:assignee attribute.

"make sure that the `user task2` work as multi-instances?"

Check the section on multi instance first and when you have issues then, post them here.

windfighter
Champ in-the-making
Champ in-the-making
my workflow model is: start->user task1->user task2(multi-instance)->user task3-> end

all the assignee I set is using flow variables.
at runtime of the flow ,the assignee are as below.

user task1 : assignee is `zhangsan`
user task2: assignee are `lisi` and `wanger`
user task3: assignee is `mazi`

I write a test function,
and hope the flow can jump from `user task3` to `user task2`,and I set the assignees of `user task2` in the `jumpAcitivtyCmd` before jumping.

but the result is : jumping work correctly, but when the second task user `wanger` complete the task of `user task2`, pop up execption.

it tasks me long time on it, and I don't kown how to resolve it. and very exhausted.

Hope you can help me!!!
thanks.

the flow mode is :

<code>
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlnsSmiley Surprisedmgdc="http://www.omg.org/spec/DD/20100524/DC" xmlnsSmiley Surprisedmgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
  <process id="simpleFlow" name="任务发起" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <userTask id="usertask1" name="User Task1" activiti:assignee="${user}"></userTask>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
    <userTask id="usertask2" name="User Task2" activiti:assignee="${user}">
      <multiInstanceLoopCharacteristics isSequential="true" activiti:collection="${users}" activiti:elementVariable="user"></multiInstanceLoopCharacteristics>
    </userTask>
    <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
    <userTask id="usertask3" name="User Task3" activiti:assignee="${user}"></userTask>
    <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_simpleFlow">
    <bpmndi:BPMNPlane bpmnElement="simpleFlow" id="BPMNPlane_simpleFlow">
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="140.0" y="150.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
        <omgdc:Bounds height="55.0" width="105.0" x="220.0" y="140.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
        <omgdc:Bounds height="55.0" width="105.0" x="370.0" y="140.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
        <omgdc:Bounds height="55.0" width="105.0" x="520.0" y="140.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="680.0" y="150.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
        <omgdi:waypoint x="175.0" y="167.0"></omgdi:waypoint>
        <omgdi:waypoint x="220.0" y="167.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="325.0" y="167.0"></omgdi:waypoint>
        <omgdi:waypoint x="370.0" y="167.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="475.0" y="167.0"></omgdi:waypoint>
        <omgdi:waypoint x="520.0" y="167.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
        <omgdi:waypoint x="625.0" y="167.0"></omgdi:waypoint>
        <omgdi:waypoint x="680.0" y="167.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>
<code>

and my test code is :
<code>
@Test
   public void testJump() {
       //flow template model is: start->usertask1->usertask2->usertask3->end
       //user task2 is multi-instance user task, and multi-instance collection is ${users}, and element is user;
       String processDefId = "simpleFlow:2:1587504";


       Map<String, Object> variables = new HashMap<>();

       //set user task1 assignee
       variables.put("user", "zhangsan");

       ProcessInstance pi = runtimeService.startProcessInstanceById(processDefId, variables);
       printExecutions(pi.getProcessInstanceId(), "after start flow");
       logger.info("流程实例Id:{}", pi.getProcessInstanceId());


       //set user task2 assignee
       List<String> u2Assignees =  Arrays.asList(new String[]{"lisi", "wanger"});
       runtimeService.setVariable(pi.getProcessInstanceId(), "users",u2Assignees);
       //complete user task 1
       completeTask(pi.getProcessInstanceId(), null);
       printExecutions(pi.getProcessInstanceId(), "after complete user task1");

       //set user task3 assignee
       runtimeService.setVariable(pi.getProcessInstanceId(), "user", "mazi");
       //complete user task2
       completeTask(pi.getProcessInstanceId(), null);
       printExecutions(pi.getProcessInstanceId(), "after complete user task2-instance1");

       //complete user task2
       completeTask(pi.getProcessInstanceId(), null);
       printExecutions(pi.getProcessInstanceId(), "after complete user task2-instance2");

       //complete user task3
       //completeTask(pi.getProcessInstanceId(), null);
       //printExecutions(pi.getProcessInstanceId(), "after complete user task3");

       //jump to user task2
       JumpActivityCmd cmd = new JumpActivityCmd(pi.getProcessInstanceId(),"usertask2","disapprove",u2Assignees,u2Assignees.get(0));
      
       managementService.executeCommand(cmd);
/*

       TaskFlowControlService taskFlowControlService = new TaskFlowControlService(processEngine,pi.getProcessInstanceId());
       try {
           taskFlowControlService.jump("usertask2");
       }catch (Exception e){
           logger.error("",e);
       }
*/

       printExecutions(pi.getProcessInstanceId(), "after jump to user task2");

       completeTask(pi.getProcessInstanceId(), null);
       printExecutions(pi.getProcessInstanceId(), "after complete user task2-instance1");


       completeTask(pi.getProcessInstanceId(), null);
       printExecutions(pi.getProcessInstanceId(), "after complete user task2-instance2");
      
   }

private void printExecutions(String processInstanceId,String messageTitle){
        List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).list();
        if(executions != null && executions.size() > 0){
            for(Execution e : executions){
                logger.info(messageTitle + ":current executionId is {},activityId is {}, parent executionId is {}",e.getId(),e.getActivityId(),e.getParentId());
            }
        }
    }

    private  void completeTask(String processInstanceId,Map variables) {
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstanceId).list();

        if (tasks != null && tasks.size() > 0) {

            for (Task e : tasks) {
                logger.info("****************************complete task:{},task assignee {} ,execution id {}****************************", e.getId(),e.getAssignee(), e.getExecutionId());
                taskService.complete(e.getId());
            }


        }

    }

<code>

and the jumpActivityCmd class is :
<code>
public class JumpActivityCmd implements Command<Object> {
    Logger logger = org.slf4j.LoggerFactory.getLogger(JumpActivityCmd.class);

    private String activityId;
    private String processInstanceId;
    private String jumpOrigin;

    //task assignees,if the target activity is multi-instance
    private List<String> taskUsers;

    //task assignee, if not multi-instance
    private String taskUser;


    public JumpActivityCmd(String processInstanceId, String activityId,String jumpOrigin,
                           List<String> taskUsers,String taskUser) {
        this(processInstanceId, activityId, jumpOrigin);
        this.taskUsers = taskUsers;
        this.taskUser = taskUser;
    }

    public JumpActivityCmd(String processInstanceId, String activityId) {
        this(processInstanceId, activityId, "jump");
    }

    public JumpActivityCmd(String processInstanceId, String activityId, String jumpOrigin) {
        this.activityId = activityId;
        this.processInstanceId = processInstanceId;
        this.jumpOrigin = jumpOrigin;
    }

    public Object execute(CommandContext commandContext) {


        ExecutionEntity executionEntity = commandContext.getExecutionEntityManager().findExecutionById(processInstanceId);
        executionEntity.destroyScope(jumpOrigin);

        ProcessDefinitionImpl processDefinition = executionEntity.getProcessDefinition();
        ActivityImpl activity = processDefinition.findActivity(activityId);

        if(!activityId.equals("end") && jumpOrigin.equals("disapprove")) {
            executionEntity.setVariable("users",taskUsers);
            executionEntity.setVariable("user",taskUser);
        }

        executionEntity.executeActivity(activity);

        return executionEntity;

    }

}
<code>