jBPM (Java Business Process Management) 是一套成熟的開源工作流引擎,支援 BPMN 2.0 標準。雖然早期版本 (如文中提及的 3.2) 使用 jPDL 自有格式,但核心概念——流程定義、部署、實例化、任務節點、流轉——至今仍是工作流開發的基石。本文將以現代視角重構經典「費用報銷審批」範例,涵蓋流程建模、資料庫整合與 API 操作。
流程邏輯:員工發起申請 → 部門主管審批 → 總經理審批 → 結束。對應 BPMN 元素:Start Event → User Task (部門主管) → User Task (總經理) → End Event。
現代 jBPM (7.x/8.x) 整合於 KIE Workbench 或 VS Code 外掛,支援圖形化拖拉建模。產出的 `reimbursement.bpmn2` 核心片段如下:
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:bpmn2="https://www.omg.org/spec/BPMN/20100524/MODEL" ...>
<bpmn2:process id="reimbursement" isExecutable="true">
<bpmn2:startEvent id="StartEvent_1"></bpmn2:startEvent>
<bpmn2:sequenceFlow id="Flow_1" sourceRef="StartEvent_1" targetRef="Task_Manager" />
<bpmn2:userTask id="Task_Manager" name="部門主管審批">
<bpmn2:extensionElements>
<tns:potentialOwner><tns:resourceAssignmentExpression><tns:formalExpression>manager</tns:formalExpression></tns:resourceAssignmentExpression></tns:potentialOwner>
</bpmn2:extensionElements>
</bpmn2:userTask>
<bpmn2:sequenceFlow id="Flow_2" sourceRef="Task_Manager" targetRef="Task_CEO" />
<bpmn2:userTask id="Task_CEO" name="總經理審批">
<bpmn2:extensionElements>
<tns:potentialOwner><tns:resourceAssignmentExpression><tns:formalExpression>ceo</tns:formalExpression></tns:resourceAssignmentExpression></tns:potentialOwner>
</bpmn2:extensionElements>
</bpmn2:userTask>
<bpmn2:sequenceFlow id="Flow_3" sourceRef="Task_CEO" targetRef="EndEvent_1" />
<bpmn2:endEvent id="EndEvent_1"></bpmn2:endEvent>
</bpmn2:process>
</bpmn2:definitions>
使用 Spring Boot 整合 jBPM,`pom.xml` 引入 `jbpm-spring-boot-starter`。資料庫結構由 Hibernate 自動建立 (配置 `spring.jpa.hibernate.ddl-auto=update`),無需手動執行 `createSchema()`。
@Autowired
private KieServices kieServices;
public void deployProcess() {
KieFileSystem kfs = kieServices.newKieFileSystem();
kfs.write(ResourceFactory.newClassPathResource("processes/reimbursement.bpmn2"));
KieBuilder kb = kieServices.newKieBuilder(kfs).buildAll();
if (kb.getResults().hasMessages(Message.Level.ERROR)) {
throw new RuntimeException("流程部署失敗: " + kb.getResults());
}
KieContainer kc = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
// 後續透過 kc 取得 KieSession
}
流程實例 (`ProcessInstance`) 是流程定義的執行副本。業務物件 (如 `ReimbursementOrder`) 透過流程變數關聯:
@Transactional
public Long startReimbursement(ReimbursementOrder order) {
KieSession ksession = kieContainer.newKieSession();
try {
// 儲存業務單據
order = orderRepository.save(order);
// 啟動流程並綁定變數
Map<String, Object> params = new HashMap<>();
params.put("orderId", order.getId());
params.put("applicant", order.getApplicant());
ProcessInstance pi = ksession.startProcess("reimbursement", params);
return pi.getId(); // 回傳流程實例 ID
} finally {
ksession.dispose();
}
}
使用者透過 `TaskService` 領取、完成任務,引擎自動推進至下一節點:
@Autowired
private TaskService taskService;
// 部門主管完成審批
public void approveByManager(String taskId, boolean approved, String comment) {
Map<String, Object> result = new HashMap<>();
result.put("approved", approved);
result.put("comment", comment);
taskService.complete(taskId, result);
}