BCB帶有多個向導(Wizards)以簡化CORBA服務器的開發過程。以下幾步描述了如何用BCB建立一個CORBA服務器。
定義對象界面
使用CORBA server wizard建立一個包含起始時初始化BOA和ORBCORBA代碼的服務器應用程序
編譯包含界面定義的IDL文件,得到框架及存根。
用CORBA object wizard定義(並實現)類的實現。
完成4建立的類實現CORBA 對象
必要時,修改CORBA界面並將修改加進類實現中。
另外,可以選擇將IDL文件注冊加入界面庫和對象激活守護進程。
--------------------------------------------------------------------------------
1-1 定義對象界面
參見OVERVIEW同主題部分。
--------------------------------------------------------------------------------
1-2 使用CORBA server wizard建立一個包含起始時初始化BOA和ORBCORBA代碼的服務器應用程序
要開始一個新的CORBA服務器工程,選擇File|New,再從對話框的Multitier頁選取題為CORBA Server的圖標。CORBA Server wizard讓你指定是生成控制台程序(console application)還是窗口應用程序(windows application)。
如果建立一個控制台應用程序,可以說明是否使用VCL類。如果不選,那麼所有生成的代碼可以移植到其它平台上。
另外,選擇應用程序類型時,還可以將任何已經存在的IDL文件加進工程中,或指定你想加進一個空白的IDL文件。服務器工程最後必須一個或多個IDL文件,該文件定義客戶用以與服務器通信的界面。
注意:如果在開始CORBA工程時沒有加入IDL文件,你始終可以選擇Project|Add to Project(對已經存在的IDL文件)或從New Items對話框的Multitier頁選擇CORBA IDL file(以定義新IDL文件)來加入。
當你選定服務器類型,單擊OK,CORBA Server wizard將新建一個指定類型的服務器工程,將CORBA庫加入工程文件,加入初始化ORB(對象請求代理)和BOA(基本對象配適器)的起始代碼。
自動生成的代碼定義兩個變量:orb和boa,你可以用它們與ORB和BOA通信。
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
CORBA::BOA_var boa = orb->BOA_init(argc, argv);
如果指定為控制台應用程序,還會看到下面這行:
boa->impl_is_ready();
這個調用使你的程序可以從BOA接收消息,正如Windows消息循環允許一個窗口應用程序從Windows收到消息。(而窗口型應用程序使用Windows消息循環處理CORBA消息)。
ORB和BOA的細節見VisiBroker文檔(可到inprise網站去下載)。
--------------------------------------------------------------------------------
1-3 編譯包含界面定義的IDL文件,得到框架及存根。
一旦你將描述CORBA界面的IDL文件加入到CORBA工程中,你就已經准備好生成存根和框架類了,這兩個類將管理服務器與客戶應用程序的通信。
生成存根和框架類,很簡單,編譯一下IDL文件就得到了。當IDL文件顯示在代碼編輯器和工程管理器中時選擇Project|Compile Unit,或在project manager的IDL文件上單擊鼠標右鍵並選Compile就可以了。IDL編譯器生成兩個文件,它們會出現在工程管理器和代碼編輯器中:
服務器文件(xxx_s.cpp)。這個文件包含框架類的實現。
客戶端文件(xxx_c.cpp)。這個文件包含存根類的實現。
工程Option對話框的CORBA頁允許你影響從IDL文件生成stub和skeleton的方式。例如,你可以指定只想在工程中包含服務器單元,或指定要包含Tie類(用於當服務器使用代理模式delegation model時)。這些選項影響當前工程中所有的IDL文件。
注: delegation model,當使用已經寫好的從不允許多實例VCL類衍生的CORBA服務器或想與其它非CORBA應用程序共享時,可以使用不其於CORBA或不生成服務器文件的服務器類。輸出不是從框架類衍生的對象時,應用程序必須使用delegation model。它是這樣的模式:框架類實例並不直接實現CORBA對象,而是將界面調用傳給完全分離現實的類。即實現的類不是繼承自skeleton而是被skeleton調用。
要使用delegation model就要在編譯IDL文件時生成tie類(綁定類)。這樣編譯得到的框架類多出一個特殊的tie類。它充當你實現的類及其方法的代理,它將用戶調用委派給你實現的類。
詳情見聯機幫助。
--------------------------------------------------------------------------------
1-4 用CORBA object wizard定義(並實現)實現類。
//譯者:這裡大量使用“實現”一詞,其意思基本上就是實際生成。
要實現定義在IDL文件中的CORBA對象,必須實現每個框架類。要完成它,選擇File|New,從對話框的mutitier頁中選擇CORBA Object Implementation。這將觸發CORBA Implementation Wizard。
CORBA Object Implementation Wizard列出工程包含的IDL文件中定義的所有界面。選擇一個IDL文件,再從這個文件中選擇要實現的界面。提供一個實現類的名字並指定命名.h、.cpp文件的單元名。這些文件將包含對象的定義和實現。
在向導中說明實現的類是否應該繼承自動生成的框架類,或者要使用delegation model(tie類)。如果使用代理模式(且服務器是VCL可用的),還應該告訴向導使你實現的類成為一個數據模塊(data module)。這允許你向實現的數據模塊中加入所需的構件(components)。
可以告訴向導加入代碼以便應用程序啟動時實例化你的CORBA對象,這樣他們就有能力收到客戶請求。如果你啟動時實例化對象,必須給他們提供名字供客戶定位用。當客戶應用程序動態綁定到你的CORBA對象時,他們使用這個名字指明想要的對象。
當你點下OK時,CORBA Object Implementation Wizard生成你實現的類的定義並生成其實現,這個實現的每個方法體都是空的。如果你指定,它也可以加入實例化對象的代碼。
在這些改變加進工程之前,還可以查看、編輯他們。要這樣做的話,在點OK之前選上標題為Show Updates的復選框。在你查看修改之後,他們被加進工程。如果你向導結束時沒有選擇查看和修改,你可以以後再在代碼編輯器裡編輯它們。
要實現多個界面,就要多次使用CORBA對象實現向導,每次一個界面。但是,你可以提供多個名字來讓向導生成單個實現類的多個實例。
--------------------------------------------------------------------------------
1-5 完成4建立的類實現CORBA對象
如果你沒有使用delegation model(代理模式),那麼實現類是將從框架類衍生而來,框架類是編譯IDL文件時生成的。否則就你的實現類就不會有明確祖先。你可以改變這個類定義使它繼承服務程序的其它類,但不要移去任何已有的對框架類的繼承。
考慮如下取自IDL文件account.IDL中的片斷(該文件在BCB例子中):
interface Account {
float balance();
};
當IDL文件被編譯時(不帶tie類),生成的服務器頭(account_s.hh)包括了帶有對應界面中每個方法的純虛方法的框架定義。
CORBA Object Wizard創建一個實現單元,在該單元中從框架類(_sk_Account)衍生一個實現類。它的頭文件看起來如下:
#ifndef Interface1ServerH
#define Interface1ServerH
#include "account_s.hh"
//---------------------------------------------------------------------------
class AccountImpl: public _sk_Account
{
protected:
public:
AccountImpl(const char *object_name=NULL);
CORBA::float balance();
};
#endif
你可以在這個類定義加入所需的附加數據成員或方法的定義。例如:
#ifndef Interface1ServerH
#define Interface1ServerH
#include "account_s.hh"
//---------------------------------------------------------------------------
class AccountImpl: public _sk_Account
{
protected:
CORBA::float _bal;
public:
void Initialize(CORBA::float startbal); // not available to clients
AccountImpl(const char *object_name=NULL);
CORBA::float balance();
};
#endif
這些附加的方法和屬性來在服務器程序裡有效,但沒有導出給客戶端。
在生成的.cpp文件中,填寫實現類的主體,就得到了可以工作的CORBA對象:
AccountImpl::AccountImpl(const char *object_name):
_sk_Account(object_name)
{
}
CORBA::float AccountImpl::balance()
{
return _bal;
};
void Initialize(CORBA::float startbal) // not available to clients
{
_bal = startbal;
}
當實現CORBA對象的方法時,記住客戶請求可能到達不同的線程。因此,你得預防線程沖突。
注意:在你的CORBA服務器中可以編寫與BOA交互的代碼。例如,使用BOA,可以臨時令服務器對象隱藏或失活,過一回再重新激活他們。詳見VisiBroker Programmer Guid。
缺省地,CORBA應用程序是多線程的。這意味著在實現CORBA對象時必須預防線程沖突。通過鏈接到orb_b.dll和orb_br.dll也可以創建單線程的CORBA服務器,但這樣做時就失去了IDE對CORBA的支持或在服務器程序中使用VCL的好處。
除非你指定,否則BOA用緩沖池緩沖客戶線程,就是說客戶可以使用任何可用的線程。然而也可以確保每個線程始終使用相同的線程,即用逐會話線程策略啟動BOA。當所有客戶使用同一線程時,可以在線程變量中保存持久客戶的信息。詳見VisiBroker Programmer Guid。
Visibroker庫包含可以幫助你避免線程沖突的類。它們在vthread.h中定義,安裝在VisiBroker的include目錄裡。VisiBroker線程支持類包括一個互斥鎖(mutex)名為VisMutex,一個條件變量(VISCondistion)及讀寫鎖定,讀寫鎖定工作方式類似於VCL的多重讀取獨占寫同步裝置(VISRWLock)。使用這些類的好處是他們可被移植到Visibroker支持的任意平台上。
例如,你可以在類實現加入VisMutex域以保護實例數據:
class A{
VISMutex _mtx;
...
}
然後,當你需要同步實例數據存取時,可以在存取實例數據的任何方法中鎖上互斥鎖:
void A::AccessSharedMemory(...)
{
VISMutex_var lock(_mtx); //請一把鎖,鎖要已經被釋放退出。
//其它代碼,存取實例數據。
}
注意,互斥鎖會在AccessShareMemory執行完畢後釋放,即使在方法體內拋出了意外。
如果你在服務器程序中使用VCL,BCB包括許多類幫助你預防線程沖突。見聯機幫助的Writing multi-threaded applications部分。
--------------------------------------------------------------------------------
1-6 必要時,修改CORBA界面並將修改加進類實現中。
如果在用CORBA Object Wizard生成實現類之後修改IDL文件中的界面,CBuilder讓你可以自動更新服務器工程反映這些改變並保證已經寫實現類代碼不會丟失。
在你修改IDL文件之後,選擇Edit|CORBA Refresh。這條命令重編譯IDL文件以自動生成服務器和客戶文件反映新的界面定義和當前的編譯選項。如果IDL文件編譯成功,使用Project Updates對話框,你可以預覽並編輯C++BUILDER將做的修改。
注意:如果CBuider找不到與現存實現類相應的界面,會問你是否改變了界面名字。如果答是,會提示你說明界面是怎麼改名的,這樣實現的類可以正確匹配界面。
當你使用CORBA Refresh命令時,新的方法被加進你的實現類中,申明被更新以反映對現有方法和屬性的改變。然而,某些修改不會引起更新。特別是,如果你刪除一個方法或屬性,它的代碼是不刪除的。相反,被刪除的方法保留在類中,但對CORBA客戶不再可用了。相似的,如果你改名一個方法或屬性,會被當作一個刪除和一個增加,老的方法或屬性將保留,並為新方法、屬性生成代碼。
--------------------------------------------------------------------------------
IDL文件注冊
盡管注冊不是必需的,但如果你只使用靜態綁定客戶調用到服務器對象,建議注冊界面。有兩個工作可用來注冊界面:
界面倉庫(Interface Repository)。注冊到界面倉庫,客戶可以在使用動態請求界面時(Dynamic Invocation Interface)編程獲取界面信息。注冊到界面庫也便於其它開發者在寫客戶應用時查看你的界面。
對象激活守護進程(Object Activation Daemon)。注冊至OAD,便利可以直到客戶需要之時,服務器才加載或對象才實例化。這樣可節省服務器上的資源。