【核心概念】iDempiere 技術架構:OSGI + ZK + PO 框架深度解析

iDempiere 技術架構:OSGI + ZK + PO 框架深度解析

iDempiere 採用 Java 企業級技術棧打造,核心架構包含 OSGI 模組化框架、ZK Web UI、PO 持久層與 Jetty 伺服器。本文將深入剖析這些技術如何協同運作,幫助開發者理解 iDempiere 的內部設計,為後續的客製開發打下基礎。

一、整體架構概覽

iDempiere 採用經典的多層式架構,各層職責分明:

層級 技術 職責
展示層 ZK Framework Web UI 呈現、使用者互動
業務邏輯層 Java + Callout + ModelValidator 商業規則、流程控制
資料存取層 PO Framework 物件關聯映射、資料持久化
基礎設施層 OSGI + Jetty 模組管理、Web 服務

架構流程圖

┌─────────────────────────────────────────┐
│           展示層 (ZK Framework)          │
│    GridController → GridTab → GridField │
└─────────────────┬───────────────────────┘
                  ▼
┌─────────────────────────────────────────┐
│         業務邏輯層 (Business Logic)      │
│   Callout ← Model Validator ← Process   │
└─────────────────┬───────────────────────┘
                  ▼
┌─────────────────────────────────────────┐
│          資料存取層 (PO Framework)       │
│      MTable → PO → DB (PostgreSQL)      │
└─────────────────┬───────────────────────┘
                  ▼
┌─────────────────────────────────────────┐
│        基礎設施層 (OSGI + Jetty)         │
│   Bundle 管理 → 熱部署 → Web Server     │
└─────────────────────────────────────────┘

二、OSGI 模組化設計

iDempiere 從 ADempiere 分支後最大的改變就是導入 OSGI (Open Service Gateway initiative) 架構,實現真正的模組化設計。

什麼是 Bundle?

在 OSGI 中,每個功能模組稱為 Bundle,它是一個包含程式碼和資源的 JAR 檔案,並透過 MANIFEST.MF 檔案描述其相依性。

核心 Bundle 結構

plugins/
├── org.adempiere.base_12.0.0.jar        # 核心基礎
├── org.adempiere.server_12.0.0.jar      # 伺服器應用
├── org.adempiere.ui.zk_12.0.0.jar       # ZK UI 模組
├── org.eclipse.equinox.launcher_1.x.jar # OSGI 啟動器
└── [自訂外掛].jar                        # 你的外掛

MANIFEST.MF 關鍵設定

Bundle-Name: iDempiere Server
Bundle-SymbolicName: org.adempiere.server;singleton:=true
Bundle-Version: 12.0.0.qualifier
Require-Bundle: org.adempiere.base;bundle-version="12.0.0"
Import-Package: javax.servlet;version="4.0.0"
Bundle-Activator: org.adempiere.server.AdempiereServerActivator

Require-Bundle vs Import-Package

方式 特性 適用場景
Require-Bundle 依賴整個 Bundle 需要特定 Bundle 的多個 Package
Import-Package 只依賴特定 Package 鬆耦合,Package 可由任何 Bundle 提供

建議:優先使用 Import-Package,保持模組間的鬆耦合。

三、啟動流程解析

iDempiere 的啟動由 idempiere-server.sh 觸發:

$JAVA -jar plugins/org.eclipse.equinox.launcher_1.*.jar \
  -application org.adempiere.server.application

啟動順序

  1. Equinox Launcher 啟動 OSGI 容器
  2. 載入所有 plugins/ 目錄下的 Bundle
  3. 呼叫 AdempiereServerActivatorstart() 方法
  4. 初始化資料庫連線、載入 Application Dictionary
  5. 啟動 Jetty Web Server(預設 port 8080)
  6. 等待使用者連線

四、ZK 前端框架

ZK Framework 是 iDempiere 的前端技術,它是一個 Server-centric 的 Java Web 框架,讓開發者用 Java 撰寫 UI 邏輯。

核心元件

元件 職責
GridController MVC Controller,處理使用者操作
GridTab 對應一個 Tab,管理資料列
GridField 對應一個欄位,處理顯示與編輯
GridTable 資料模型,與 PO 層互動

MVC 流程

使用者點擊 → GridController 處理事件
         → 呼叫 GridTab 的方法
         → GridTab 透過 PO 存取資料庫
         → 更新 UI 顯示

五、PO 持久層框架

PO (Persistent Object) 是 iDempiere 的 ORM 框架,負責 Java 物件與資料庫表的映射。

PO 類別結構

PO (抽象基類)
 └── X_TableName (自動生成,對應欄位)
      └── MTableName (業務邏輯擴充)

例如訂單表 C_Order

  • X_C_Order:自動生成,包含所有欄位的 getter/setter
  • MOrder:擴充業務邏輯(如 completeIt、voidIt)

PO 核心方法

// 建立新記錄
MOrder order = new MOrder(ctx, 0, trxName);
order.setC_BPartner_ID(1000000);
order.saveEx();

// 查詢現有記錄
MOrder order = new MOrder(ctx, 1000001, trxName);

// 刪除記錄
order.deleteEx(true);

Cache 機制

iDempiere 大量使用 CCache 快取常用資料,減少資料庫查詢:

private static CCache<Integer, MProduct> s_cache 
    = new CCache<>("M_Product", 100);

六、Jetty Web Server

iDempiere 內嵌 Jetty 作為 Web 伺服器,設定檔位於 jettyhome/etc/

設定檔 用途
jetty.xml 主要伺服器設定
jetty-http.xml HTTP 連接設定(port 8080)
jetty-https.xml HTTPS 設定(port 8443)
jetty-ssl-context.xml SSL 憑證設定

七、如何追蹤程式碼

開發時常用的追蹤技巧:

  1. 從 UI 出發:System Admin 角色可看到 Field 對應的 Process
  2. 找 Model:表名 C_Order → 類別 MOrder
  3. 找 Process:AD_Process
  4. OSGI Console:telnet localhost 12612 可管理 Bundle

常見問題 FAQ

Q1: OSGI 和傳統 Java Web 應用有什麼不同?

傳統應用所有程式碼打包成一個 WAR,OSGI 則將功能拆成多個 Bundle,可獨立更新、熱部署,不需重啟整個系統。

Q2: 為什麼要用 ZK 而不是 Vue/React?

ZK 是 Server-centric 架構,UI 邏輯用 Java 撰寫,與後端無縫整合。iDempiere 歷史悠久,ZK 是當時成熟的選擇。社群也有人嘗試開發 REST API + 前端分離方案。

Q3: PO 和 JPA/Hibernate 有什麼不同?

PO 是 iDempiere 自己的 ORM 框架,與 Application Dictionary 深度整合,可透過 UI 定義欄位後自動生成 Model。JPA 則是獨立的標準 ORM。

Q4: 如何開發自己的 Plugin?

建立 Eclipse Plugin Project,設定 MANIFEST.MF 相依性,將 2Pack 匯出檔放入 META-INF,打包成 JAR 後透過 Felix Console 安裝。

Q5: OSGI Console 怎麼用?

執行 telnet localhost 12612,常用指令:ss(列出 Bundle)、start/stop [id](啟動/停止 Bundle)、install file:xxx.jar(安裝新 Bundle)。

留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *