Skip to content

Flowable:BPMN 流程如何从模型走到运行时

Flowable 是一组可嵌入 Java 应用的流程引擎。BPMN 引擎负责可预先建模的业务流程,CMMN 引擎处理更依赖事件和人工判断的案例,DMN 引擎执行决策表;Event Registry、身份、任务、变量和作业服务提供跨引擎共享能力。应用既可以直接调用 Java API,也可以把引擎放在服务端,通过 REST 接入。

从源码看,BPMN 图不会被逐节点解释成一串递归方法调用。部署阶段先把 XML 转成模型,为节点挂接 ActivityBehavior;运行阶段再把一次 API 调用包装成 Command,在同一个 CommandContext 中不断消费 Agenda 队列里的 operation。流程走到 User Task、Receive Task 或异步节点时,内存调用停止,执行位置被写入数据库,下一次外部事件或作业线程再恢复执行。

这套结构同时解释了 Flowable 的优势和成本。服务 API、命令拦截器、持久化 Session、流程行为与作业服务彼此分层,扩展点很多;另一方面,完整仓库包含 90 个 flowable-* 模块,配置项、共享服务和兼容层也很多。表达式、脚本、Java Delegate、HTTP、Mail 等节点还可能执行带副作用的业务逻辑,生产环境必须把模型发布权、可调用 Bean、网络出口和凭据管理当作安全边界。

下面先画出全仓库的职责地图,再以 BPMN 主引擎为中心,沿 Spring Boot 启动、模型部署、流程启动、人工任务完成和异步作业五条链路深入。CMMN、DMN、Event Registry 和 Flowable 5 兼容模块只说明各自如何接入,不声称逐一覆盖全部模块。

GitHub 仓库信息

信息内容
项目标题Flowable
项目描述面向开发者、系统管理员和业务用户的轻量工作流与业务流程管理平台,提供 Java 编写的 BPMN 流程、CMMN 案例和 DMN 决策引擎。
GitHub 仓库flowable/flowable-engine
官网地址Flowable 官网
主要开发语言GitHub Languages API 的动态元数据快照(2026-09-04,不能绑定 source_commit):Java 94.3%、JavaScript 4.95%、SQLPL 0.21%
开源许可证Apache-2.0
最近代码更新2026-09-02(GitHub pushed_at,核对日期:2026-09-04)

仓库结构与模块职责

根 POM 默认聚合模型、共享服务和核心引擎,deploydistro 等 Maven Profile 再引入 Spring、REST、兼容层和集成模块。下面的目录树按语义裁剪,不等于完整模块清单。

text
flowable-engine/
├── modules/
│   ├── flowable-engine-common-api/      # 通用 Engine、Command、事件与异步接口
│   ├── flowable-engine-common/          # CommandContext、拦截器、Session、锁与 MyBatis 基础
│   ├── flowable-bpmn-model/             # BPMN 内存模型
│   ├── flowable-bpmn-converter/         # BPMN XML 与模型转换
│   ├── flowable-process-validation/     # BPMN 语义校验
│   ├── flowable-engine/                 # BPMN API、命令、Agenda、行为、实体与查询
│   ├── flowable-task-service[-api]/     # 跨引擎任务实体和持久化服务
│   ├── flowable-variable-service[-api]/ # 变量类型、实体和持久化服务
│   ├── flowable-job-service[-api]/      # 异步、定时、暂停与死信作业
│   ├── flowable-eventsubscription-*     # 消息、信号等事件订阅
│   ├── flowable-cmmn-*                  # CMMN 模型、转换、校验与案例引擎
│   ├── flowable-dmn-*                   # DMN 模型、XML 转换与决策引擎
│   ├── flowable-event-registry-*        # 外部事件模型、通道和引擎集成
│   ├── flowable-spring/                 # Spring 事务、生命周期与资源自动部署
│   ├── flowable-spring-boot/            # Starter、自动配置和样例
│   ├── flowable-rest/                   # BPMN REST 资源
│   └── flowable5-*                      # 历史流程定义兼容路径
├── docs/docusaurus/docs/                # 官方文档源码
├── distro/sql/                          # 多数据库建表与升级脚本
├── tooling/archetypes/                  # 测试工程脚手架
├── build-tools/                         # Checkstyle 等构建规则
└── pom.xml                              # 8.1.0-SNAPSHOT、JDK 17、模块与 Profile
语义层关键模块或文件职责与上下游
公开 APIRepositoryServiceRuntimeServiceTaskServiceManagementService接收部署、启动、任务和作业操作,大多数实现立即转交给 CommandExecutor
命令基础设施AbstractEngineConfigurationCommandContext组装日志、事务、上下文和自定义拦截器,统一 Session flush、关闭和异常传播
BPMN 部署flowable-bpmn-converterflowable-process-validationBpmnDeployer把 XML 解析为模型,执行 XSD/语义校验,持久化流程定义并刷新缓存和事件订阅
BPMN 运行时ProcessInstanceHelperFlowableEngineAgendaContinueProcessOperation建立执行树,计划 operation,执行节点行为并决定同步、等待或异步分流
共享状态服务flowable-task-serviceflowable-variable-serviceflowable-identitylink-service为 BPMN、CMMN 等引擎提供任务、变量和参与者关系的统一实体与持久化能力
后台作业flowable-job-service查询到期作业、写入锁 owner 和到期时间、提交线程池、执行 Handler、重试或转死信
宿主集成flowable-springflowable-spring-bootflowable-rest将引擎放入 Spring 生命周期,发现流程资源,暴露 Bean 或 HTTP 入口

