編寫Enterprise bean的客戶端(下) (轉)

worldblog發表於2007-12-08
編寫Enterprise bean的客戶端(下) (轉)[@more@]

使用bean的控制程式碼:

  控制程式碼是用來引用enterprise bean的另一種方法。控制程式碼相當於bean的一個較長的指標。你可以從remote介面獲得控制程式碼。一旦你擁有了控制程式碼,就可以將它寫入到或其它的持久存貯器裡面。便於以後可以重新得到控制程式碼,用它來重新建立enterprise bean的引用。

  但是,你只能用remote介面的控制程式碼來重新建立bean的引用。你不能用控制程式碼來建立bean本身。如果另一個程式刪除了bean,或者崩潰或關閉,刪除了bean的例項,則當應用試圖用控制程式碼重新建立對bean的引用時會丟擲異常。

  當你不確定bean的例項是否依然存在的時候,你可以不用remote介面的控制程式碼。而是儲存bean的home介面的控制程式碼,在以後要用的時候再透過create方法或finder方法重新建立bean。

  在客戶建立了bean的例項以後,就能夠用getHandle()方法來獲得例項的控制程式碼。一旦擁有的控制程式碼,就能夠將它寫到檔案裡面去。在以後的時間,客戶可以讀這個檔案,將讀出來的物件轉化為控制程式碼型別。然後,就可以在控制程式碼上呼叫的get方法來獲得bean的引用。最後再將getEJBObject方法返回的值轉化為合適的型別。

使用控制程式碼來引用一個Bean

Import .io;

Import javax.ejb.Handle;

……

Cart cart;

……

cart = home.create(cartHolderName,creditcartNumber,expirationDate);

//在cart物件上呼叫getHander方法來獲得它的控制程式碼。

CartHander=cart.getHandler();

//將hander寫到檔案中去。

FileOutputStream f = new FileOutputStream(“carthandle.ser”);

ObjectOutputStream o = new ObjectOutputStream(f);

o.writeObject(myHandle);

o.flush();

o.close();

……

//在以後的某個時間,可以從檔案中讀出handle

FileInputStream fi = new FileInputStream(“carthandle.ser”);

ObjectInputSteam oi = new ObjectInputStream(fi);

//從檔案中讀出物件並將它轉化為Hander型別。

CartHanle = (Handle)oi.readObject();

Oi.close;

……

//使用handle來引用bean的例項

try{

Object ref = context.lookup(“cart”);

Cart cart1 = (Cart)javax..PortableRemoteObject.narrow(ref,Cart.class);

……

}catch(RemoteException e){

……

}

……

  當用完會話bean的控制程式碼以後,客戶將使用javax.ejb.EJBHome.remove(Handle handle)方法來刪除控制程式碼。


二、管理事務:

  客戶程式能夠管理它自己的事務,而不是讓enterprise bean或者是容器來管理。客戶管理自己事務的時,就好象會話bean管理它自己的事務一樣。

  當客戶管理自己的事務的時候,需要自己來描述事務的分界線。這也就是說,它必須明確的開始一個事務和終止(提交或回滾)一個事務。

  客戶使用javax.transaction.UserTransaction介面來管理它自己的事務。它必須首先用JNDI來獲得UserTransaction介面的引用。一旦有了UserTranscation的上下文,就可以用UserTransaction.begin()方法來開始一個事務(後面用UserTranscation.commit()方法提交或Usertransction.rollback()方法回滾這個事務)。這之間客戶做有關的查詢和操作。

  如下程式碼演示了客戶如何實現管理它自己的事務。客戶管理的屬於的那部分用粗體顯示:

客戶管理事務:

import javax.naming.initialContext;

import javax.transcation.UserTransaction;

……

public class clientTransaction{

public static void main(String[] argv){

UserTranscation ut=null;

InitialContext initContext = new InitialContext();

……

ut = (UserTransaction)initContext.lookup(“java:comp/UserTranscation”);

//開始一個事務

ut.begin();

//做事務工作。

……

ut.commit(); //or ut.rollback();

}

}


