How to Implement Service Tasks in Activiti 7 with Spring Boot
This guide demonstrates how to configure and execute ServiceTask nodes in Activiti 7.1 within a Spring Boot 2.3.12 application, covering service class implementation, three configuration methods (direct class, delegate expression, Spring bean method), BPMN XML definition, and a REST endpoint to start the process.
Environment: Spring Boot 2.3.12.RELEASE + Activiti 7.1.0.M6
Introduction
In Activiti, a ServiceTask is a node that can execute custom service logic after the previous task completes, such as recording logs automatically before moving to the next task.
After the previous task finishes, the process can automatically perform operations like logging, then proceed to the next task.
Process Design
Write Service Class
public class LogService implements JavaDelegate {
@Override
public void execute(DelegateExecution execution) {
System.out.println("开始记录日志");
}
}The service class must implement the JavaDelegate interface.
Configure ServiceTask Node
Method 1: Directly specify the service class.
Method 2: Use a delegate expression.
Method 3: Call a method on a custom Spring bean.
All three methods allow execution of local service logic.
Process Definition (BPMN XML)
<?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"
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.st.org">
<process id="st" name="st" isExecutable="true">
<startEvent id="startevent1" name="Start"/>
<userTask id="usertask1" name="办公用品申请" activiti:assignee="${userId}"/>
<serviceTask id="servicetask1" name="生成申请日志" activiti:expression="${customService.log(execution)}"/>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"/>
<sequenceFlow id="flow2" sourceRef="usertask1" targetRef="servicetask1"/>
<endEvent id="endevent1" name="End"/>
<userTask id="usertask2" name="部门经理" activiti:assignee="${jl}"/>
<sequenceFlow id="flow3" sourceRef="usertask2" targetRef="endevent1"/>
<sequenceFlow id="flow4" sourceRef="servicetask1" targetRef="usertask2"/>
</process>
<!-- ... -->
</definitions>Start Process
@GetMapping("/start")
public R startProcess(String processDefinitionId, String userId) {
Map<String, Object> variables = new HashMap<>();
variables.put("userId", userId);
// Start process instance (also starts the first task)
ProcessInstance instance = ps.startProcessInstanceAssignVariables(processDefinitionId, variables);
// Set the next executor
variables.put("jl", "20000");
ps.executionTask(variables, instance.getId());
return R.success();
}The execution result shows the ServiceTask executed successfully and the process moved to the department manager node.
Runtime task table (act_ru_task) confirms the transition.
ServiceTask execution completes the workflow.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
