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.

Programmer1970
Programmer1970
Programmer1970
Getting Started with Flowable Workflow Engine in Spring Boot – Part 4

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: false

4. 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-demo
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaDockerworkflowBPMNSpring BootMySQLProcess Automationflowable
Programmer1970
Written by

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.

0 followers
Reader feedback

How this landed with the community

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.