五个核心机制

API 最终汇入 Command

Command 是描述一次引擎操作及其参数的对象。RuntimeServiceImpl.startProcessInstanceByKey()RepositoryServiceImpl.deploy()TaskServiceImpl.complete() 的共同点,是把参数封装成命令后交给 CommandExecutor。默认拦截器链包含日志、数据库特定重试、事务、CommandContext 和最终命令执行器;前后还可以插入自定义 CommandInterceptor

CommandContext 是一次引擎调用的工作单元。CommandContext 保存本次命令打开的 Session、异常和关闭监听器:正常结束先通知监听器,再 flush Session;失败时触发失败监听器;无论成功与否都关闭 Session。Spring 版本用 SpringTransactionInterceptor 接入宿主事务,嵌套服务调用还可以复用当前上下文。这意味着一个 API 返回成功,通常也意味着同一命令中的持久化刷新已经完成;运行到异步边界后的业务结果则不在这一事务承诺里。

部署把模型节点变成可执行行为

BPMN XML 先由 BpmnXMLConverter 转为 BpmnModel,再经过 ProcessValidator 做语义校验。解析处理器随后把 User Task、Service Task、Gateway、Event 等模型元素绑定到具体 ActivityBehavior。运行期因此无需重新解释 XML,只需从流程定义缓存取得模型,并调用当前节点已经挂接的行为。

部署不只是保存一份文件。BpmnDeployer 还会计算定义版本和 ID,写入授权,更新定时器和事件订阅,生成可选流程图,刷新流程定义缓存。重复部署过滤、租户、派生部署和 Flowable 5 兼容会在同一链路中改变行为。

Agenda 如何推进执行

每次根命令都有一个 Agenda,也就是当前命令的待执行 operation 队列。命令本身可以把 ContinueProcessOperationTakeOutgoingSequenceFlowsOperationTriggerExecutionOperation 等 operation 放入队列;CommandInvoker 持续取出并执行,直到队列为空。一个 operation 又能计划后续 operation,所以网关分支、子流程、边界事件和结束处理都能在同一事务内继续推进。

流程图的连线描述控制流,真正推进这些连线的是 Agenda 队列;execution tree 则保存流程实例、子流程和并行分支的运行位置。排查“为什么没有走到下一节点”时,应同时看当前 ExecutionEntity、当前 FlowElement、对应行为以及 Agenda 计划了什么,单看 Java 调用栈不够。

等待状态把控制权交回数据库

User Task 创建 TaskEntity 后不会主动计划离开当前节点。当前 execution 保留在该活动上,任务、变量和参与者关系写入 ACT_RU_* 表,调用结束。稍后 TaskService.complete() 删除或归档任务,计划 TriggerExecutionOperation,再由 UserTaskActivityBehavior.trigger() 离开节点。

