Backend Development 32 min read

Integrating Activiti 7 with Spring Boot: Dependencies, Setup, and Advanced Workflow Operations

This article provides a step‑by‑step guide for integrating Activiti 7 workflow engine into a Spring Boot application, covering Maven dependencies, environment setup, process deployment, task handling, business keys, suspension/activation, candidate users, variables, gateways, and various advanced operations with complete code examples.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Integrating Activiti 7 with Spring Boot: Dependencies, Setup, and Advanced Workflow Operations

1. Dependencies

Add the Activiti Spring Boot starter and the Activiti image generator to your Maven pom.xml , excluding conflicting libraries such as commons-io , commons-lang3 , and mybatis as shown below.

org.activiti
activiti-spring-boot-starter
7.0.0.SR1
commons-io
commons-io
commons-lang3
org.apache.commons
mybatis
org.mybatis
org.activiti
activiti-image-generator
7.0.0.SR1
commons-io
commons-io

2. Install Activiti Environment

Configure IntelliJ IDEA to avoid Chinese character garbling:

Set File → Settings → Editor → File Encodings to UTF‑8.

Add -Dfile.encoding=UTF-8 to custom VM options.

Append -Dfile.encoding=UTF-8 to idea.exe.vmoptions and idea64.exe.vmoptions files.

Restart IDEA.

3. Basic Usage

1. Create a BPMN file

Draw a simple process diagram using the Activiti designer plugin.

2. Deploy Process Definition

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.junit.Test;

public class ActivitiTest {
    @Test
    public void testDeploy() {
        //创建ProcessEngine对象
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        //获取RepositoryService对象
        RepositoryService repositoryService = processEngine.getRepositoryService();
        //进行部署
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("bpmn/leave.bpmn")
                .addClasspathResource("bpmn/leave.png")
                .name("请假流程")
                .deploy();
        //输出部署的一些信息
        System.out.println("流程部署ID:"+deployment.getId());
        System.out.println("流程部署名称:"+deployment.getName());
    }
}

3. Start Process Instance

@Test
public void testStartProcess() {
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    RuntimeService runtimeService = processEngine.getRuntimeService();
    ProcessInstance instance = runtimeService.startProcessInstanceByKey("leaveProcess");
    System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
    System.out.println("流程实例的id = " + instance.getId());
}

4. Query Tasks

@Test
public void testSelectTodoTaskList() {
    String assignee = "李四";
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    TaskService taskService = processEngine.getTaskService();
    List
taskList = taskService.createTaskQuery()
            .processDefinitionKey("leaveProcess")
            .taskAssignee(assignee)
            .list();
    for (Task task : taskList) {
        System.out.println("流程定义id = " + task.getProcessDefinitionId());
        System.out.println("流程实例id = " + task.getProcessInstanceId());
        System.out.println("任务id = " + task.getId());
        System.out.println("任务名称 = " + task.getName());
    }
}

5. Complete Task

@Test
public void testCompleteTask() {
    String assignee = "李四";
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    TaskService taskService = processEngine.getTaskService();
    List
taskList = taskService.createTaskQuery()
            .processDefinitionKey("leaveProcess")
            .taskAssignee(assignee)
            .list();
    for (Task task : taskList) {
        taskService.complete(task.getId());
    }
}

6. Add Approval Comment

@Test
public void testAddComment() {
    String assignee = "王五";
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    TaskService taskService = processEngine.getTaskService();
    List
taskList = taskService.createTaskQuery()
            .processDefinitionKey("leaveProcess")
            .taskAssignee(assignee)
            .list();
    for (Task task : taskList) {
        taskService.addComment(task.getId(), task.getProcessInstanceId(), task.getName() + "审批通过");
        taskService.complete(task.getId());
    }
}

7. View Historical Approvals

@Test
public void testSelectHistoryTask() {
    String processInstanceId = "2501";
    String taskAssignee = "王五";
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    HistoryService historyService = processEngine.getHistoryService();
    TaskService taskService = processEngine.getTaskService();
    List
list = historyService
            .createHistoricActivityInstanceQuery()
            .activityType("userTask")
            .processInstanceId(processInstanceId)
            .taskAssignee(taskAssignee)
            .finished()
            .list();
    for (HistoricActivityInstance instance : list) {
        System.out.println("任务名称:" + instance.getActivityName());
        System.out.println("任务开始时间:" + instance.getStartTime());
        System.out.println("任务结束时间:" + instance.getEndTime());
        System.out.println("任务耗时:" + instance.getDurationInMillis());
        List
taskComments = taskService.getTaskComments(instance.getTaskId());
        if (taskComments.size() > 0) {
            System.out.println("审批批注:" + taskComments.get(0).getFullMessage());
        }
    }
}

4. Advanced Operations

1. Process Definition Query

