Backend Development 8 min read

Mastering Parallel Gateways in Activiti 7 with Spring Boot: A Step‑by‑Step Guide

This tutorial explains how to use parallel gateways in Activiti 7 with Spring Boot, covering their branching and merging functions, a complete reimbursement‑approval example, BPMN XML definition, and Java code for starting, querying, and approving workflow tasks.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Parallel Gateways in Activiti 7 with Spring Boot: A Step‑by‑Step Guide

Environment: Springboot 2.3.12.RELEASE + Activiti 7.1.0.M6

This article introduces the use of parallel gateways.

Overview

A parallel gateway allows a process to split into multiple concurrent branches and later merge them back into a single flow.

It has two functions: branching and merging .

Branching creates a concurrent branch for each outgoing sequence flow.

Merging combines multiple incoming branches into one outgoing flow.

The main difference from an exclusive gateway is that a parallel gateway ignores any conditions on the outgoing flows.

Example

The following reimbursement approval example demonstrates the branching and merging capabilities of a parallel gateway.

Four user tasks are defined, each with a dynamic assignee.

The "Employee reimbursement" task creates two parallel branches for approval by a deputy manager and a manager. After both approvals, the gateway merges and the flow proceeds to the "General manager".

Process definition (BPMN XML)

<code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="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"&gt;
  &lt;process id="ps" name="ps" isExecutable="true"&gt;
    &lt;startEvent id="startEvent" name="开始"/&gt;
    &lt;parallelGateway id="parallelgateway" name="并行执行"/&gt;
    &lt;userTask id="usertask1" name="副经理" activiti:assignee="${fjl}"/&gt;
    &lt;userTask id="usertask2" name="经理" activiti:assignee="${jl}"/&gt;
    &lt;parallelGateway id="parallelgateway1" name="Parallel Gateway"/&gt;
    &lt;sequenceFlow id="flow4" sourceRef="parallelgateway" targetRef="usertask1"/&gt;
    &lt;sequenceFlow id="flow5" sourceRef="parallelgateway" targetRef="usertask2"/&gt;
    &lt;sequenceFlow id="flow6" sourceRef="usertask1" targetRef="parallelgateway1"/&gt;
    &lt;sequenceFlow id="flow7" sourceRef="usertask2" targetRef="parallelgateway1"/&gt;
    &lt;userTask id="usertask3" name="总经理" activiti:assignee="${zjl}"/&gt;
    &lt;sequenceFlow id="flow8" sourceRef="parallelgateway1" targetRef="usertask3"/&gt;
    &lt;endEvent id="endevent1" name="End"/&gt;
    &lt;sequenceFlow id="flow9" sourceRef="usertask3" targetRef="endevent1"/&gt;
    &lt;userTask id="usertask4" name="员工报销单" activiti:assignee="${userId}"/&gt;
    &lt;sequenceFlow id="flow10" sourceRef="usertask4" targetRef="parallelgateway"/&gt;
    &lt;sequenceFlow id="flow11" sourceRef="startEvent" targetRef="usertask4"/&gt;
  &lt;/process&gt;
  &lt;!-- ... --&gt;
&lt;/definitions&gt;</code>

Start Process

<code>@GetMapping("/start")
public R startProcess(String processDefinitionId, String userId) {
    Map<String, Object> variables = new HashMap<>();
    variables.put("userId", userId);
    // start process instance
    ProcessInstance instance = ps.startProcessInstanceAssignVariables(processDefinitionId, variables);
    // set next assignees
    variables.put("fjl", "20000");
    variables.put("jl", "20001");
    ps.executionTask(variables, instance.getId());
    return R.success();
}</code>

Query Tasks

<code>@GetMapping("/tasks")
public R myTasks(String userId) {
    List<Task> list = ps.queryTasks(userId);
    List<Map<String, Object>> result = list.stream().map(task -> {
        Map<String, Object> res = new HashMap<>();
        res.put("id", task.getId());
        res.put("assignee", task.getAssignee());
        res.put("createTime", task.getCreateTime());
        res.put("bussinessKey", task.getBusinessKey());
        res.put("category", task.getCategory());
        res.put("dueDate", task.getDueDate());
        res.put("desc", task.getDescription());
        res.put("name", task.getName());
        res.put("owner", task.getOwner());
        res.put("instanceId", task.getProcessInstanceId());
        res.put("variables", task.getProcessVariables());
        res.put("state", task.isSuspended());
        return res;
    }).collect(Collectors.toList());
    return R.success(result);
}</code>

Approve Task

<code>@GetMapping("/approve")
public R approve(@RequestParam Map<String, Object> variables) {
    String instanceId = (String) variables.remove("instanceId");
    if (StringUtils.isEmpty(instanceId)) {
        return R.failure("未知任务");
    }
    ps.executionTask(variables, instanceId);
    return R.success();
}</code>

Runtime tables (act_ru_task, act_ru_execution) show the state of tasks after each approval step, illustrating how the parallel gateway merges branches only after both deputy manager and manager have approved.

Finally, the process ends when the general manager approves, demonstrating the simple branching and merging behavior of parallel gateways.

workflowbackend developmentBPMNSpring BootActivitiParallel Gateway
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.