Receive Task、消息捕获、定时器和外部事件也遵循类似原则。等待状态把执行位置持久化到数据库,当前线程随命令结束;JVM 可以在等待期间重启,另一个应用节点也可以根据同一数据库恢复流程。

异步作业把事务切成两段

当 FlowNode 标记为异步时,ContinueProcessOperation 不执行节点行为,而是创建 JobEntity 并调度。当前 API 事务只承诺作业已落库;后台获取线程再查询到期作业、设置锁 owner 与锁过期时间、放入执行线程池,并在新事务中调用 JobHandler。

异步节点把流程切成两个事务阶段:数据库作业先成为可靠交接点,线程池再作为后续消费者。集群节点通过锁字段和乐观锁竞争工作;失败作业在独立新事务中减少重试次数,进入定时作业等待下一次尝试,耗尽后进入死信表。

源码环境与运行边界

固定源码的根 POM 声明 8.1.0-SNAPSHOT 和 JDK 17。2026 年 9 月 4 日核对到的最新公开 Release 是 flowable-8.0.0,发布于 2026 年 2 月 27 日。Release 说明明确 Flowable 8 升级到 Spring Framework 7、Spring Boot 4 和 Jackson 3;快照源码仍保留 Jackson2JsonObjectRestVariableConverter 这条 Jackson 2 REST 兼容路径,不能把 8.1 快照行为直接等同于 8.0 Release。

本次完成了固定提交的静态阅读、根 POM 内容哈希比对和文档校验,没有运行目标仓库的 Maven 构建、JUnit、数据库、Spring Boot 应用、REST 服务或异步执行器。下面是复现路径,不是亲测记录。

获取同一份源码

前置条件是 Git、JDK 17 和可用的 Maven。选择空目录执行:

bash
git clone https://github.com/flowable/flowable-engine.git
cd flowable-engine
git checkout d6d39ce1c69ff244f2d9dc6af756a9b95e865586
java -version
mvn -version

git status --short --branch 应显示 detached HEAD 或该固定提交,并且没有意外改动。若只阅读 BPMN 主引擎,可先构建相关反应器模块:

bash
mvn -pl modules/flowable-engine -am -DskipTests package

预期成功信号是 Maven 以 BUILD SUCCESS 结束,并在相关模块生成 target/ 产物。此命令显式跳过测试;要验证测试,应另行运行测试目标并查看测试汇总:

bash
mvn -pl modules/flowable-engine -am test

核心 API 片段

官方入门文档使用独立 ProcessEngineConfiguration 配合 JDBC 数据库,也支持 Spring Boot Starter。Flowable 8 的 Spring 集成面向 Spring Boot 4.x。下面是围绕已配置好的三个 Service 的核心 API 片段,不是可单独编译的最小程序;数据库、引擎 Bean、BPMN 资源和 import 需要由宿主工程提供。最小验证不应停在应用启动,至少要完成部署、启动和人工任务续行:

java
Map<String, Object> variables = Map.of("days", 3);

Deployment deployment = repositoryService.createDeployment()
    .addClasspathResource("processes/holiday-request.bpmn20.xml")
    .deploy();

ProcessInstance instance = runtimeService
    .startProcessInstanceByKey("holidayRequest", variables);

Task task = taskService.createTaskQuery()
    .processInstanceId(instance.getId())
    .singleResult();

taskService.complete(task.getId(), Map.of("approved", true));

可观察结果应包括:部署查询能找到流程定义;启动后 ACT_RU_EXECUTION 有运行实例;走到 User Task 时任务查询返回一条任务;完成后任务消失并出现下一个等待状态或流程结束。若使用自动建表,开发环境可启用 schema update;生产环境更适合先审阅 distro/sql 或模块内数据库脚本并显式迁移。

整体架构地图

为了避免把 BPMN 深挖误读成“所有引擎都已逐链路展开”,各引擎在本文中的源码覆盖边界如下:

引擎或入口固定源码入口本文覆盖未展开部分
BPMNProcessEngineConfigurationImpl深入启动、部署、执行、人工任务和异步作业全部 90 个语义模块的逐文件审计
CMMNCmmnEngineConfiguration引擎装配和共享任务、变量、作业服务边界plan item 生命周期和完整案例链路
DMNDmnEngineConfiguration决策引擎角色及与 BPMN 的集成位置决策表解析和逐规则求值
Event RegistryEventRegistryEngineConfiguration外部事件通道和共享服务边界入站、出站通道的完整消息链路
RESTProcessInstanceCollectionResource作为 Java API 之上的传输适配器REST 资源逐接口分析、认证部署和权限配置

