国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

如何編寫Enterprise bean的客戶端

2019-11-18 14:46:21
字體:
來源:轉載
供稿:網友

  一、EnterPRise javaBean的客戶視圖:

  Enterprise JavaBean客戶是一個獨立的應用程序,或者是一個Servlet,或者一個Applet,還或者另一個Enterprise JavaBean。無論如何,客戶要使用一個Enterprise JavaBean必須要做如下事情:


首先要JavaBean的home接口:EJB 規范里面要求客戶應該使用Java的名字和目錄接口JNDI(Java Naming and Direcotry Interface)API來定位Bean的home接口。


然后獲得Enterprise JavaBean的remote接口的引用:可以使用Enterprise bean的home接口中定義的方法。可以產生一個會話bean,也可以產生或尋找(find)一個實體bean。


調用Enterprise JavaBean中定義的方法:客戶并不直接調用Enterprise JavaBean中定義的方法。而是通過調用在Enterprise JavaBean的remote接口中暴露給用戶的方法來使用JavaBean類中的方法。在remote接口中定義的方法就是在JavaBean中希望暴露給用戶,讓用戶使用的方法。


初始化客戶:

  在IAS所帶的例子里面,作為客戶的SortClient應用程序引入了必要的JNDI類、還引入了SortBean的home接口和remote接口。客戶使用JNDI的API來定位Enterprise JavaBean的Home接口。

定位Home接口:

  客戶用JNDI定位home接口。首先需要獲得一個JNDI的初始化的上下文context。下面的代碼實例化了一個新的javax.naming.Context類。在我們這個例子中叫做initialContext。然后,客戶就可以使用上下文的lookup()方法從一個名字對應到home接口。注重,初始的命名上下文工廠的初始化是由EJB容器/服務指定的。

  上下文的lookup()方法返回了一個java.lang.Object的對象。代碼必須把返回的對象轉成所希望的類型。下面的代碼是SortClient例子中的一段代碼。Main()從使用JNDI服務開始,并用上下文的lookup()方法來定位home接口。將remote接口的名字(在這個例子中是sort)傳遞給context.loopup()方法。注重,程序最后將context.lookup()方法的結果傳遞給了SortHome,home接口的類型。


用JNDI定位home接口:

// SortClient java

import javax.naming.InitialContext;

import SortHome; // 引入bean的home接口

import Sort; // 引入bean的remote接口

public class SortClient {

……

public static void main(String[] args) throws Exception

javax.naming.Context context;

{ // 用命名服務獲得JNDI上下文

context = new.javax.naming.InitialContext();

}

Object objref = context.lookup(sort);

SortHome home = (SortHome)javax.rmi.PortableRemoteObject.narrow(objref,

SortHome class);

Sort sort = home.create();

//做排序工作

sort remove();

}

maint()首先拋出一個普通的異常Excepion。當代碼執行到這兒的時候,就算可能會導致程序的終止,客戶也需要捕捉任何發生的異常。

獲得remote接口:

  現在我們獲得了Enterprise JavaBean的home接口,然后,使用home接口的create()方法或者finder()方法就可以獲得其remote接口了。實際使用哪個方法取決于Enterprise JavaBean的類型和Enterprise JavaBean的提供者在home接口定義的方法。

  例如:上面的代碼顯示了客戶SortClient如何獲得Sort的remote接口的引用。一旦SortClient獲得了home接口的引用并將之轉化為適當的類型(這里是SortHome),客戶就可以產生bean的實例,并調用它的方法。本例子中調用了home接口的create()方法,方法返回了remote接口的引用。(因為這個例子里面SortBean是一個無狀態的會話bean,其home接口只有一個create()方法,這個方法沒有任何參數)。然后,SortClient就能夠調用定義在remote接口中的方法:sort()和merge()來進行排序工作。當排序工作完成的時候,客戶調用remote接口的remove方法來刪除Enterprise bean的實例。


會話Bean:

  客戶通過調用home接口中的Create()方法獲得Enterprise JavaBean的remote接口的引用。

  每一個會話Bean都必須至少有一個Create()方法。無狀態的會話bean只能有一個Create()方法,并且這個Create()方法不能有參數。有狀態的session bean可以有一個不帶參數的Create()方法,也可以有另外的帶有不同參數的create()方法。Create()方法中的參數是用來初始化的會話bean的。

  缺省的create()方法沒有參數。例如,Sort例子使用了一個無狀態的會話bean。根據定義,它有一個沒有參數的create()方法。

   Sort sort=home.create();

  我們比較一下另一個例子:Cart例子,使用的是有狀態的會話bean。在其home接口中實現了多個的create()方法。其中一個create()方法帶了三個參數,三個參數用來標識cart的購買者,返回了Cart的home接口的引用。Cart客戶先將三個參數的值給cartHoldName,creditCartNumber和eXPirationDate這三個變量,然后調用create()方法。其代碼如下:

