Java IDL技術在Java平臺上添加了CORBA(Common Object Request Broker Architecture)功能,提供了基于標準的互操作能力和連接性。Java IDL技術使得分布式的Java Web應用能夠通過使用工業(yè)標準的IDL和IIOP(Internet Inter-ORB Protocol)來透明地調用遠程網絡服務的操作。運行時組件(Runtime Components)包括了一個用于分布式計算且使用IIOP通信的Java ORB.
可移植對象適配器(Portable Object Adapter,POA)
CORBA對象的負責分隔服務器端遠程調用句柄
(handler)到遠程對象和它的服務者(servant)。對象由遠程調用所暴露,而服務者包含實際處理這些請求的方法。每個對象都可以選擇服務者為
靜態(tài)的(一次)或動態(tài)的(每個遠程調用),在這兩種情況下,都允許調用轉移到另一臺服務器。
在服務器端,POA形成了類似樹狀的結構,每個POA都負責一到多個服務的對象。樹的分支可以是獨立活動的、或鈍化的,服務者調用有不同的代碼和不同的請求處理策略。
API規(guī)范
* org.omg.CORBA 包 - 提供了OMG CORBA APIs到Java編程語言的映射
* org.omg.CosNaming 包 - 為Java IDL提供命名服務
* org.omg.PortableServer 包 - 為建立服務器端的可移植的、跨越多ORB的應用程序提供類和接口
* org.omg.PortableInterceptor 包 - 提供了注冊ORB鉤子的機制,此鉤子通過ORB服務能截取正常的ORB執(zhí)行流
* org.omg.DynamicAny 包 - 提供了使得任何值都能被動態(tài)解釋(或遍歷)和通過DynAny對象構造出來的類和接口
* org.omg.CORBA.ORB - 為CORBA ORB功能的API
分布式對象之間的關系有兩方面:客戶端和服務器。
服務器提供遠程接口,客戶端調用遠程接口。
在客戶端,應用程序包括遠程對象的引用。該對象引用有stub方法,它是獨立的遠程方法。stub方法實際連接到ORB,因此調用它實際上轉發(fā)調用到服務器。
在服務器端,ORB使用skeleton代碼翻譯遠程調用為本地對象的方法調用。Skeleton把調用轉換成指定實現的格式,并在方法中調用。當方法返回時,Skeleton代碼轉換方法調用的結果或錯誤,經ORB送回客戶端。
Java IDL開發(fā)過程
1)定義遠程接口
使用IDL語言為遠程對象定義接口。
【Billing.idl源代碼】如下:
- // 聲明CORBA IDL模塊
- module BillingApp{
- // 聲明接口
- interface Billing{
- string successBilling();
- oneway void shutdown();
- };
- };
2)編譯遠程接口
使用idlj編譯器生成Java語言的stub和skeleton源文件。
idlj編譯器缺省只生成客戶端的binding代碼。如果同時需要客戶端的bindings和服務器端的skeletons,必須加上-fall選項。
使用POA(Portable Object Adaptor)的優(yōu)點:
· 允許編程者構建對象在不同ORB產品之間的可移植實現
· 支持帶持久化標識的對象
· 對對象的透明活動提供支持
· 允許單個servant支持多種對象同時標識
注意:確定jdk/bin目錄下有:idlj、java、javac、orbd
命令:
idlj -fall Billing.idl
在當前目錄下生成BillingApp目錄,包含如下六個文件:
· Billing.java ————> 此接口包含IDL接口的Java版本。它繼承自org.omg.CORBA.Object,提供標準的CORBA對象功能。
· BillingHelper.java ————> 此類提供輔助功能,Helper類負責讀寫數據類型到CORBA流,以及插入和提取數據類型。
· BillingHolder.java ————> This final class holds a public instance member of type Billing.
· BillingOperations.java ————> 此接口包含successBilling()和shutdown()方法。
·
BillingPOA.java ————>
此抽象類是基于流的服務器Skeleton,為服務器提供基本的CORBA功能。它繼承org.omg.PortableServer.Servant,
實現了InvokeHandler接口和BillingOperations接口。服務器類BillingServant繼承BillingPOA。
·
_BillingStub.java ————>
此類是客戶端stub,為客戶端提供CORBA功能。它繼承org.omg.CORBA.Object,提供標準CORBA對象功能。還擴展了
BillingOperations接口和org.omg.CORBA.portable.IDLEntity接口。
3)實現服務器端
一旦使用idlj編譯器后,就可以使用它產生的Skeleton裝配服務器應用程序了。另外要實現遠程接口方法,服務器代碼應包含啟動ORB和等待遠程客戶端調用的機制。
服務器端由兩個類組成,一個是servant,另一個是Server。
servant是BillingImpl類,是Billing IDL接口的實現,每個Billing實例均由BillingImpl實例實現。servant是BillingPOA的子類。
servant包含了IDL定義的所有方法,與通常的Java方法類似。
server類含服務器的main()方法,它:
· 創(chuàng)建和初始化ORB實例
· 獲得根POA的引用并激活POAManager
· 創(chuàng)建一個Servant實例(CORBA的Billing對象的實現)并通知ORB
· 獲得根命名上下文
· 在命名上下文用“Billing”名注冊新對象
· 等待客戶端調用此新對象
【BillingImpl.java源碼】:
- import org.omg.CORBA.ORB;
- import BillingApp.*;
- class BillingImpl extends BillingPOA{
- private ORB orb;
- public void setORB(ORB orb_val){
- this.orb = orb_val;
- }
- /**
- * 實現successBilling()方法
- */
- public String successBilling() {
- return "\nBilling success!!\n";
- }
- /**
- * 實現shutdown()方法
- */
- public void shutdown(){
- orb.shutdown(false);
- }
- }
【BillingServer.java源碼】:
- import org.omg.CORBA.ORB;
- import org.omg.CosNaming.NameComponent;
- import org.omg.CosNaming.NamingContextExt;
- import org.omg.CosNaming.NamingContextExtHelper;
- import org.omg.PortableServer.POA;
- import BillingApp.*;
- public class BillingServer {
- public static void main(String args[]){
- try{
- // 創(chuàng)建和初始化ORB
- ORB orb = ORB.init(args, null);
- // 獲得根POA的引用并激活POAManager
- POA rootpoa = (POA)orb.resolve_initial_references("RootPOA");
- rootpoa.the_POAManager().activate();
- // 創(chuàng)建servant并注冊到ORB
- BillingImpl billingImpl = new BillingImpl();
- billingImpl.setORB(orb);
- // 從servant獲得對象引用
- org.omg.CORBA.Object ref = rootpoa.servant_to_reference(billingImpl);
- Billing href = BillingHelper.narrow(ref);
- // 得到根命名上下文
- org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
- // 使用命名上下文,它是互操作命名服務規(guī)范的一部分
- NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
- // 在命名中綁定對象引用
- String name = "Billing";
- NameComponent path[] = ncRef.to_name(name);
- ncRef.rebind(path, href);
- System.out.println("BillingServer is ready and waiting...");
- // 等待客戶端調用
- orb.run();
- }catch(Exception e){
- System.err.println("ERROR:"+e);
- e.printStackTrace(System.out);
- }
- System.out.println("BillingServer Exiting ...");
- }
- }
4)實現客戶端
與第三步類似,可以使用idlj產生的stub作為客戶端應用程序的基礎??蛻舳舜a建立于stub之上,啟動ORB,使用服務器提供的命名服務查詢,獲得遠程對象的引用,調用其方法。
【BillingClient.java源碼】:
- import org.omg.CORBA.ORB;
- import org.omg.CosNaming.NamingContextExt;
- import org.omg.CosNaming.NamingContextExtHelper;
- import BillingApp.*;
- public class BillingClient {
- static Billing billingImpl;
- public static void main(String args[]){
- try{
- // 創(chuàng)建和初始化ORB
- ORB orb = ORB.init(args, null);
- System.out.println("ORB initialised");
- // 獲得根命名上下文
- org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
- // 使用NamingContextExt代替命名上下文,它是互操作命名服務的一部分
- NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
- // 在命名中解析對象引用
- String name = "Billing";
- billingImpl = BillingHelper.narrow(ncRef.resolve_str(name));
- System.out.println("Obtained a handle on server object: "+billingImpl);
- System.out.println(billingImpl.successBilling());
- billingImpl.shutdown();
- }catch(Exception e){
- System.out.println("ERROR: "+e);
- e.printStackTrace(System.out);
- }
- }
- }
5)啟動應用程序
要運行服務器和客戶端,必須先啟動命名服務,再啟動服務器,最后運行客戶端。
此例用到命名服務,它使得servant對象的操作對客戶端有效。服務器需要命名服務的對象引用,命名服務可以發(fā)布對象引用實現各種接口??蛻舳耸褂脤ο笠脕碚{用方法。
Java SE 1.4以上提供了兩種可選的命名服務:
· tnameserv
一種透明的命名服務
· orbd
包含自啟動服務、透明的命名服務、持久化命名服務和命名管理器的后臺處理進程。
本例使用orbd。
5.1)啟動orbd
注意:Solaris系統(tǒng)運行要求root權限并以1024端口開始進程。因此,對所有OS,可以選用大于或等于1024的端口以實現統(tǒng)一。
-ORBInitialPort選項用于指定端口(非缺省狀態(tài))。
例如:假定使用1050端口的Java ORB Daemon(orbd),命令如下:
start orbd -ORBInitialPort 1050 -ORBInitialHost localhost
5.2)開始Billing服務器
start java BillingServer -ORBInitialPort 1050 -ORBInitialHost localhost
注:如在同一臺主機上運行,可省略-ORBInitialHost localhost
5.3)運行客戶端應用程序
java BillingClient -ORBInitialPort 1050 -ORBInitialHost localhost