用OBPM30分鐘實(shí)現(xiàn)BUG管理系統(tǒng)
http://vinsun.javaeye.com/blog/138164posted @ 2009-02-25 10:07 paulwong 閱讀(316) | 評(píng)論 (1) | 編輯 收藏
posted @ 2009-02-25 10:07 paulwong 閱讀(316) | 評(píng)論 (1) | 編輯 收藏
posted @ 2009-01-21 16:32 paulwong 閱讀(2327) | 評(píng)論 (1) | 編輯 收藏
posted @ 2008-12-31 12:16 paulwong 閱讀(959) | 評(píng)論 (0) | 編輯 收藏
posted @ 2008-12-22 10:53 paulwong 閱讀(1204) | 評(píng)論 (0) | 編輯 收藏
posted @ 2008-12-17 12:04 paulwong 閱讀(707) | 評(píng)論 (0) | 編輯 收藏
posted @ 2008-12-06 16:29 paulwong 閱讀(202) | 評(píng)論 (0) | 編輯 收藏
posted @ 2008-12-04 11:33 paulwong 閱讀(262) | 評(píng)論 (0) | 編輯 收藏
Session Bean 是目前 EJB 規(guī)格 (EJB 2.0) 中 3種 Enterprise Bean 的其中一種,另外兩種分別是 Entity Bean 和 Message Driven Bean,這3種 Enterprise Bean 依照其特性被應(yīng)用在不同的範(fàn)疇中。其中 Session Bean 和 Entity Bean 早在 EJB 1.x 規(guī)格中就已經(jīng)存在,Message Driven Bean 卻是在 EJB 2.0 才被加入。
在 EJB 架構(gòu)中,Session Bean 主要目的是塑造企業(yè)流程,當(dāng)中可能包括系統(tǒng)運(yùn)算、存取資料庫(kù)、呼叫其他 Enterprise Bean等等。其範(fàn)例包括流程引擎、買(mǎi)賣(mài)交易、型錄查詢等應(yīng)用。接下來(lái)會(huì)從 Session Bean 的各個(gè)不同的特性說(shuō)明其實(shí)際應(yīng)用的方式、時(shí)機(jī)和要注意的地方。
在 EJB 規(guī)格中,Session Bean被細(xì)分為 Stateless Session Bean 和 Stateful Session Bean。兩者根據(jù)特性在應(yīng)用上有著很大差異:
Session Bean 不能被共用,每一個(gè) Bean 只能用來(lái)服務(wù)一個(gè)客戶,而 Bean 和客戶端之間會(huì)有一份對(duì)話資訊 (請(qǐng)參考附註 [A] )。
基本上只在單一方法呼叫中保存對(duì)話資訊,一旦 Bean 完成處理後,對(duì)話資訊會(huì)隨著被清除。
在同一個(gè) Session 裡,可以保留呼叫者與 Session Bean 之間的對(duì)話資訊與狀態(tài),等下一次執(zhí)行方法時(shí)繼續(xù)提供使用。
Session Bean 的生命週期除了依不同廠商的 EJB Container 會(huì)有所不同外,Bean 的 Stateful 特性也會(huì)影響到其存活的時(shí)機(jī)。
當(dāng)客戶端所呼叫 Stateless Session Bean完畢後,Bean 會(huì)馬上被 EJB Container 銷(xiāo)毀,或?qū)?shí)例 (Instance) 保存下來(lái)以供其他客戶端使用。
和 Stateless Session Bean 不同,當(dāng)客戶端所呼叫Stateless Session Bean完畢後,Bean 不會(huì)馬上被 EJB Container 銷(xiāo)毀,而是繼續(xù)存在於 Session Bean Pool (請(qǐng)參考附註 [B] ),直到 Session 完結(jié)。
1. 不需要在每次客戶端對(duì) Session Bean 的方法呼叫後保持對(duì)話資訊。
1. 在每個(gè) Session Bean 的方法呼叫之間需要保持 Session 中的資訊。
2. 利用 Session Bean 的對(duì)話狀態(tài) (Conversational State) (請(qǐng)參考附錄) 管理企業(yè)流程。
由於不需要管理對(duì)話資訊,也就是可以佔(zhàn)用比較少系統(tǒng)資源去暫存與客戶端之間的對(duì)話資訊,而且在每次被呼叫完畢後可以馬上轉(zhuǎn)移給其他客戶端使用,故效能較佳。
每次被客戶端呼叫完畢後都會(huì)將代表這客戶端的狀態(tài)資訊暫時(shí)儲(chǔ)存起來(lái),在 Session 完畢後也要把之前所記錄與客戶端的對(duì)話資訊清除,所以會(huì)消耗較多系統(tǒng)資源。
開(kāi)發(fā)一支 Session Bean 時(shí),至少包括4個(gè)步驟:
1. 編寫(xiě) Home Interface
2. 編寫(xiě) Remote Interface
3. 編寫(xiě) Bean 的實(shí)作 (Implement) 類別,當(dāng)中包括描述企業(yè)流程的方法實(shí)作
4. 編寫(xiě)部署文件 (ejb-jar.xml)
Session Bean 的`介面繼承自 javax.ejb.EJBHome,負(fù)責(zé)控制一個(gè) Session Bean 的生命週期,含有建立與銷(xiāo)毀 EJB 物件的方法,一般情況下,其命名規(guī)則為 <<Bean-name>> + Home。要注意的是,Home介面中需要定義一個(gè) create() 方法 (對(duì)應(yīng)到 Bean 實(shí)作類別的 ejbCreate()),用來(lái)取得一個(gè) Bean 的實(shí)例。另外 Home 介面中也可以定義一個(gè) remove() 方法對(duì)應(yīng)到 Bean 實(shí)作類別的 ejbRemove()),用來(lái)移除 Bean 的實(shí)例。
【範(fàn)例】
package examples;
import javax.ejb.*;
import java.rmi.RemoteException;
public Interface HelloWorldHome extends EJBHome{
HelloWorld create() throws RemoteExcception, CreateException;
}
繼承自 javax.ejb.EJBObject,含有 Bean 裡所有的每一個(gè)方法以供遠(yuǎn)端程序呼叫,一段情況下,其命名規(guī)則為 <<Bean-name>>。由於遠(yuǎn)端介面是 RMI-IIOP 遠(yuǎn)端介面 (繼承 java.rmi.Remote) ,因此必須拋出 java.rmi.RemoteException。
【範(fàn)例】
package examples;
import javax.ejb.*;
import java.rmi.RemoteException;
public Interface HelloWorld extends EJBObject{
public void helloWorld() throws RemoteException;
}
繼承自 javax.ejb.SessionBean,一段情況下,其命名規(guī)則為 <<Bean-name>> + Bean。定義一個(gè) Session Bean 可以透過(guò)定義一個(gè)實(shí)現(xiàn) javax.ejb.SessionBean 介面的類別來(lái)達(dá)成,該介面定義如下:
public Interface javax.ejb.SessionBean extends javax.ejb.EnterpriseBean{
public void ejbCreate(…) throws RemoteException;
public void ejbActivate() throws RemoteException;
public void ejbPassivate() throws RemoteException;
public void ejbRemove() throws RemoteException;
public void setSessionContext(SessionContext ctx) throws RemoteException;
}
以上幾個(gè)方法並不是要讓客戶端使用和呼叫的,而是要讓 EJB Container 使用來(lái)管理 Session Bean 的生命週期,因此不可以直接在客戶端程式裡呼叫。每個(gè)方法的說(shuō)明如下,詳細(xì)的方法呼叫時(shí)機(jī)請(qǐng)參考「Session Bean 與 EJB Container 互動(dòng)」:
方法 |
說(shuō)明 |
ejbCreate(…) |
初始化 Session Bean |
ejbActivate() |
EJB container 將 Session Bean 主動(dòng)化 (activate) 後馬上呼叫此一方法,取得 Bean 所需資源 (在 stateless 不需實(shí)作,因?yàn)椴恍杈S護(hù)對(duì)話資訊) |
ejbPassivate() |
EJB container 將 Session Bean 被動(dòng)化 (passivate) 後馬上呼叫此一方法,釋放 Bean 所佔(zhàn)的資源(如 socket 連線) |
ejbRemove() |
EJB container 將 Session Bean 從記憶體中移除之前會(huì)呼叫此一方法,釋放所有已配置的資源 |
setSessionContext(SessionContext ctx) |
EJB container 將 Session Bean 與 Session Context 關(guān)聯(lián)在一起,Bean 可以從中查詢目前交易狀態(tài)和資訊 |
【範(fàn)例】
package examples;
import javax.ejb.*;
public Interface HelloWorldBean extends EJBObject{
public void helloWorld(){
System.out.println(“Hello Word !!!”);
}
public void ejbCreate() throws CreateException{
System.out.println(“ejbCreate”);
}
public void ejbRemove() {
System.out.println(“ejbRemove”);
}
public void ejbActivate() {
System.out.println(“ejbActivate”);
}
public void ejbPassivate() {
System.out.println(“ejbPassivate”);
}
public void setSessionContext(SessionContext ctx) {
System.out.println(“setSessionContext”);
}
}
要讓所編寫(xiě)的 Session Bean 可以在 EJB Container 部署和正確運(yùn)作,除了編寫(xiě)程式碼外,我們還需要把 Session Bean 的特性描述在部署文件,也就是 ejb-jar.xml。編寫(xiě) Session Bean 時(shí),不需要在程式碼中指明所寫(xiě)的 Bean 是 stateless 還是 stateful,其 stateful 特性是定義在部署文件裡,也就是說(shuō)可以透過(guò)修改部署文件而簡(jiǎn)單的把 Session Bean 在 stateless 和 stateful 之間切換。
【範(fàn)例】
<!DOCTYPE ejb-jar PUBLIC
“-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN”
“http://java.sun.com/dtd/ejb-jar_2_0.dtd”>
<ejb-jar>
<enterprise-Beans>
<Session>
<ejb-name>Hello</ejb-name>
<Home>examples.HelloWorldHome</Home>
<remote>examples.HelloWorld</ remote>
<ejb-class>examples.HelloWorldBean</ejb-class>
<Session-type>Stateless</Session-type>
<transaction-type>Container</transaction-type>
</Session>
</enterprise-Beans>
</ejb-jar>
<ejb-name> |
Session Bean 的名稱 |
<Home> |
Session Bean 的 Home 介面 |
<remote> |
Session Bean 的 remote 介面 |
<ejb-class> |
Session Bean 實(shí)作的類別 |
<Session-type> |
描述Session Bean 的 stateful 特性 (Stateless / Stateful) |
<transaction-type> |
描述 Session Bean 的交易特性 (Container / Bean) |
在客戶端的程式呼叫 Session Bean 的方法時(shí),其實(shí) Bean 會(huì)根據(jù)其特性 (stateful 特性) 和 EJB container 互動(dòng),以下簡(jiǎn)單的說(shuō)明 EJB container 如何管理 Session Bean 的生命週期。
1. 當(dāng)客戶端程式呼叫 Stateless Session Bean 上的方法之前,會(huì)先呼叫 Bean 的Home 介面中的create() 以取得一個(gè) Bean 的參考 (reference)。
2. EJB container 會(huì)馬上呼叫 ejbCreate() 和 setSessionContext() 產(chǎn)生一個(gè) Bean 實(shí)例和把 Session Context 和 Bean 關(guān)聯(lián)在一起。
3. 當(dāng)方法呼叫完畢,EJB container 會(huì)呼叫 ejbRemove() 把 Bean 銷(xiāo)毀,Bean 所佔(zhàn)用的資源也會(huì)被釋放。
1. 和 Stateless Session Bean 一樣,客戶端程式呼叫 Stateful Session Bean 上的方法之前會(huì)先呼叫 create() 取得一個(gè) Bean 的參考。
2. EJB container 會(huì)馬上呼叫 ejbCreate() 和 setSessionContext() 產(chǎn)生一個(gè) Bean 實(shí)例和把 Session Context 和 Bean 關(guān)聯(lián)在一起。
3. 由於 Stateful Session Bean 會(huì)管理與客戶端之間的對(duì)話資訊,所以在Bean 的方法被呼叫完畢後,EJB container 不會(huì)馬上把 Bean 銷(xiāo)毀,而是在適當(dāng)時(shí)間 (依不同廠商的EJB Container 會(huì)有所不同) 把 Bean 被動(dòng)化 (呼叫 ejbPassivate()) 和將對(duì)話資訊暫存起來(lái)。
4. 當(dāng)客戶端程式再次呼叫 Bean 上的方法時(shí),如果 Bean 是在被動(dòng)狀態(tài),EJB container 會(huì)呼叫 Bean 的 ejbActivate() 把 Bean 的狀態(tài)轉(zhuǎn)為預(yù)備狀態(tài),而之前暫存的對(duì)話資訊也會(huì)再放進(jìn) Bean 實(shí)例裡。
5. 當(dāng)客戶端程式呼叫 Bean 的 remove() 或是客戶端的 Session 已經(jīng)完結(jié)時(shí),EJB container會(huì)呼叫 ejbRemove() 把 Bean 銷(xiāo)毀,Bean 所佔(zhàn)用的資源也會(huì)被釋放,之前所保持的與客戶端之間的對(duì)話資訊也會(huì)同時(shí)被清除。
附註 [A] 對(duì)話資訊:包括 Session 資訊和對(duì)話狀態(tài) Conversational State。當(dāng)客戶端程式呼叫 Session Bean 時(shí),可能會(huì)改變其實(shí)例參數(shù) (Instance Variable) 的值。在客戶端程式再次呼叫同一個(gè) Session Bean 參考的方法時(shí),Stateful Session Bean 會(huì)保留上次方法呼叫被改變的實(shí)例參數(shù)的值,但 Stateless Session Bean 卻不會(huì)。
附註 [B] Session Bean Pool:EJB container 存放 Session Bean 實(shí)例 (Instance) 的地方,可根據(jù)不同的需要而設(shè)定大小 (設(shè)定於佈署文件中),Pool 的大小會(huì)影響系統(tǒng)效能。
posted @ 2008-12-04 11:32 paulwong 閱讀(539) | 評(píng)論 (0) | 編輯 收藏
posted @ 2008-12-04 11:32 paulwong 閱讀(492) | 評(píng)論 (0) | 編輯 收藏
從前面幾期的介紹,我們知道Enterprise JavaBean(EJB)是J2EE架構(gòu)中用來(lái)實(shí)作business tier的技術(shù)。就J2EE Design Pattern而言,business tier代表了MVC pattern中的model,model負(fù)責(zé)處理的是對(duì)business最重要的domain objects與business logic。在這個(gè)脈絡(luò)下,J2EE Design Pattern建議我們使用session bean與message-driven bean實(shí)作business logic,而以entity bean實(shí)作domain objects。透過(guò)使用entity bean,我們以物件模式塑模(modeling)business data,這不僅使我們可以運(yùn)用物件導(dǎo)向程式設(shè)計(jì)的優(yōu)點(diǎn),也得以享受EJB Container提供的各種背景服務(wù)(如Persistence、Transaction、Security、Concurrency等)。本期及下一期我們將就entity bean的種類、生命週期、程式碼的實(shí)作、以及client端的使用對(duì)entity bean做一初步的介紹。後續(xù)的幾期我們將介紹entity bean的進(jìn)階功能與相關(guān)設(shè)定。
就資料保存(Data Persistency)的觀點(diǎn)而言,entity bean以物件模式保存資料只是各種資料保存模式中的一種。在實(shí)作中,entity bean除了接收來(lái)自clent端的資料外,主要還是從所謂的Enterprise Information System tier(EIS)取得既存的資料並將處理後的資料儲(chǔ)存在EIS tier,而關(guān)聯(lián)式資料庫(kù)(RDBM)則是目前最為普遍的EIS tier技術(shù)。面對(duì)不同的資料保存模式,如何在不同的tier之間維持資料的一致性與完整性(Data Interity)是個(gè)重要的課題。針對(duì)這個(gè)問(wèn)題,EJB提供了兩種技術(shù):CMP bean與BMP bean。BMP bean(Bean-Managed Persistence)將有關(guān)資料保存的工作交由開(kāi)發(fā)人員負(fù)責(zé),開(kāi)發(fā)人員必須熟悉EJB Container呼叫call back 方法與其他bean life-cycle方法的時(shí)機(jī)與方式,並在BMP bean中實(shí)作與存取資料庫(kù)有關(guān)的程式碼。而CMP bean(Container-Managed Persistence)則將有關(guān)資料保存的工作交由EJB Container處理,開(kāi)發(fā)人員不需要在entity bean中編寫(xiě)有關(guān)存取資料庫(kù)的程式碼,而只需要在部署描述子(deployment descriptor)中定義好entity bean與資料庫(kù)之間的對(duì)應(yīng)(mappings),在部署階段部署工具會(huì)自動(dòng)產(chǎn)生相關(guān)的JDBC程式碼。這麼做的好處首先在於實(shí)際部署時(shí)得以動(dòng)態(tài)產(chǎn)生entity bean與data sources之間的繫結(jié);更重要的是,它使開(kāi)發(fā)人員得以專注於以物件導(dǎo)向的思維模式集中心力於business logic上。
在EJB 1.1規(guī)格書(shū)中並沒(méi)有對(duì)CMP如何與資料庫(kù)schema之間的mappings提出一個(gè)標(biāo)準(zhǔn)的規(guī)範(fàn),此外對(duì)於如何建立多個(gè)entity bean之間的關(guān)係,如何尋找與定位(finding and locating)entity bean的做法亦付之闕如。但在EJB 2.0規(guī)格書(shū)中則對(duì)CMP做出了重大的改進(jìn),包括標(biāo)準(zhǔn)的Query Language(QL)、Container-Managed Relationships(CMR)等,我們將在下期作進(jìn)一步的介紹。以下是有助於選擇CMP或BMP的因素:
1. CMP比BMP易於開(kāi)發(fā)維護(hù),EJB Container會(huì)對(duì)資料存取的過(guò)程做最佳化。
2. BMP適用於對(duì)效能要求較高與較為複雜的應(yīng)用程式,但若開(kāi)發(fā)不當(dāng),則很容易拖垮系統(tǒng)的效能。
3. CMP不支援較為複雜的SQL語(yǔ)法,如在where子句中對(duì)日期與時(shí)間的比較。
4. CMP支援的data sources類型受container provider的限制。此外目前的CMP並不支援非JDBC的data sources。
5. 如果要使用CMR,則必須使用CMP。
EJB Container運(yùn)用集區(qū)(Pool)的概念來(lái)管理entity bean以妥善運(yùn)用系統(tǒng)資源並增進(jìn)系統(tǒng)效能。根據(jù)entity bean是否被放入集區(qū)與是否與EJB Object結(jié)合,entity bean有三種狀態(tài):分別是Not Exist State、Pooled State、Ready State。下圖展示了EJB Container如何藉由呼叫bean class的call back與life-cycle方法在這三種狀態(tài)間轉(zhuǎn)換(下圖引用自Richard Monson-Haefel, Enterprise JavaBeans, 3rd Edition, O’Reilly,Page 308, Figure 11-2):
1. Not Exist State
在這個(gè)狀態(tài)中,entity bean可視為一堆檔案的集合,這些檔案包括部署描述子、component interface,以及所有在部署階段產(chǎn)生的輔助classes。此時(shí)不存在任何entity bean instance。
2. Pooled State
當(dāng)EJB Server啟動(dòng)後,它會(huì)讀取相關(guān)檔案,產(chǎn)生一些entity bean的instance。在產(chǎn)生entity bean instance後,EJB Container會(huì)呼叫entity bean的setEntityContext()方法,將EntityContext物件賦予entity bean instance,EntityContext物件記載著該entity bean instance所在的EJB Container的狀態(tài)。在entity bean instance被賦予EntityContext後,就被放到集區(qū)中,進(jìn)入Pooled State。此時(shí)的entity bean只有預(yù)設(shè)值,並不代表資料庫(kù)裡的任何資料。
有幾種情況可以使得在Pooled State中的entity bean instance離開(kāi)集區(qū)並被資源回收。首先,EJB Server可視需要增加或減少集區(qū)中的entity bean instance,以有效利用系統(tǒng)資源並在效能上有較佳表現(xiàn)。其次,當(dāng)停止EJB Server時(shí),EJB Container也會(huì)釋放所有在集區(qū)中的bean instance。最後,當(dāng)entity bean instance出現(xiàn)不可修復(fù)的錯(cuò)誤時(shí),EJB Container也會(huì)將之移出集區(qū),並以集區(qū)中其他entity bean instance取代之。
在entity bean instance被移出集區(qū)之後與被資源回收之前,EJB Container會(huì)呼叫其unsetEntityContext()方法,以通知該entity bean instance即將被毀滅。
3. Ready State
當(dāng)client端呼叫entity bean的home interface上的create()方法時(shí),EJB Server會(huì)產(chǎn)生一個(gè)EJB Object,並從集區(qū)中取出一個(gè)entity bean與之結(jié)合,此時(shí)entity bean進(jìn)入Ready State。接著EJB Container會(huì)依序呼叫在entity bean instance上與create()對(duì)應(yīng)的ejbCreate()與ejbPostCreate()方法。當(dāng)ejbPostCreate()方法執(zhí)行完成後,create()方法會(huì)回傳一個(gè)EJB Object的reference給client端,此時(shí)entity bean instance與EJB Object就可以服務(wù)來(lái)自client端的請(qǐng)求。
前面介紹Pooled State時(shí)曾提到EJB Container為了有效利用系統(tǒng)資源,會(huì)視需要增加或減少集區(qū)中的entity bean instance,同樣地,EJB Container也會(huì)視需要在Pooled State與Ready State之間移動(dòng)entity bean instance。Entity bean instance從Ready State移至Pooled State叫做Passivation過(guò)程,從Pooled State移至Ready State則叫做Activation過(guò)程。在Passivation過(guò)程中,EJB Container會(huì)呼叫entity bean的ejbStore()方法,將目前entity bean instance的資料寫(xiě)回資料庫(kù),再呼叫entity bean的ejbPassivate()方法通知該entity bean instance其即將被移回Pooled State。ejbPassivate()方法執(zhí)行完成後,entity bean instance就與EJB Object分離並回到Pooled State。
Activation過(guò)程預(yù)設(shè)了某entity bean先前的Passivation過(guò)程。在Passivation過(guò)程結(jié)束後,原先與EJB Object結(jié)合的entity bean instance回到Pooled State,而EJB Object則維持其與client端的連線。一旦client再度呼叫EJB Object上的方法時(shí),EJB Container就從集區(qū)中任意取出一entity bean instance與既存的EJB Object結(jié)合,繼續(xù)服務(wù)來(lái)自client端的請(qǐng)求。在這過(guò)程中,EJB Container呼叫entity bean的ejbActivate()方法,通知該entity bean instance準(zhǔn)備更新來(lái)自資料庫(kù)的資料,再呼叫entity bean的ejbLoad()方法通知該entity bean instance資料已經(jīng)重新寫(xiě)入,準(zhǔn)備服務(wù)來(lái)自client端的請(qǐng)求。
最後一種從Ready State將entity bean instance移回Pooled State的情況是client端呼叫EJB Object或EJB Home上相關(guān)的的remove方法時(shí),EJB Container會(huì)呼叫entity bean上的ejbRemove()方法,此時(shí)系統(tǒng)會(huì)刪除資料庫(kù)中與該entity bean instance相對(duì)應(yīng)的資料。ejbRemove()方法執(zhí)行完成後,該entity bean instance就被移回Pooled State。
posted @ 2008-12-04 11:30 paulwong 閱讀(297) | 評(píng)論 (0) | 編輯 收藏