如何調用create()方法的代碼:

Cart cart;

{

String cartHolderName=”Jack B.Quick”

String creditCartNumber = “345-346-32525252”

Date expirationDate = new GregorianCalendar(2001, Calendar JULY, 1) getTime();

Cart = home.create(cartHolderName,creditCartNumber,expirationDate);

}

另外,要注重的是,會話Bean沒有finder方法。


實體 bean:

  通過finder方法,或者通過create方法,客戶得到實體對象的引用。我們在前面提到,實體對象代表了存儲在數據庫中的某些數據。既然Entity bean代表了一些持久的數據,那么通常實體bean存在相對長的一段時間,肯定比客戶調用它的時間要長,這樣,客戶通常需要尋找一個代表了數據庫中它感愛好的那一段數據的實體bean,而不是創建(create)一個實體bean。Create操作將會產生一個新的數據,并將新的數據存在底層的數據庫中。

  客戶通過find操作來定位一個已經存在的實體bean。可以是相關數據庫里面指定的行。也就是說,finder操作定位一個原來已經插入到數據庫中的數據實體。這個數據也許已經被實體bean加入到數據庫中,也許已經被加入到EJB上下文的外部(例如是數據庫治理系統DBMS)。或者是在原有系統中,這數據的在安裝EJB之前就已經存在。

  客戶使用create方法產生一個新的數據實體,并將數據實體存放在底層的數據庫中。實體bean的create方法將實體數據插入到數據庫中,用create方法的參數初始化實體的變量。實體bean的create方法總是返回一個remote接口。但是,對應的ejbcreate()方法是返回實體Bean實例的主鍵。

  每一個實體bean都必須有一個主鍵值來唯一標識它。一個實體bean也可以有次鍵值,用來定位特定的實體對象。


Find方法和主鍵類:

  一個實體bean的缺省的find方法是findByPrimaryKey()方法。它通過主鍵來定位實體bean。其語法如下:

<remote interface> findByPrimaryKey(<key type> primary key)

  每一個實體bean必須實現findByPrimaryKey方法。PrimaryKey參數是一個獨立的定義在配置描述器中的主鍵類。鍵的類型是主鍵,而且必須是RMI-IIOP合法的值。鍵類可以是任何Java類或者你自己寫的類。

  例如,你可能有一個名字為Acount的實體bean。已經將它的主鍵類定義為AccountPK。AccountPK是一個字符串類型。它擁有Account bean的標識。我們將account bean的標識設為AccountPK,然后調用findByPrimaryKey方法,就可以得到account bean實例的引用。如下代碼所示:

Finding a Entity bean instance using the primary key

AccountPK accountPK =new AccountPK(“1234-56-789”);

Account source = accountHome.findByPrimaryKey(accountPK);

Bean的提供者可以定義另外的finder方法給客戶使用。


Create()方法和remove()方法:

  客戶也能夠用home接口中定義的create()方法來創建一個實體bean。當客戶調用實體bean的create()方法的時候,一個新的實體bean的實例就存到數據倉庫中。新實例總是有一個標識它的主鍵值。它的狀態可以用create方法傳遞的參數值來初始化。

  注重:實體bean存在的時間與它在數據庫中代表的數據是一樣的。其生命并不由與客戶的會話來決定。通過調用實體bean的remove方法,可以將實體bean刪除。Remove方法不僅將實體bean刪除,也將它所代表的數據從數據庫中刪除。另外也可以直接刪除實體bean。例如,可以通過用原來的應用程序或用DBMS刪除數據庫中的一條記錄的方法來刪除。