这张矩阵说明了一个重要边界:共享服务的存在可以从固定源码确认,但 CMMN、DMN 和 Event Registry 的完整业务语义仍需要各自的专门走读。

想理解的能力阅读入口继续向下读
引擎如何创建AbstractBuildableEngineConfiguration.buildEngine()ProcessEngineConfigurationImpl.init()ProcessEngineImpl
Spring Boot 如何装配ProcessEngineAutoConfigurationProcessEngineServicesAutoConfigurationProcessEngineFactoryBeanSpringProcessEngineConfiguration
API 的事务边界AbstractEngineConfiguration.initCommandInterceptors()CommandContextInterceptorTransactionContextInterceptorCommandContext.close()
BPMN 如何部署RepositoryServiceImpl.createDeployment()DeployCmdBpmnDeployerParsedDeploymentBuilderBpmnParse
流程如何启动RuntimeServiceImpl.startProcessInstanceByKey()StartProcessInstanceCmdProcessInstanceHelperCommandInvoker
人工任务如何恢复UserTaskActivityBehaviorCompleteTaskCmdTaskHelperTriggerExecutionOperation
异步作业如何集群执行AcquireAsyncJobsDueRunnableAcquireJobsCmdExecuteAsyncRunnableJobRetryCmd
动态跳转如何实现RuntimeService.createChangeActivityStateBuilder()ChangeActivityStateBuilderImplChangeActivityStateCmdDefaultDynamicStateManager

引擎启动链路

独立引擎

buildEngine() 只做四步:初始化配置、准备构建后回调、创建引擎、执行回调。真正复杂的是 ProcessEngineConfigurationImpl.init()ProcessEngineConfigurationImpl.init() 按依赖顺序创建命令设施、表达式、数据源、服务、解析器、缓存、实体管理器、部署器、事件分发器和异步执行器。

ProcessEngineImpl 构造函数取得各项 Service,在命令事务中执行 schema management,注册引擎,并按配置启动已激活的异步执行器;buildEngine() 随后执行 post-build consumer。关闭时则先注销引擎、停止两个异步执行器,再关闭配置和通知生命周期监听器。

Spring Boot 引擎

Spring Boot 路线增加了两层宿主控制。ProcessEngineAutoConfiguration 创建 SpringProcessEngineConfiguration,注入 DataSource、事务管理器、异步执行器和自动部署资源;ProcessEngineServicesAutoConfiguration 再创建 ProcessEngineFactoryBean。FactoryBean 调用 buildProcessEngine(),并在销毁时关闭引擎。

SpringProcessEngineConfiguration 关闭了“引擎构造后立即启动执行器”的默认行为。Spring 生命周期进入 start() 后,start() 才遍历已构建引擎,调用 startExecutors() 并按 deployment mode 自动部署 classpath 中发现的流程资源;自动部署位置、后缀和检查开关由 FlowableProperties 暴露。这个顺序避免后台线程在 Spring 容器尚未完全就绪时抢先工作,也让 Flowable 的事务交给 PlatformTransactionManager 管理。

BPMN 部署链路

DeploymentBuilderImpl.deploy() 回到 RepositoryServiceImpl.deploy(),后者执行 DeployCmd。命令先处理 Flowable 5 兼容和重复部署过滤,再保存 DeploymentEntity,最后交给 DeploymentManager 中注册的 deployer。

ParsedDeploymentBuilder 只挑选 BPMN 资源。BpmnParse.execute() 依次执行 XML 转换、可选 XSD 校验、语义校验、parse handler 和图形信息处理;错误会中断整个命令。随后 BpmnDeployer.deploy() 检查 definition key 冲突,为新版本计算 ID,持久化定义和授权,更新定时器与事件,再刷新缓存。

部署阶段把“业务图”转换为“可执行定义”。若部署失败,运行时不会得到半成品模型,因为部署与定义写入处在同一个命令事务中。

流程实例启动链路

