Integrating Flowable Workflow Engine with Spring Boot: A Comprehensive Guide
This article provides a detailed tutorial on using Flowable as a BPMN workflow engine within a Spring Boot application, covering the history of workflow engines, core concepts, Maven dependencies, BPMN diagram creation, process deployment, task configuration, service task implementation, and troubleshooting tips.
1. Introduction
The author, a senior architect, shares a step‑by‑step guide for building a leave‑request workflow using the Flowable BPMN engine integrated into a Spring Boot project.
2. Workflow Engine Overview
Early workflow engines started with jBPM (a Java‑based engine from JBoss). From jBPM emerged Activiti, which later forked into Camunda and Flowable. The three mainstream engines today are:
Activiti – cloud‑oriented, moving toward Spring Cloud and Docker.
Flowable – feature‑rich, offering many extension points.
Camunda – lightweight, provides a compact BPMN editor based on bpmn.io.
3. Core Concepts
Event – start, end, intermediate, boundary events.
Sequence Flow – connects events, tasks, gateways.
Task – user, service, script, receive, send.
Gateway – exclusive, parallel, event, inclusive.
4. Spring Boot Integration
4.1 Maven Dependency
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>6.7.2</version>
</dependency>4.2 Database Configuration
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://ip:port/process?useSSL=false&useUnicode=true&characterEncoding=utf-8
username: username
password: pw4.3 BPMN Diagram Creation
Use the Flowable BPMN visualizer plugin (or the IDEA plugin) to create a file named ask_for_leave.bpmn20.xml . The diagram includes a start event, employee user task, group‑leader approval gateway, manager approval gateway, a service task for failure notification, and an end event.
4.4 Process Definition (XML)
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" ...>
<process id="ask_for_leave" name="ask_for_leave" isExecutable="true">
<startEvent id="sid-start"/>
<userTask id="sid-leave" name="请假" flowable:assignee="#{leaveTask}"/>
<sequenceFlow sourceRef="sid-start" targetRef="sid-leave"/>
...
</process>
</definitions>4.5 Service Task Implementation
@Slf4j
@Component
public class LeaveFailService implements JavaDelegate {
@Override
public void execute(DelegateExecution delegateExecution) {
log.info("审批不通过{}", delegateExecution.getCurrentActivityId());
}
}4.6 Runtime API for Diagram Viewing
@RestController
public class LeaveController {
@Autowired RuntimeService runtimeService;
@Autowired RepositoryService repositoryService;
@Autowired ProcessEngine processEngine;
@GetMapping("/pic")
public void showPic(HttpServletResponse resp, String processId) throws Exception {
ProcessInstance pi = runtimeService.createProcessInstanceQuery()
.processInstanceId(processId).singleResult();
if (pi == null) return;
List<Execution> executions = runtimeService.createExecutionQuery()
.processInstanceId(processId).list();
List<String> activityIds = new ArrayList<>();
for (Execution exe : executions) {
activityIds.addAll(runtimeService.getActiveActivityIds(exe.getId()));
}
BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, new ArrayList<>(),
engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(),
engconf.getClassLoader(), 1.0, false);
OutputStream out = resp.getOutputStream();
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
}5. Common Issues
When the generated diagram shows garbled characters ("口口口"), the host lacks a default font. Configure the engine to use a installed font, e.g. in FlowableConfig set setActivityFontName("宋体") , setLabelFontName("宋体") , and setAnnotationFontName("宋体") . Also, modifying a BPMN file after a process instance has started does not affect the running instance because the definition is already persisted.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
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.