@Test
public void testDefinitionQuery() {
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    RepositoryService repositoryService = processEngine.getRepositoryService();
    List
processDefinitionList = repositoryService
            .createProcessDefinitionQuery()
            .processDefinitionKey("leaveProcess")
            .list();
    for (ProcessDefinition definition : processDefinitionList) {
        System.out.println("流程定义ID:" + definition.getId());
        System.out.println("流程定义名称:" + definition.getName());
        System.out.println("流程定义key:" + definition.getKey());
        System.out.println("流程定义版本:" + definition.getVersion());
        System.out.println("流程部署ID:" + definition.getDeploymentId());
        System.out.println("====================");
    }
}

2. Download Process Resources

@Test
public void testDownloadResource() throws Exception {
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    RepositoryService repositoryService = processEngine.getRepositoryService();
    List
list = repositoryService
            .createProcessDefinitionQuery()
            .processDefinitionKey("leaveProcess")
            .orderByProcessDefinitionVersion()
            .desc()
            .list();
    ProcessDefinition definition = list.get(0);
    String deploymentId = definition.getDeploymentId();
    InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, definition.getResourceName());
    InputStream pngInput = repositoryService.getResourceAsStream(deploymentId, definition.getDiagramResourceName());
    FileOutputStream bpmnOutPut = new FileOutputStream("D:/leave.bpmn");
    FileOutputStream pngOutPut = new FileOutputStream("D:/leave.png");
    IOUtils.copy(bpmnInput, bpmnOutPut);
    IOUtils.copy(pngInput, pngOutPut);
}

3. Delete Process Definition

@Test
public void testDeleteDeploy() {
    String deploymentId = "10001";
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    RepositoryService repositoryService = processEngine.getRepositoryService();
    repositoryService.deleteDeployment(deploymentId);
    // repositoryService.deleteDeployment(deploymentId, true); // cascade delete if needed
}

4. Business Key Usage

BusinessKey links a workflow instance to a business record (e.g., a leave request ID). It is set when starting a process and can be retrieved later to fetch related business data.

@Test
public void testStartProcess() {
    String businessKey = "8001";
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    RuntimeService runtimeService = processEngine.getRuntimeService();
    ProcessInstance instance = runtimeService.startProcessInstanceByKey("leaveProcess", businessKey);
    System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
    System.out.println("流程实例的id = " + instance.getId());
}
@Test
public void testGetBusinessKey() {
    String assignee = "李四";
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    TaskService taskService = processEngine.getTaskService();
    RuntimeService runtimeService = processEngine.getRuntimeService();
    List
taskList = taskService.createTaskQuery()
            .processDefinitionKey("leaveProcess")
            .taskAssignee(assignee)
            .list();
    for (Task task : taskList) {
        ProcessInstance instance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(task.getProcessInstanceId())
                .singleResult();
        System.out.println("业务key:" + instance.getBusinessKey());
        System.out.println("===================");
    }
}

5. Suspend / Activate Process Definitions and Instances

Suspending a definition pauses all its instances; activating resumes them. Individual instances can also be suspended or activated.

@Test
public void testSuspendAllProcessInstance() {
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    RepositoryService repositoryService = processEngine.getRepositoryService();
    ProcessDefinition processDefinition = repositoryService
            .createProcessDefinitionQuery()
            .processDefinitionKey("leaveProcess")
            .singleResult();
    boolean suspended = processDefinition.isSuspended();
    System.out.println("流程定义状态:" + (suspended ? "已挂起" : "已激活"));
    String processDefinitionId = processDefinition.getId();
    if (suspended) {
        repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
        System.out.println("流程ID:" + processDefinitionId + ",已激活");
    } else {
        repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null);
        System.out.println("流程ID:" + processDefinitionId + ",已挂起");
    }
}
@Test
public void testSuspendSingleProcessInstance() {
    String processInstanceId = "2501";
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    RuntimeService runtimeService = processEngine.getRuntimeService();
    ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
            .processInstanceId(processInstanceId)
            .singleResult();
    boolean suspended = processInstance.isSuspended();
    System.out.println("流程实例ID:" + processInstanceId + ",状态:" + (suspended ? "已挂起" : "已激活"));
    if (suspended) {
        runtimeService.activateProcessInstanceById(processInstanceId);
        System.out.println("流程实例ID:" + processInstanceId + ",状态修改为已激活");
    } else {
        runtimeService.suspendProcessInstanceById(processInstanceId);
        System.out.println("流程实例ID:" + processInstanceId + ",状态修改为已挂起");
    }
}

6. Task Assignment Strategies

Assignments can be fixed, expression‑based, or handled by listeners. Example listener implementation:

import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;

public class AssigneeTaskListener implements TaskListener {
    public void notify(DelegateTask delegateTask) {
        if (delegateTask.getName().equals("部门经理审批")) {
            delegateTask.setAssignee("赵六");
        } else if (delegateTask.getName().equals("部门经理审批")) {
            delegateTask.setAssignee("孙七");
        }
    }
}

7. Process Variables

Variables drive conditional flow. They can be set at start or during execution and accessed via UEL expressions such as ${assignee} or ${price<10000} .

