首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

Compiere 工作流引擎架構深度解析:核心類職責、流程啟動機制與擴展設計模式

     編輯:關於SqlServer

前言:ERP 核心業務流程的自動化大腦

Compiere (現 ADempiere/iDempiere 系列祖先) 採用全流程工作流驅動架構:所有業務單據 (訂單、發票、出貨、付款...) 皆由工作流引擎協調狀態流轉、任務分派、規則驗證。本文基於核心類圖與序列圖,深度解析其引擎設計精髓。

核心類職責矩陣

類別名稱核心職責關鍵屬性/方法設計模式角色
MWorkflow工作流定義容器:版本、啟用狀態、所屬模組AD_Workflow_ID, getProcess(), start()Facade / Aggregate Root
MWFProcess流程圖定義:節點集合、轉移規則、起始/結束節點AD_WF_Process_ID, startWork(), getNodes()Process Definition
MWFNode流程節點:類型(開始/結束/任務/決策/子流程)、XY 座標、關聯活動AD_WF_Node_ID, getActivity(), getNextConditions()Node / State
MWFActivity工作項/任務實體:執行邏輯、指派規則、表單/程序/子流程AD_WF_Activity_ID, run(), performWork()Command / Task
MWFNextCondition轉移條件:SQL 片段/規則引擎表達式、優先序、預設路徑Condition, SeqNo, evaluate()Guard Condition
StateEngine狀態機核心:單據狀態定義、合法轉移矩陣、轉移動作攔截getNextState(), transition(), validate()State Machine
DocAction (Interface)單據行為契約:prepare(), complete(), approve(), void(), close()所有單據 Model 實作此介面Strategy / Command
WMFAccess工作流存取控制:角色/用戶/組織對節點/活動的權限矩陣canAccess(), getAssignedUsers()Authorization
WorkflowValidate部署時驗證:節點連通性、無孤立節點、條件完整性、循環檢測validate(), getErrors()Validator

典型工作流啟動與執行序列圖解析

啟動入口:ProcessCtl.startWorkflow(AD_Workflow_ID)

// ProcessCtl.java
public static void startWorkflow(int AD_Workflow_ID, PO doc, Trx trx) {
    MWorkflow workflow = new MWorkflow(Env.getCtx(), AD_Workflow_ID, trx);
    workflow.start(doc, trx);  // 傳入單據物件 (實作 DocAction)
}

MWorkflow.start() → MWFProcess.startWork()

// MWorkflow.java
public void start(PO doc, Trx trx) {
    MWFProcess process = getProcess();  // 取得關聯流程定義
    process.startWork(this, doc, trx);  // 委派給流程實例
}

MWFProcess.startWork() — 核心調度邏輯

// MWFProcess.java
public void startWork(MWorkflow workflow, PO doc, Trx trx) {
    // 1. 取得起始節點 (NodeType='S')
    MWFNode startNode = getStartNode();
    
    // 2. 取得起始節點關聯的活動
    MWFActivity startActivity = startNode.getActivity();
    
    // 3. 執行活動 — 這是同步阻塞呼叫
    startActivity.run(workflow, doc, trx);
}

MWFActivity.run() → performWork() — 實際業務執行點

// MWFActivity.java
public void run(MWorkflow workflow, PO doc, Trx trx) {
    // 1. 執行前驗證 (權限、前置條件)
    if (!validate(workflow, doc, trx)) return;
    
    // 2. 核心業務邏輯 — 由具體活動類型決定
    performWork(workflow, doc, trx);
    
    // 3. 執行後處理:評估下一條件、推進流程
    completeWork(workflow, doc, trx);
}

protected void performWork(MWorkflow workflow, PO doc, Trx trx) {
    switch (getWFAction()) {
        case 'F':  // Form 表單 - 等待用戶互動
            createWorkItem(workflow, doc, trx);
            break;
        case 'P':  // Process 程序 - 自動執行
            executeProcess(workflow, doc, trx);
            break;
        case 'S':  // Subflow 子流程
            startSubWorkflow(workflow, doc, trx);
            break;
        case 'D':  // Document 動作 - 委派單據 DocAction
            docAction(doc, trx);
            break;
    }
}

completeWork() — 流程推進邏輯

private void completeWork(MWorkflow workflow, PO doc, Trx trx) {
    // 1. 取得所有輸出轉移條件
    List conditions = getNextConditions();
    
    // 2. 按優先序評估,第一個滿足者勝出
    for (MWFNextCondition cond : conditions) {
        if (cond.evaluate(workflow, doc, trx)) {
            MWFNode nextNode = cond.getNextNode();
            MWFActivity nextActivity = nextNode.getActivity();
            
            // 3. 遞迴執行下一活動 (同步鏈)
            nextActivity.run(workflow, doc, trx);
            return;
        }
    }
    
    // 3. 無條件滿足 → 流程結束或錯誤
    if (conditions.isEmpty()) 
        workflow.setStatus("CO");  // Completed
    else
        workflow.setStatus("ER");  // Error - no path matched
}