RuntimeServiceImpl.startProcessInstanceByKey() 创建 StartProcessInstanceCmd。命令按 key、tenant 和 fallback 规则解析流程定义,校验启动表单后交给 ProcessInstanceHelper。后者拒绝已挂起定义,从缓存取得 Process 和起始元素,创建根 execution、初始子 execution、变量、身份关系、历史记录与事件订阅,然后计划 ContinueProcessOperation

CommandInvokerwhile (!agenda.isEmpty()) 是同步推进的核心。ContinueProcessOperation 读取 execution 当前元素:遇到 Sequence Flow 就处理监听器和目标节点;遇到 FlowNode 就创建边界事件,选择同步、多实例或异步路径,再调用已经绑定的行为。

同步 Service Task 可能在一次 startProcessInstanceByKey() 中直接执行。若 Delegate 抛出普通运行时异常,当前命令事务回滚;若模型在前面设置了 async="true",启动事务只创建作业,Delegate 的异常由后台作业重试链处理。这是建模层直接改变事务边界的例子。

人工任务链路

创建任务并停在等待状态

UserTaskActivityBehavior.execute() 创建任务,解析名称、到期时间、优先级、表单、assignee、owner、候选用户和候选组。任务插入后才建立人员关系,因为 identity link 需要 task ID。创建监听器与 TASK_CREATED 事件在同一命令内触发。

如果 skip expression 判定跳过,任务会被立即删除并继续离开节点;普通 User Task 不调用 leave(),所以 Agenda 耗尽后事务结束,execution 留在当前节点。这正是可持久化等待状态。

完成任务并恢复流程

CompleteTaskCmd 先拒绝用 BPMN API 完成 CMMN 创建的任务,并保留 Flowable 5 兼容分流。TaskHelper.completeTask() 写入流程变量和本地变量,触发 complete listener 与事件,记录完成人和历史,再完成任务实体。若监听器抛出 BPMN Business Error,错误会按模型传播,不再执行普通续行;否则计划 TriggerExecutionOperation

TriggerExecutionOperation 要求当前行为实现 TriggerableActivityBehaviorUserTaskActivityBehavior.trigger() 会检查同一 execution 下是否还有未删除任务,确认后才 leave()。这能防止绕过任务完成直接 signal execution。

异步作业链路

AcquireAsyncJobsDueRunnable 先看线程池剩余容量,再执行 AcquireJobsCmd。命令查询可执行作业,把本节点标识和锁到期时间写入每个作业。多个节点同时获取时,乐观锁异常被视为集群中的正常竞争;还可以选择全局获取锁,让节点轮流填充队列。

ExecuteAsyncRunnable 对 exclusive job 额外锁定流程实例,避免同一实例的并发作业交错修改执行树。事务型作业通过 ExecuteAsyncRunnableJobCmd 重新查询数据库,因为排队期间作业可能已被边界事件或另一分支删除;确认仍存在后才交给 JobManager 和具体 JobHandler。

失败路径不会在已回滚事务里直接修改重试次数。FailedJobListener.closeFailure() 使用 transactionRequiresNew() 创建新命令,BPMN 的 JobRetryCmd 读取模型上的 retry time cycle。仍有次数时,作业移入 timer job 并计算下一次到期时间;次数耗尽或异常不可恢复时,作业进入 dead letter。异常消息和堆栈也随新作业实体保存。

分支、失败与扩展