import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class VariablesTest {
    @Test
    public void testDeploy() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("bpmn/leave-variables.bpmn")
                .name("请假流程")
                .deploy();
        System.out.println("流程部署ID:" + deployment.getId());
        System.out.println("流程部署名称:" + deployment.getName());
    }
    @Test
    public void testStartProcess() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RuntimeService runtimeService = processEngine.getRuntimeService();
        Map
variables = new HashMap<>();
        variables.put("day", 2);
        ProcessInstance instance = runtimeService.startProcessInstanceByKey("leaveVariablesProcess", variables);
        System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
        System.out.println("流程实例的id = " + instance.getId());
    }
    @Test
    public void testSelectTodoTaskList() {
        String assignee = "李四";
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        List
taskList = taskService.createTaskQuery()
                .processDefinitionKey("leaveVariablesProcess")
                .taskAssignee(assignee)
                .list();
        for (Task task : taskList) {
            System.out.println("流程定义id = " + task.getProcessDefinitionId());
            System.out.println("流程实例id = " + task.getProcessInstanceId());
            System.out.println("任务id = " + task.getId());
            System.out.println("任务名称 = " + task.getName());
        }
    }
    @Test
    public void testCompleteTask() {
        String assignee = "李四";
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        List
taskList = taskService.createTaskQuery()
                .processDefinitionKey("leaveVariablesProcess")
                .taskAssignee(assignee)
                .list();
        for (Task task : taskList) {
            taskService.complete(task.getId());
        }
    }
}

8. Candidate Users and Task Claiming

Define multiple candidates using the candidate-users attribute, then claim a task before completing it.

@Test
public void testSelectCandidateTaskList() {
    String candidateUser = "李四";
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    TaskService taskService = processEngine.getTaskService();
    List
taskList = taskService.createTaskQuery()
            .processDefinitionKey("leaveCandidateProcess")
            .taskCandidateUser(candidateUser)
            .list();
    for (Task task : taskList) {
        System.out.println("流程定义id = " + task.getProcessDefinitionId());
        System.out.println("流程实例id = " + task.getProcessInstanceId());
        System.out.println("任务id = " + task.getId());
        System.out.println("任务名称 = " + task.getName());
    }
}
@Test
public void testClaimTask() {
    String taskId = "2505";
    String assignee = "张三";
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    TaskService taskService = processEngine.getTaskService();
    taskService.claim(taskId, assignee);
}

9. Gateways

Examples of exclusive, parallel, and inclusive gateways are provided, demonstrating conditional routing based on process variables such as ${day > 3} .

@Test
public void testDeploy() {
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    RepositoryService repositoryService = processEngine.getRepositoryService();
    Deployment deployment = repositoryService.createDeployment()
            .addClasspathResource("bpmn/leave-EGateway.bpmn")
            .name("请假流程-排他网关")
            .deploy();
    System.out.println("流程部署ID:" + deployment.getId());
    System.out.println("流程部署名称:" + deployment.getName());
}

@Test
public void testStartProcess() {
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    RuntimeService runtimeService = processEngine.getRuntimeService();
    Map
variables = new HashMap<>();
    variables.put("day", 0);
    ProcessInstance instance = runtimeService.startProcessInstanceByKey("leaveEGatewayProcess", variables);
    System.out.println("流程定义的id = " + instance.getProcessDefinitionId());
    System.out.println("流程实例的id = " + instance.getId());
}

5. Service Overview

The main Activiti services used are:

RepositoryService : Deploy and manage process definitions and resources.

RuntimeService : Start processes and query runtime state.

TaskService : Query, claim, complete, and comment on tasks.

HistoryService : Access historical data such as completed tasks and activity instances.

ManagementService : Engine administration (e.g., job management).

6. Common Operations (Code Snippets)

Deploy a process: repositoryService.createDeployment().addClasspathResource("bpmn/xxx.bpmn").deploy();

Start a process: runtimeService.startProcessInstanceByKey("processKey", variables);

Query tasks: taskService.createTaskQuery().list();

Complete a task: taskService.complete(taskId);

Claim a task: taskService.claim(taskId, userId);

Add a comment: taskService.addComment(taskId, processInstanceId, "comment");

Suspend/activate definition: repositoryService.suspendProcessDefinitionByKey(...); repositoryService.activateProcessDefinitionByKey(...);

Suspend/activate instance: runtimeService.suspendProcessInstanceById(...); runtimeService.activateProcessInstanceById(...);

Delete deployment: repositoryService.deleteDeployment(deploymentId, true);

Query definitions: repositoryService.createProcessDefinitionQuery().list();

Query instances: runtimeService.createProcessInstanceQuery().list();

Query historic tasks: historyService.createHistoricTaskInstanceQuery().list();

By following the steps and code examples above, developers can fully integrate Activiti 7 into Spring Boot projects, manage workflows, handle tasks, and leverage advanced features such as business keys, variables, gateways, and candidate user assignments.

JavaworkflowBPMNSpringBootActivitiProcessEngineTaskManagement
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

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.