關鍵設計模式與架構決策

1. 單據即狀態機:DocAction 介面統一行為

所有業務單據 (Order, Invoice, Shipment, Payment...) 實作 DocAction:

public interface DocAction {
    boolean prepare();
    boolean complete();
    boolean approve();
    boolean voidIt();
    boolean close();
    String getDocStatus();
    // ...
}

// Order.java
public class MOrder extends PO implements DocAction {
    public boolean complete() {
        // 1. 驗證明細、庫存、價格
        // 2. 更新狀態 CO (Completed)
        // 3. 觸發後續:建立出貨、發票、會計憑證
        return true;
    }
}

優勢:工作流引擎無需知曉具體單據類型,統一呼叫 docAction() 實現多態。

2. 活動類型策略模式:F/P/S/D 四大執行策略

類型代碼執行語義典型場景
表單任務F建立工作項 → 等待用戶操作 → 用戶完成 → 推進審批、確認、輸入
自動程序P同步執行 Java 類/預存程序 → 立即推進計算價格、生成單號、發送郵件
子流程S啟動另一工作流定義 → 等待子流程結束 → 推進訂單流程包含信用檢核子流程
單據動作D呼叫單據 DocAction 方法 → 依結果推進完成訂單、核准發票

3. 狀態引擎分離:StateEngine 獨立於流程圖

  • 流程圖 (MWFProcess) 定義節點與轉移拓撲
  • 狀態引擎 (StateEngine) 定義單據合法狀態與轉移規則
  • 雙重保障:流程圖控制執行路徑,狀態引擎控制資料合法性

4. 存取控制整合:WMFAccess 細粒度權限

// 節點層級權限
boolean canAccess(int AD_Role_ID, int AD_User_ID, int AD_Org_ID) {
    // 1. 檢查角色/用戶是否在節點指派清單
    // 2. 檢查組織存取權
    // 3. 檢查單據層級敏感度
}

擴展與客製化最佳實踐

場景一:新增自定義活動類型 (如呼叫外部 REST API)

  1. 擴展 MWFActivity 新增 WFAction = 'R' (REST)
  2. 實作 performWork() 中 case 'R': callRestApi(); break;
  3. 資料庫 AD_WF_Activity 表新增 REST_Endpoint, REST_Payload_Template 欄位
  4. 工作流設計器 UI 增加「REST 活動」拖拉元件

場景二:動態條件表達式 (Groovy/JS/SpEL)

// MWFNextCondition 增加 Expression 欄位
// 評估引擎整合 GroovyShell
public boolean evaluate(MWorkflow wf, PO doc, Trx trx) {
    Binding binding = new Binding();
    binding.setVariable("doc", doc);
    binding.setVariable("wf", wf);
    binding.setVariable("ctx", Env.getCtx());
    GroovyShell shell = new GroovyShell(binding);
    return (Boolean) shell.evaluate(getExpression());
}

// 使用範例:表達式 = "doc.getTotalLines() > 100 && doc.getC_BPartner_ID() == 1000045"

場景三:非同步/長時間活動 (外部系統整合)

  • 活動執行時狀態設為 WAITING_EXTERNAL
  • 外部系統回呼 WorkflowCallback.complete(activityInstanceId, result)
  • 引擎恢復 completeWork() 推進流程
  • 需補償機制:超時未回呼 → 升級/重試/人工介入

效能與擴展性考量

挑戰Compiere 方案現代化改良建議
同步阻塞鏈活動同步遞迴執行,長鏈導致交易超時引入事件總線,活動發事件 → 背景 Worker 處理 → 回呼推進
資料庫鎖爭用工作流實例、工作項、單據同一交易樂觀鎖 + 重試、關鍵路徑拆分微服務
流程定義版本管理MWorkflow 版本欄位,運行中實例綁定舊版GitOps 風格:流程定義即代碼,CI/CD 部署、藍綠發布
監控與可觀測性僅資料庫狀態欄位整合 OpenTelemetry:TraceID 貫穿工作流實例、活動、單據

結語

Compiere 工作流引擎以元資料驅動、介面契約解耦、狀態機雙重保障為核心設計哲學,實現了 ERP 複雜業務流程的標準化自動化。其類結構清晰展現了領域驅動設計 (DDD)的雛形:聚合根 (MWorkflow)、實體 (MWFProcess/Node/Activity)、值物件 (MWFNextCondition)、領域服務 (StateEngine/WorkflowValidate)、介面契約 (DocAction)。理解這套架構,不僅能駕馭 Compiere 系列產品二次開發,更能啟發現代微服務編排引擎、低代碼流程平台的設計思維。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved