EJB 規範定義了標準的遠程調用協議 RMI-IIOP,但允許客戶端以兩種截然不同的 API 風格接入:標準的 javax.naming + javax.rmi (RMI-IIOP 風格) 與標準的 org.omg.CORBA + org.omg.CosNaming (CORBA 風格)。本文通過完整的 HelloWorld 實例,對比展示兩種模式的代碼結構、關鍵 API 及事務控制差異。
這是最常見、最符合 J2EE 規範的寫法,適用於純 Java 客戶端調用任意兼容 EJB 容器。
package com.wiley.compBooks.roman.corba.helloworld;
import javax.ejb.*;
import javax.naming.*;
import javax.rmi.*;
import java.util.Properties;
import javax.transaction.UserTransaction;
/**
* 調用無狀態 Session Bean 的標準 RMI-IIOP 客戶端示例
*/
public class RMIClient {
public static void main(String[] args) {
try {
// 1. 獲取 JNDI 初始化屬性
Properties props = System.getProperties();
// 2. 創建初始上下文
Context ctx = new InitialContext(props);
// 3. 查找 Home 接口並進行 narrow 縮窄轉換
HelloHome home = (HelloHome)
PortableRemoteObject.narrow(ctx.lookup("HelloHome"), HelloHome.class);
// 4. 查找 JTA UserTransaction 接口
UserTransaction userTran = (UserTransaction)
ctx.lookup("javax.transaction.UserTransaction");
// 5. 開啟事務
userTran.begin();
// 6. 創建 EJB 對象並調用業務方法
Hello hello = home.create();
System.out.println(hello.hello());
// 7. 移除 EJB 對象
hello.remove();
// 8. 提交事務
userTran.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
}
關鍵點解析:
PortableRemoteObject.narrow():替代 Java 強制轉型,確保跨 ORB 環境下的類型安全。javax.transaction.UserTransaction:標準 JTA 客戶端事務 API,容器無關。"HelloHome" 為邏輯名,部署時映射到具體容器命名空間。當 EJB 部署在基於 CORBA 架構的容器(如早期 WebLogic, Inprise Application Server)時,可直接使用 CORBA API 進行更底層的控制。
package com.wiley.compBooks.roman.corba.helloworld;
import java.util.*;
import org.omg.CosNaming.*;
import org.omg.CosTransactions.*;
import org.omg.CORBA.ORB;
public class CORBAClient {
public static void main(String[] args) throws Exception {
// 1. 初始化 ORB(此處使用廠商專有方式獲取)
ORB orb = com.inprise.ejb.Global.orb();
// 2. 獲取命名上下文
NamingContext context = NamingContextHelper.narrow(
orb.resolve_initial_references("NameService"));
// 3. 通過 COS Naming 查找 Home 對象
NameComponent[] names = { new NameComponent("HelloHome", "") };
HelloHome helloHome = HelloHomeHelper.narrow(context.resolve(names));
// 4. 獲取 OTS (Object Transaction Service) Current 接口控制事務
Current currentTX = CurrentHelper.narrow(
orb.resolve_initial_references("TransactionCurrent"));
// 5. 開啟事務
currentTX.begin();
// 6. 創建 EJB 對象並調用業務方法
Hello hello = helloHome.create();
System.out.println(hello.hello());
// 7. 移除 EJB 對象
hello.remove();
// 8. 提交事務 (true 表示報告啟發式決策)
currentTX.commit(true);
}
}
關鍵差異對比:
| 維度 | RMI-IIOP 客戶端 | CORBA 客戶端 | |
|---|---|---|---|
| 命名服務 | JNDI (InitialContext) | COS Naming (NamingContext) | |
| 對象縮窄 | PortableRemoteObject.narrow() | XXXHelper.narrow() (IDL 生成) | |
| 事務控制 | JTA UserTransaction | OTS Current | |
| ORB 管理 | 隱式 (由 RMI 運行時管理) | 顯式 (ORB.init() 或廠商 API) | |
| 可移植性 | 高 (標準 J2EE) | 低 (依賴容器 CORBA 實現) | |
rmic -iiop,CORBA 使用 idlj 處理 IDL 文件。HelloHome, Hello 等接口類、Stub 類及容器客戶端 JAR 包。jndi.properties 指定 java.naming.factory.initial 及 provider.url (IIOP 端點)。RMI-IIOP 風格是構建可移植 J2EE 應用的首選;CORBA 風格則適用於需要深度整合現有 CORBA 資產、或利用容器特有 CORBA 服務(如高級負載均衡、特定攔截器)的場景。理解雙模式代碼結構,有助於在遷移、整合項目中做出正確的技術選型。