分流条件源码行为排障入口
流程定义不存在或已挂起启动命令在创建 execution 前抛错StartProcessInstanceCmdProcessInstanceHelper
BPMN 校验有 errorBpmnParse 汇总错误并抛出 FlowableException;warning 只记录日志部署异常、资源名、XSD 和 ProcessValidator 输出
节点同步执行行为与后续 operation 留在当前命令事务API 异常、事务回滚、执行监听器与 Delegate
节点 async="true"当前事务创建作业,后台事务执行行为ACT_RU_JOB、锁字段、Async Executor 日志
User Task skip expression 为真任务插入后立即删除,不触发普通任务事件并直接续行模型表达式、变量值、SkipExpressionUtil
complete listener 抛 BPMN Error错误按模型传播,普通 TriggerExecutionOperation 不再计划Task listener、边界错误事件、execution 当前节点
作业排队时已被删除执行命令重新查询后直接跳过ExecuteAsyncRunnableJobCmd 的调试日志
作业执行失败新事务减少重试并转 timer job;耗尽后转 dead lettertimer job、dead letter、异常堆栈
集群竞争同一作业lock owner、lock expiration 与乐观锁决定归属获取线程日志、数据库时钟、锁过期配置
Flowable 5 流程定义部署、启动、任务和作业命令进入兼容 Handlerflowable5-* classpath 与兼容开关
扩展需求合适入口代价与边界
给所有 API 增加审计、租户或重试自定义 CommandInterceptor位于事务主路径,错误会影响所有命令
在引擎初始化前后替换组件EngineConfigurator.beforeInit() / configure()依赖初始化顺序和 priority,升级时需复核内部对象
实现业务 Service TaskJavaDelegate、delegate expression能访问流程变量和 Spring Bean,也可能执行任意副作用
实现新的 BPMN 节点行为ActivityBehaviorFactory / ActivityBehavior属于内部 SPI,需要理解 Agenda、execution 和历史记录
监听任务、流程和作业事件BPMN listener、FlowableEventListener同步 listener 可能延长事务;异常语义取决于监听器类型
运行中跳转、撤回或加签ChangeActivityStateBuilder会重写执行树和关联任务,应覆盖并发、多实例、子流程与历史测试

安全上最容易被低估的是模型内容。ProcessExpressionManager 接收可调用的 Bean 映射;DefaultActivityBehaviorFactory 为 Class Delegate、Delegate Expression、Script、Shell、HTTP 和 Mail 等模型行为创建执行对象。流程定义应像可执行代码一样经过版本控制、评审和发布授权,REST 暴露也应另行配置认证、租户隔离和网络策略。

数据表如何对应运行状态

前缀典型表含义
ACT_RE_*ACT_RE_DEPLOYMENTACT_RE_PROCDEFACT_RE_MODELRepository,部署资源和流程定义
ACT_RU_*ACT_RU_EXECUTIONACT_RU_TASKACT_RU_VARIABLEACT_RU_JOBRuntime,当前执行树、任务、变量和作业
ACT_HI_*历史流程、活动、任务和变量表History,已经发生的审计与查询数据

当流程停在 User Task 时,重点关联 ACT_RU_EXECUTIONACT_RU_TASK 和 identity link;异步节点则增加 ACT_RU_JOB。执行结束后,EndExecutionOperation 会清理运行时执行数据;是否还能查询完整轨迹取决于历史级别和异步历史配置。直接改表会绕过实体缓存、版本字段、事件和历史管理,不适合作为常规修复手段。

设计取舍

命令统一事务边界。 对外 Service 不自行拼接事务和持久化细节,拦截器链让日志、重试、上下文与扩展按统一顺序工作。代价是自定义拦截器位于所有 API 的主路径,错误影响面很大。

模型与行为分离。 部署期完成解析和行为绑定,运行期围绕 execution 与 behavior 工作,既保留 BPMN 语义,也允许替换行为工厂。内部 SPI 与初始化顺序较复杂,跨大版本升级需要重新核对。

Agenda 显式表达控制流。 operation 队列为网关、边界事件、子流程和调试监听提供统一执行面。理解问题时需要同时掌握 execution tree、模型节点和 Agenda,学习成本高于普通状态机。

等待状态和作业都持久化。 长流程不占用线程,异步交接、集群竞争、重试和死信也有数据库状态可查。数据库因此同时承担业务状态和协调压力,索引、清理、锁等待与时钟一致性都进入运维范围。

多引擎共享基础服务。 BPMN 与 CMMN 复用任务、变量、作业和身份关系服务,但保留各自语义。共享降低重复,也让配置器、schema 和生命周期之间的关系更难从单一模块看全。

适用场景与同类选择

Flowable 适合需要 BPMN 2.0 可视化流程、人工任务、长期等待、审计历史、定时器和 Java/Spring 深度嵌入的系统,例如审批、订单履约、客户服务和跨系统编排。若流程主要由开发者以代码定义、没有 BPMN 建模与人工任务需求,代码优先的持久执行框架可能更直接;若只是简单状态枚举,完整流程引擎会引入过多概念和表。