調用方法:

  一旦客戶獲得了bean的remote接口的引用。就可以調用在remote接口中為enterprise bean定義的方法。屬于此bean的應用邏輯的方法才是客戶感愛好的。也有一些方法是用來獲得enterprise bean的信息或者接口信息的。例如:獲得bean對象的handle,檢查一個bean是否與另一個bean相同,刪除bean的方法。

  下面的代碼解釋了客戶如何調用enterprise bean中的方法。這個例子調用的是Cart 這個會話bean。代碼從產生一個新的Cart bean實例并重新找到一個cart bean實例的remote接口的引用開始。從這里開始,客戶就預備好可以調用bean的方法。

  首先,客戶創建了一個新的book對象,設定了其title 和price參數。然后,調用了enterprise bean的應用方法addItem()來將一個book對象加到shopping cart中去。AddItem()方法是在CartBean 這個會話bean中定義的,通過Cart的remote接口把它變成公共的方法。客戶增加了一項其它的東西,然后用summairze()方法列出shopping cart里面的所有的Items。最后,就調用remove方法來刪除bean的實例。注重,客戶用調用其他的方法也是通過同樣的途徑,即使是自己定義的方法summarize()。

調用Bean的方法

………

Cart cart;

{



//獲得bean的remote接口的實例。

Cart = home.create(cartHodlerName,creditCardNumber,expirationDate);

}

//創建一個新的book對象。

Book knuthBook = new Book(“The Art of Computer Programming”,49.95f);

//將新書加到Cart中。

Cart.addItem(knutBook);

………

//列舉當前Cart中的書

summarize(cart);

cart.removeItem(knutBook);

……


刪除bean的實例:

  remove方法對會話bean的操作和對實體bean的操作是不同的。因為對于客戶來說,會話對象的存在是不持久的。會話對象的客戶在完成了會話之后需要調用remove方法。對客戶來說,有兩個remove方法可以調用:可以用javax.ejb.EJBObject.remove()方法來刪除會話bean;也可以用javax.ejb.EJBHome.remove(Handle handle)方法來刪除會話bean的handle。

  一個好的編程風格是不需要由客戶刪除一個會話bean對象。假如客戶沒有刪除一個有狀態的會話bean,容器在過了一段時間(指定的超時值timeout value)之后會自動刪除這個對象。Timeout value是一個配置屬性。但是,客戶能夠為以后的引用保持這個對象的handle。

  Entity bean的客戶不需要考慮這個問題,因為實體bean只是在客戶的事務期間。由容器負責它的生命周期,包括激活和鈍化。只是當客戶需要將實體對象從底層數據庫中刪除的時候,才調用remove方法。

使用bean的句柄:

  句柄是用來引用enterprise bean的另一種方法。句柄相當于bean的一個較長的指針。你可以從remote接口獲得句柄。一旦你擁有了句柄,就可以將它寫入到文件或其它的持久存貯器里面。便于以后可以重新得到句柄,用它來重新建立enterprise bean的引用。

  但是,你只能用remote接口的句柄來重新建立bean的引用。你不能用句柄來創建bean本身。假如另一個進程刪除了bean,或者系統崩潰或關閉,刪除了bean的實例,則當應用程序試圖用句柄重新建立對bean的引用時會拋出異常。

  當你不確定bean的實例是否依然存在的時候,你可以不用remote接口的句柄。而是保存bean的home接口的句柄,在以后要用的時候再通過調用create方法或finder方法重新創建bean對象。

  在客戶創建了bean的實例以后,就能夠用getHandle()方法來獲得實例的句柄。一旦擁有的句柄,就能夠將它寫到文件里面去。在以后的時間,客戶可以讀這個文件,將讀出來的對象轉化為句柄類型。然后,就可以在句柄上調用的getEJBObject方法來獲得bean的引用。最后再將getEJBObject方法返回的值轉化為合適的類型。

使用句柄來引用一個Bean

Import java.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.rmi.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接口的API。JNDI是在其它的服務(CORBA的命名服務,LDAP/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-SSL


  另外: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 transfer(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 NameComponet{

Istring id;

Istring kind;

};

typedef sequence <NameCompoent> 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 <<”Could not initial naming context” <<endl;

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<<”Could not narrow to ATMSessionHome” <<endl;

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<<”Could not resolve current ”<<endl;

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來來證實服務器或者是客戶的身份。當服務器需要客戶的身份驗證的時候,服務器使用這個證書作為客戶的身份驗證。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 策勒县| 车险| 大安市| 庆阳市| 石屏县| 临颍县| 和龙市| 宿松县| 襄樊市| 眉山市| 霸州市| 海淀区| 科技| 灵丘县| 伊春市| 安泽县| 潞城市| 平塘县| 道孚县| 仪陇县| 松原市| 高要市| 津南区| 松溪县| 丁青县| 满洲里市| 诸城市| 盐城市| 斗六市| 松阳县| 郸城县| 夹江县| 宣恩县| 进贤县| 苏尼特右旗| 洛浦县| 新源县| 濉溪县| 什邡市| 克东县| 夏津县|