三、獲得enterprise bean的資訊:

  enterprise bean的資訊是一個指向metadata引用。客戶使用enterprise bean的home介面的getMetaData()方法能夠獲得bean的metadata資訊。

  GetMetaData()方法經常被開發環境和build工具所使用,因為它們需要知道enterprise bean的相關資訊,例如哪些連結到一起的bean已經被。指令碼客戶也需要獲得bean的metadata資訊。

  一旦客戶重新得到home介面的引用。就能夠在home介面上呼叫getEJBMetaData()方法。然後,客戶就可以透過呼叫EJBMetaData介面上的方法來取得如下資訊。

  用EJBMetaData.getEJBHome()方法獲得bean的EJBHome介面。


  用EJBMetaData.getHomeInterfaecClass()方法來獲得home介面類的物件。包括其介面,類,域和方法。


  用EJBMetaData.getRemoteInterfaceClass()方法來獲得remote介面類的物件。包括所有的類資訊。

  用EJBMetaData.getPrimaryKeyClass()方法來獲得bean的主鍵類物件。

  不管是會話bean還是實體bean。可用EJBMetaData.isSession()方法來判斷。

  用EJBMetaData.isStatelessSession()來判斷會話bean是否有狀態還是無狀態的。


四、JNDI的支援:

  EJB規範定義了定位home介面的。JNDI是在其它的服務(的命名服務,/X.500,flat files,目錄服務)上面實現的。下圖解釋了不同的實現選擇。典型的,EJB服務提供者選擇一個特定的JNDI實現。

 


  這個技術實現了JNDI底層的與客戶無關性。客戶只需要使用JNDI的API就可以了。


五、EJB到CORBA的對映:

  EJB和CORBA之間有許多的聯絡。有三點很重要:

  用ORB實現EJB容器/服務。


  將原有系統放到EJB中間層的綜合能力。


  從非java的客戶,訪問EJB的能力。


  EJB規範目前只涉及到這三個方面。

  CORBA是實現EJB下層組織的很適合而且很自然的平臺。CORBA提供了所有的EJB規範與CORBA核心規範或者與CORBA核心服務之間的相關的東西。

持分散式:CORBA核心和CORBA命名服務


支援事務:CORBA物件的事務服務


支援:CORBA的安全規範,包括IIOP-over-


  另外:CORBA允許非JAVA元件與應用程式的結合。這些元件可以是原來的系統或程式,將它們插入到不同的客戶中去。後端系統能夠很容易的用OTS和任何能夠與IDL對映的語言結合在一起。這需要容器提供OTS和IIOP的APIs。


  EJB規範允許非JAVA客戶訪問enterprise bean,也提供了EJB到CORBA的對映。EJB/CORBA對映的目的是:

  支援用任何CORBA支援的程式設計語言編寫的客戶端和基於CORBA的EJB服務上的enterprise bean的結合。


  使客戶程式在相同的事務處理中與CORBA物件或者enterprise bean相結合。


  支援在涉及到不同商提供的多個客戶端在基於CORBA的EJB上執行時的分散式事務。


  對映是基於java-to-IDL對映的。其規範包括瞭如下幾個方面:分散式關係的對映,命名約定的對映,事務處理的對映,安全的對映。下面的部分,我們將解釋每一個對映。因為對映用了新的IDL特性,這些特性在OMG的Object-by-Value規範中介紹。與其它語言的結合需要與CORBA2.3ORB規範相容。


分散式的對映:

  enterprise bean有兩個可以訪問的介面:remote介面和home介面。IDL規範中有這樣的JAVA/IDL到這些介面的對映。EJB規範中定義的基類也是以同樣的方式對映到IDL中的。

  例如:讓我們看看下面的IDL介面,這是ATM那個例子。是一個enterprise 會話bean。有一個方法在accounts之間轉帳。也可以丟擲資金不足的異常。透過JAVA/IDL對映其home介面和remote介面。我們得到如下的IDL介面:


Module transaction{

Module ejb{

Valuetype InsufficientFundsException: ::java::lang::Exception{};


Exception InsufficientFundsEx{

::transcation::ejb::InsufficientFundsException value;

};


interface Atm: ::javax::ejb::EJBObject{

void traner(in string arg[], in string arg1, in float arg2)

raise(::transaction::ejb::InsufficientFundsEx);

};


interface AtmHome: ::javax.:ejb::EJBHome{

::transaction::ejb::Atm create{}

raise(::javax::ejb::CreateEx);

};

};

};


