Getting Started with Flowable Workflow Engine in Spring Boot – Part 4
This guide walks through setting up Flowable 6.8.0 with Spring Boot 2.7.x, configuring MySQL, defining and deploying BPMN processes, managing runtime tasks, handling dynamic assignments, querying history, adding extensions like multi‑instance approvals and email notifications, and finally containerizing the application with Docker.
1. Environment Preparation
Required stack: JDK 11+, Spring Boot 2.7.x, Flowable 6.8.0, MySQL 8.0.
2. Dependency Configuration
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Flowable Starter -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>6.8.0</version>
</dependency>
<!-- MySQL Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
</dependencies>3. Database Configuration
spring:
datasource:
url: jdbc:mysql://localhost:3306/flowable?useSSL=false&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
flowable:
# Auto‑update DB schema
database-schema-update: true
# Full history level
history-level: full
# Disable async executor during development
async-executor-activate: false4. Process Definition and Deployment
Design a leave‑request BPMN file (e.g., leave-request.bpmn20.xml) with the following structure:
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL">
<process id="leaveProcess" name="请假流程">
<startEvent id="start"/>
<userTask id="applyTask" name="提交申请"/>
<exclusiveGateway id="decision"/>
<userTask id="managerApproval" name="经理审批"/>
<endEvent id="end"/>
<sequenceFlow sourceRef="start" targetRef="applyTask"/>
<sequenceFlow sourceRef="applyTask" targetRef="decision"/>
<sequenceFlow sourceRef="decision" targetRef="managerApproval" conditionExpression="${days <= 3}"/>
<sequenceFlow sourceRef="managerApproval" targetRef="end"/>
</process>
</definitions>Place the BPMN file under src/main/resources/processes/ so that Spring Boot deploys it automatically, or deploy programmatically:
@Autowired
private RepositoryService repositoryService;
public void deployProcess() throws Exception {
InputStream bpmnStream = new FileInputStream("path/to/leave-request.bpmn20.xml");
repositoryService.createDeployment()
.addInputStream("leave-request.bpmn20.xml", bpmnStream)
.deploy();
}5. Process Instance Operations
Start a process instance with variables:
@Autowired
private RuntimeService runtimeService;
public String startProcess() {
Map<String, Object> variables = new HashMap<>();
variables.put("days", 3); // process variable
ProcessInstance instance = runtimeService.startProcessInstanceByKey("leaveProcess", variables);
return instance.getId();
}Query and complete tasks:
@Autowired
private TaskService taskService;
public void completeTask(String taskId) {
Map<String, Object> variables = new HashMap<>();
variables.put("approved", true);
taskService.complete(taskId, variables);
}
public List<Task> getTasks(String assignee) {
return taskService.createTaskQuery()
.taskAssignee(assignee)
.list();
}6. Dynamic Task Assignment
Static assignment in BPMN:
<userTask id="managerApproval" name="经理审批" flowable:assignee="manager1"/>Dynamic assignment using a process variable:
// Set variable when starting the process
variables.put("nextApprover", "user123");
// BPMN expression
<userTask id="task" name="动态任务" flowable:assignee="${nextApprover}"/>7. History Data Query
@Autowired
private HistoryService historyService;
public List<HistoricProcessInstance> getHistoryInstances() {
return historyService.createHistoricProcessInstanceQuery()
.finished()
.list();
}
public List<HistoricTaskInstance> getHistoryTasks(String processInstanceId) {
return historyService.createHistoricTaskInstanceQuery()
.processInstanceId(processInstanceId)
.list();
}8. Extension Features
Multi‑instance (countersign) task using flowable:candidateUsers or flowable:candidateGroups:
<userTask id="ccApproval" name="会签审批">
<documentation>需所有成员审批通过</documentation>
<multiInstanceLoopCharacteristics isSequential="false" flowable:collection="ccList" flowable:elementVariable="ccUser">
<completionCondition>${nrOfCompletedInstances/nrOfInstances >= 1}</completionCondition>
</multiInstanceLoopCharacteristics>
</userTask>Email notification integrated with Spring Mail:
@Autowired
private JavaMailSender mailSender;
public void sendNotification(String to, String taskId) {
mailSender.send(new SimpleMailMessage() {{
setTo(to);
setSubject("新任务待处理");
setText("您有新任务,ID: " + taskId);
}});
}9. Docker Deployment
Package the application: mvn clean package Create a Docker image (Dockerfile):
FROM openjdk:11-jre
COPY target/flowable-demo.jar /app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]Build and run the container:
docker build -t flowable-demo .
docker run -d -p 8080:8080 --name flowable-app flowable-demoSigned-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.
Programmer1970
Formerly called 'Code to 35'. Add our main WeChat ID to access a wealth of shared resources (algorithms, interview prep, tech stacks: Java, Python, Go, big data). We mainly share serious development techniques, focusing on output-driven input. Occasionally we post life snippets and gossip. Our aim is to attract precise traffic and test advertising opportunities.
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.
