Backend Development 21 min read

Integrating Flowable Workflow Engine with Spring Boot: A Step‑by‑Step Guide

This article introduces the evolution of Java workflow engines, explains core BPMN concepts, and provides a comprehensive tutorial on integrating Flowable with Spring Boot—including Maven dependencies, database configuration, BPMN diagram creation, service task implementation, diagram viewing API, and unit testing.

Top Architect
Top Architect
Top Architect
Integrating Flowable Workflow Engine with Spring Boot: A Step‑by‑Step Guide

Early workflow engines such as jBPM gave way to Activiti, Camunda and Flowable, each with distinct characteristics; today the three dominate the market.

1. Workflow Engine Overview

jBPM was created by Tom Baeyens and later split into Activiti, which subsequently forked into Camunda and Flowable. The three engines differ in focus: Activiti leans toward cloud integration (Spring Cloud, Docker), Flowable offers rich extensibility, and Camunda provides a lightweight BPMN editor.

2. Core BPMN Concepts

A BPMN diagram consists of events, sequence flows, tasks, and gateways. Tasks include user tasks, service tasks, script tasks, receive tasks, and send tasks, each serving different automation needs. Gateways (exclusive, parallel, event, inclusive) control flow branching.

3. Spring Boot Integration with Flowable

3.1 Add Maven Dependency

<dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-spring-boot-starter</artifactId>
    <version>6.7.2</version>
</dependency>

Process definitions placed under resources/processes are auto‑deployed.

3.2 Configure Database

spring:
  datasource:
    driverClassName: com.mysql.jdbc.Driver
    url: jdbc:mysql://ip:port/process?useSSL=false&useUnicode=true&characterEncoding=utf-8
    username: username
    password: pw

The engine creates tables and stores runtime data automatically.

3.3 Create BPMN Diagram

Use the Flowable BPMN Visualizer plugin or the IDEA BPMN editor to design a leave‑request process (start → employee user task → leader approval → manager approval → end). Save the file as ask_for_leave.bpmn20.xml .

3.4 Service Task Implementation

@Slf4j
@Component
public class LeaveFailService implements JavaDelegate {
    @Override
    public void execute(DelegateExecution delegateExecution) {
        log.info("审批不通过{}", delegateExecution.getCurrentActivityId());
    }
}

The class implements JavaDelegate and runs custom logic when the service task is triggered.

3.5 Diagram Viewing API

@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
executions = runtimeService.createExecutionQuery()
                .processInstanceId(processId).list();
        List
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();
    }
}

The endpoint returns a PNG of the current process state.

3.6 Unit Tests

@SpringBootTest
@Slf4j
@ActiveProfiles("dev")
class ProcessApplicationTests {
    @Autowired RuntimeService runtimeService;
    @Autowired TaskService taskService;
    static final String yuangongId = "yuangongID_3";
    static final String zuzhangId = "zuzhangId_3";
    static final String manageId = "manageId_3";

    @Test
    void askForLeave() {
        HashMap
map = new HashMap<>();
        map.put("leaveTask", yuangongId);
        ProcessInstance pi = runtimeService.startProcessInstanceByKey("ask_for_leave", map);
        runtimeService.setVariable(pi.getId(), "name", "javaboy");
        runtimeService.setVariable(pi.getId(), "reason", "休息一下");
        runtimeService.setVariable(pi.getId(), "days", 10);
        log.info("创建请假流程 processId:{}", pi.getId());
    }
    // additional tests for submission, approval, rejection omitted for brevity
}

Tests demonstrate starting the process, completing user tasks, and handling approval outcomes.

4. Common Issues

4.1 Diagram Text Appears as Boxes

Install a default font (e.g., SimSun) or configure Flowable to use a specific font:

@Configuration
public class FlowableConfig implements EngineConfigurationConfigurer
{
    @Override
    public void configure(SpringProcessEngineConfiguration cfg) {
        cfg.setActivityFontName("宋体");
        cfg.setLabelFontName("宋体");
        cfg.setAnnotationFontName("宋体");
    }
}

4.2 Modifying a Deployed Process Definition

Changes only affect new process instances; already‑running instances keep the original definition because the runtime data is persisted.

javaworkflowBPMNSpring BootFlowable
Top Architect
Written by

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.

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.