命名對映:

  基於CORBA的EJB執行時環境如果要想讓所有的CORBA客戶都能夠訪問enterprise bean,就必須使用CORBA命名服務來發布enterprise bean的home介面。執行時能夠直接使用CORBA的命名服務,或者透過JNDI及其到CORBA命名服務的標準對映來間接的使用。

  JNDI命名用一個字串表示成如下形式:“directory1/directory2/…/directotyN/objectName”。CORBA的命名服務將名字定義成一系列的名字元件:

Typedef string Istring;

Struct NameComp{

Istring id;

Istring kind;

};

typedef sequence Name;

  每一個由”/”分開的JNDI字串名字都被對映成一個名字元件。最左邊的元件就是CORBA命名服務名字的第一個入口。

JNDI字串名字與一些命名上下文有關。我們把這樣的上下文叫做JNDI根部上下文。JNDI根部上下文相當於CORBA的命名服務的初始化上下文。CORBA命名服務的名字與CORBA的初始化上下文有關。

透過在ORB的虛擬物件上面呼叫resolv_initial_reference(“NameService”),CORBA應用程式能夠得到初始的CORBA命名服務的上下文。CORBA命名服務並沒有指定如何組織命名上下文,這樣,根上下文的概念就不起作用了。ORB的初始化透過resolve_initial_reference()來決定上下文。

例如:一個C++的客戶端能夠定位我們的ATM會話bean的home介面。這個ATM bean已經用JNDI字串“transaction/corbaEjb/atm”註冊。首先,我們得到初始的命名上下文。

oject_ptr obj = orb->resolve_initial_references(“NameService”);

NameContext initialNameContext = NameingContext.narrow(obj);

if (initialNameingContext == NULL) {

cerr <

exit(1);

}

然後,我們產生了一個CORBA命名服務的名字並且根據上面所說的對它進行初始化。

Name name = new Name(1);

name[0].id=”atm”;

name[0].kind=””;

現在我們解決了初始化命名服務的名字問題。假定我們成功的進行了初始化,我們也有了enterprise bean名字域上的上下文。我們將CORBA物件範圍縮小到所需要的型別,並且,確信這樣的縮小是成功的。

Object_ptr obj=initialNamingContext->resolve(name);

AtmSessionHome_ptr atmSessionHome = AtmSessionHome.narrow(obj);

if (atmSessionHome == NULL){

cerr<

exit(1);

}


事務處理的對映:

基於CORBA的enterprise bean執行時環境需要使CORBA的客戶端參加到涉及enterprise bean的事務處理中來,就必須使用CORBA的OTS(Object Transaction Service)來進行事務控制。

當enterprise bean好之後,能夠根據不同的事務服務方針進行安裝。方針是定義在配置描述器中的。

事務性的enterprise bean有如下的定義規則:CORBA客戶透過IDL介面產生的stub來呼叫enterprise bean的remote介面和home介面。如果涉及到事務處理,它使用CORBA OTS提供的介面。

例如:一個C++的客戶能夠呼叫ATM會話bean:

try{

//obtain transaction current

Object_ptr obj = orb->resolve_initial_reference(“Current”);

Current current = Current.narrow(obj);

if(current==NULL){

cerr<

exit(1);

}

//execute transaction

try{

current->begin();

atmSession->transfer(“checking”,”saving”,100.00);

current->commit(0);

}catch(…){

current->rollback();

}

}catch(…){

……

}


安全的對映:

EJB規範的安全方面主要考慮的是控制enterprise bean的訪問。CORBA規定了一些方法來定義識別符號,包括如下的方面:

Plain IIOP(簡單的IIOP方式):CORBA的主要介面在1998年早期並沒有被接受。主要的介面用來確定客戶的標識。但是,CORBA安全服務的作者卻實現了不同的途徑:GIOP。GIOP規範包括了一個叫服務上下文的元件,其實是一個元素為值對的陣列。其識別符號是CORBA的long型的,值是十進位制的序列。服務上下文的入口可以用來標識呼叫者。


Secure IIOP(可靠的IIOP方式):CORBA的安全規範為身份定義了一個不透明的資料型別。身份的實際型別是由所選擇的安全機制所決定的。例如:GSS Kerberos,SPKM,或者CSI-ECMA。


IIOP over SSL:SSL(套接字協議層)用X.509來來證明伺服器或者是客戶的身份。當伺服器需要客戶的身份驗證的時候,伺服器使用這個證照作為客戶的身份驗證。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-989768/,如需轉載,請註明出處,否則將追究法律責任。

相關文章