方案建模与运行形态更适合的侧重点采用时应核对
FlowableJava 可嵌入或 REST;BPMN、CMMN、DMN 与共享服务Spring 应用中的流程、案例、决策和人工任务统一引擎Flowable 8 基础栈、数据库容量、模型发布治理
Camunda 7Java 流程引擎与 BPMN/DMN 生态已有 Camunda 7 模型、插件和运维体系产品生命周期、版本支持与后续迁移路线
Temporal代码定义的持久工作流,不以 BPMN 图为核心开发者主导的分布式长事务、重试和补偿与业务建模人员的协作方式、SDK 与服务端运维

真正有区分度的问题是:谁维护流程,状态要保留多久,是否需要人工任务,业务代码能否接受引擎侵入,数据库或独立服务由谁运维,以及升级是否允许改变 Spring/Jackson 基线。

构建与调试问题

下面的排障入口来自固定提交的静态源码阅读和 Flowable 官方配置文档;这些内容给出检查顺序与可观察状态,不代表本次任务已经在目标仓库运行验证。

启动时报数据库表不存在

先确认 schema update 配置与环境目标,参见 Flowable 数据库配置文档。开发环境可让引擎创建表;生产环境应使用对应数据库和版本的 SQL 脚本。验证时不要只看一张 ACT_RU_* 表,还要检查被启用的 common、identity、task、variable、job 和 history schema。

Spring Boot 启动了但流程没有自动部署

检查 FlowableProperties 中的 process-definition-location-prefix、文件后缀、check-process-definitions 和 deployment mode。自动配置先发现 Resource,再由 SpringProcessEngineConfiguration.start() 调用部署策略。日志中的 “No deployment resources were found for autodeployment” 表明没有发现资源,不等同于引擎创建失败。

完成任务后流程没有继续

先确认任务属于 BPMN 还是 CMMN;再检查 TaskHelper.completeTask() 是否完成任务、complete listener 是否传播了 BPMN Error、execution 当前节点是否仍为 User Task。普通路径会计划 TriggerExecutionOperation

异步节点长期不执行

AcquireAsyncJobsDueRunnable 的状态顺序排查:ACT_RU_JOB 是否有记录,due date 是否到期,lock owner 是否长期不释放,执行器是否 active,线程池是否满,作业是否已转到 timer、suspended 或 dead letter 表。集群中偶发乐观锁日志可能只是正常竞争,持续锁超时则要检查节点存活、数据库时钟和锁时长。

Service Task 重复调用外部系统

Flowable 的作业重试保证流程继续尝试,不自动保证外部副作用只发生一次。Delegate 调用支付、库存、通知等系统时应传递业务幂等键,并把“外部成功但本地事务回滚”的情况纳入对账或补偿设计。

升级到 Flowable 8 后依赖冲突

先核对 Flowable 8.0.0 Release 所说明的 Spring Boot 4、Spring Framework 7、Jackson 3 和 JUnit 5 基础栈。若现有应用仍固定在 Spring Boot 3,不应只替换 Flowable 版本号。Jackson 2 兼容层也不代表所有第三方扩展都已适配 Jackson 3。

后续阅读路径

准备扩展业务节点时,从 JavaDelegate、Service Task 解析处理器和 ActivityBehaviorFactory 开始;排查同步流程,从 Service API 进入 Command,再看 Agenda 和 execution;排查异步失败,则按 job、timer job、dead letter 的状态迁移阅读 AcquireAsyncJobsDueRunnableExecuteAsyncRunnableJobRetryCmd

若要理解 Flowable 全套平台,下一步再分别进入 CMMN 的 plan item 生命周期、DMN 的 decision execution、Event Registry 的入站与出站通道,以及这些引擎如何通过 EngineConfigurator 挂到 App Engine。阅读顺序仍应以一次真实业务链为主,不必按 90 个模块逐个展开。

阅读 Flowable 时可以沿四层定位问题:部署阶段把标准模型编译成带行为的内存定义;运行阶段用 Command 组织事务边界,用 Agenda 推进执行树;数据库保存等待位置,作业服务负责恢复异步工作。这样可以把复杂模块映射回一次具体业务链。

参考资料

文章结论绑定 source commit;动态信息以核对日期为准。