top
Loading...
編寫Enterprisebean的客戶端(上)
P >下面兩篇從五個方面來介紹如何編寫Enterprise bean的客戶端:

一、Enterprise JavaBean的客戶視圖:

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

  1. 首先要JavaBean的home接口:EJB 規范里面要求客戶應該使用Java的名字和目錄接口JNDI(Java Naming and Direcotry Interface)API來定位Bean的home接口。
  2. 然后獲得Enterprise JavaBean的remote接口的引用:可以使用Enterprise bean的home接口中定義的方法。可以產生一個會話bean,也可以產生或尋找(find)一個實體bean。
  3. 調用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 Sor // 引入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。其語法如下:

$#@60;remote interface$#@62; findByPrimaryKey($#@60;key type$#@62; 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方法。

作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