本文延續前兩篇 Geronimo 實戰文章,示範如何開發一個獨立的 Swing 「胖客戶端」,透過 RMI/JNDI 連線至 Geronimo 應用伺服器內部的 EJB 層,操作電話簿資料庫。整體部署架構如下:

圖 1:UML 部署圖 — Swing 客戶端透過 EJB 連接埠 (預設 4201) 與 Geronimo 叢集通訊
關鍵限制: Geronimo 預設僅允許本機回環位址 (127.0.0.1) 連線 EJB 連接埠。跨機器存取需修改伺服器設定檔並重新編譯 (詳見文末「配置 Geronimo 的 EJB 連接埠」)。
專案需將以下 JAR 放入 Classpath (Maven 專案可透過 `project.xml` 依賴管理自動解析):
核心機制: Geronimo 使用 CGLib 在客戶端動態生成 Remote Proxy 類別,`InitialContext.lookup()` 回傳的即為此類實例。`geronimo-spec-j2ee.jar` 提供介面定義,`openejb-core.jar` 則處理通訊協定細節。
public void connect() {
String host = getHostName(); // 例: localhost
String port = getPort(); // 例: 4201
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.openejb.client.RemoteInitialContextFactory"); // 關鍵: Geronimo 專用 Factory
props.setProperty("java.naming.provider.url", host + ":" + port);
props.setProperty("java.naming.security.principal", "username");
props.setProperty("java.naming.security.credentials", "passwd");
try {
Context ic = new InitialContext(props);
// JNDI 查詢 + PortableRemoteObject.narrow() 取得型別安全的 Home 介面
PhoneBookSessionHome home = (PhoneBookSessionHome) PortableRemoteObject.narrow(
ic.lookup(PhoneBookSessionHome.JNDI_NAME),
PhoneBookSessionHome.class
);
phoneBookSession = home.create(); // 建立 Stateless Session Bean 實例
} catch (Throwable ex) {
ex.printStackTrace();
} finally {
// 關閉 Context 釋放資源
}
}
此範例展示標準 J2EE 客戶端連線模式,無 Geronimo 專有 API 洩漏,移植性極佳。

圖 2:UML 類別圖 — 採用 Singleton `Application` 控制器統籌 EJB 操作,UI 元件透過 Observer 模式 (`DataChangeEvent`, `PhoneBookSelectionListener`) 回應資料變更。
cd PhoneBook && mvn
cd PhoneBookClient && mvn
成功後在 `target/` 產出 `phonebook-client-uber.jar` (包含所有相依庫的 Fat JAR)。
java -jar phonebook-client-uber.jar

圖 3:應用程式主介面 — 選單列提供連線設定,左側聯絡人列表,右側編輯表單。
操作流程:`File > Connect` 連線 (預設 localhost:4201) → 編輯欄位輸入姓名/號碼 → `Save` 新增/修改 → 列表選取項目 → `Delete` 刪除。
編輯 `openejb/modules/assembly/src/plan/j2ee-server-plan.xml` 中的 `EJBNetworkService` GBean 定義:
<gbean name="EJBNetworkService" class="org.openejb.server.StandardServiceStackGBean">
<attribute name="port">4201</attribute>
<attribute name="address">0.0.0.0</attribute> <!-- 改為 0.0.0.0 監聽所有介面 -->
<attribute name="allowHosts">192.168.10.{5,6,7}, 192.168.255.255</attribute> <!-- 允許的客戶端 IP 規則 -->
...
</gbean>
allowHosts 支援模式:
修改完成後需重新編譯 Geronimo 並重新部署。詳細正則規則請參考原始碼 `ServiceAccessController.java`。
本文完整示範了從零構建連接 Geronimo EJB 的 Swing 胖客戶端:標準 JNDI 連線、Maven 多模組建置、關注點分離的 UI 架構、以及伺服器端網路存取控制配置。遵循此模式,你可快速開發出連接企業級後端的豐富桌面應用。