每一個Home接口都擴展了javax.ejb.EJBHome接口。如下代碼顯示了javax.ejb.EJBHome接口的定義:
package javax.ejb;
public interface EJBHome extends java.rmi.Remote() {
void remove(Handle handle) throws java.rmi.RemoteException,RemoveException;
void remove(Object primarykey) throws java.rmi.RemoteException,RemoveException;
EJBMetaData getEJBMetaData() throws RemoteException;
Homehandle getHomeHandle() throws RemoteException;
}
這里提供了兩個remove()方法來刪除Enterprise bean的實例。第一個remove方法是通過句柄來刪除一個Enterprise bean的實例。第二個remove方法通過主鍵來刪除一個Enterprise bean的實例。
在眾多的Enterprise bean實例中,句柄唯一的標識一個實例。一個句柄與它引用的Enterprise bean有相同的生命期。考慮一個實體對象,客戶可以通過一個句柄來重新獲得相應的Enterprise bean的實例。一個句柄能夠對應一個Enterprise bean對象的多個實例。例如,即使當Enterprise bean對象所在的主機崩潰了,或者Enterprise bean對象在不同的機器之間移動,句柄仍是有效的。這里的句柄是Serialized句柄,與CORBA中的字符串化的CORBA對象的引用是相似的概念。
在EJBHome接口中的第二個remove操作通過其主鍵來決定要刪除的Enterprise bean。主鍵可以是擴展了Java Object類的任何類型,但是,必須要實現Java的Serializable接口。主鍵是標識實體bean的主要的方法。通常,主鍵是數據庫中的一個關鍵字,唯一的定義了由實體bean代表的數據。
方法getEJBMetaData()返回了Enterprise bean對象的metadata接口。這個接口允許客戶獲得Enterprise bean的metadata信息。當開發工具來編譯鏈接應用程序的時候,或者配置工具來配置的時候,可能會用到metadata信息。Javax.ejb.EJBMetadata接口提供了獲得javax.ejb.EJBHome接口,home類,remote接口,還有獲得主鍵的方法。也提供了一個isSesson()的方法來確定在放這個home接口的對象是會話bean還是實體bean。IsStatelessSession()方法指示這個會話bean是有狀態還是無狀態的。如下代碼顯示了javax.ejb.EJBMetadata接口的定義部分的代碼。
Public javax.ejb;
lic interface EJBMetaData{
EJBHome getEJBHome();
Class getHomeInterfaceClass();
Class getRemoteInterfaceClasss();
Class getPrimaryKeyClass();
Boolean isSession();
Boolean isStatelesssSession();
}
會話bean的home接口:
在前面我們說過,一個會話bean只有一個客戶。這就是說,當一個客戶創建一個會話bean的時候,這個會話bean的實例只是為了這個創建它的客戶而存在(這里,我們指的是有狀態的會話bean。無狀態的會話bean因為并不保持會話的狀態,所以可以多個客戶)。
因為home 接口包括了一個或多個的Create()方法的定義,成為會話bean的工廠。對每一個Create()方法,EJB規范定義了如下的命名約定:
- 它的返回值是會話bean的remote接口的類型。
- 方法的名字只能是Create()。
- 對會話bean類中的每一個ejbCreate()方法都必須有一個Create()與之對應。
- 對于每一個Create()方法的參數的類型和數量都必須與會話bean類中的ejbCreate()方法相對應。
- 方法必須拋出java.rmi.RemoteException例外。
- 方法必須拋出javax.rmi.CreateExeption例外。
- Create()方法的參數是用來初始化新的會話bean對象的。
如下代碼顯示了一個會話bean對象的不同的Create()方法,其中必須的部分用粗體顯示:
public interface AtmHome extends javax.ejb.EJBHome{
Atm create() throws java.rmi.RemoteException,javax.ejb.CreateException;
Atm create(Profile preferredProfile)
Throws java.rmi.RemoteExeption,javax.ejb.CreateException;
}
注意,會話Bean的home 接口并沒有定義finder方法來定位對象。因為一個有狀態的會話bean只是給創建它的客戶使用。如果不是客戶自己創建的會話Bean,沒有必要也不允許去定位這樣的一個會話Bean。
實體bean的home接口:
跟會話bean的home接口一樣,實體bean的home接口提供了Create()的方法。另外,實體
bean的Home接口還提供了finder方法,這樣,客戶就能夠定位并使用實體bean的對象。Finder操作是必要的,因為實體bean是長時間存活的,可以被多個客戶所使用。對于大多數的應用程序而言,實體bean的實例是存在的,客戶只需要找到一個用來使用就可以了。
一個Entity bean的home接口必須提供一個缺省的finder方法:finderByPrimary(primaryKey)。這個方法允許客戶通過主鍵來定位Entity bean。方法只有一個唯一的參數:主鍵。方法的返回值類型是實體bean的remote接口類型。主鍵的類型可以是擴展了Java Object類型的任何Java類型。在配置描述器中,你必須告訴容器主鍵的類型。注意,根據定義,findByPrimaryKey()方法總是返回一個單個的Entity 對象。而其它的finder()方法可以返回Entity對象的集合。
下面是findByPrimaryKey()方法的定義:
$#@60;entity bean’s remote interface$#@62; findByPrimaryKey($#@60;primary key type$#@62; key)
throws java.rmi.RemoteException,FinderException;
home接口還可以定義別的finder()方法。每一個finder()方法都必須在Enterprise bean類里面有一個對應的實現。每一個finder方法都必須符合如下的約定。
- 返回值的類型是remote接口類型,或者finder方法能夠返回不止一個的Entity對象,或者一個以remote接口為內容類型的集合類型。有效的Java集合類型是java.util.Enumeration接口(JDK1.1規范)或java.util.Collection接口(java 2規范)。
- finder方法總是以前綴find開頭。在實體bean 類里面以前綴ejbFind開頭。
- 必須拋出java.rmi.RemoteException異常。
- 必須拋出javax.ejb.FinderException異常。
- 在home接口中的的throws子句與實體bean類的ejbCreate()方法的throws子句也必須對應。
另外,Entity的Home接口能夠提供一個或多個的Create()方法。這些方法返回了實體bean的remote接口的對象引用類型。它們的參數必須由應用程序指定。
Home接口中的Create()方法必須遵守如下規則:
- 必須拋出java.rmi.RemoteException異常
- 必須拋出javax.ejb.CreateException異常
- 返回是實體bean的remote接口類型
- 方法的名字必須是create
- 必須有一個方法與實體bean類里面的ejbCreate()方法相對應。每一個create()方法參數的個數和類型都必須與實體bean類中的相應的ejbCreate()方法一致。
- Home接口中,create()方法中的throws子句必須包括所有在實體bean類中相應的ejbCreate()方法和ejbPostCreate()方法中的throws子句拋出的例外。這就是說,Create()方法拋出的例外集合必須是ejbCreate()方法和ejbPostCreate()方法拋出例外的并集的超集。EjbCreate()方法的返回值是主鍵類。
- Create()方法的參數是用來初始化新實體bean對象的。
如下代碼顯示了不同類型的finder()和Create()方法。必須的部分用粗體表示:
public interface AccountHome extends javax.ejb.EJBHome{
Account create(String accoundId)
throws java.rmi.RemoteException,javax.ejb.CreateException;
Account create(String accoundId, float initialBalance)
Throws java.rmi.RemoteException, javax.ejb.CreateException;
Account findByPrimaryKey(String key)
Throws java.rmi.RemoteException, javax.ejb.FinderException;
Enumeration findBySocialSecurityNumber(String socialSecurityNumber)
Throws java.rmi.RemoteException,javax.ejb.FinderException;
}
Enterprise bean實現:
Enterprise bean的實現包括了所有的應用程序指定的語義。這是Bean提供者的主要工作。一個會話bean類實現了javax.ejb.SessionBean接口。而一個實體bean實現了一個javax.ejb.EntityBean接口。這兩個接口都擴展了同一個基類javax.ejb.EnterpriseBean。但是會話bean的實現和實體bean的實現不同。
Enterprise bean接口:
Enterprise bean接口javax.ejb.EntpriseBean定義了一個通用的基類,并擴展了java.io.Serializable接口。它并沒有定義任何方法。其定義代碼如下:
Package javax.ejb;
Public interface EnterpriseBean extends java.io.Serializable{}
Handle句柄:
Handle是遠程對象引用Enterprise bean對象它的Home接口的一種抽象的方式。所有的Enterprise bean對象句柄都實現了javax.ejb.Handle接口。這個接口提供了對Enterprise bean對象的持久的引用。其定義代碼如下:
Public interface javax.ejb.Handle extends java.io.Serializable{
Public EJBObject getEJBObject() throws java.rmi.RemoteException;
}
通過Serialize類(這個類實現了handle接口)的實例,handle可以持久的存儲一個Enterprise bean對象的引用。這與CORBA IOR的字符串化相似。Javax.ejb.Handle擴展了java.io.Serializable接口。
Javax.ejb.HomeHandle接口也提供了Enterprise bean的home接口的持久的引用。Javax.ejb.HomeHandle由所有的Home對象handle實現。其定義代碼如下:
Public interface HomeHandle extends java.io.Serializable{
Public EJBHome getEJBHome() throws RemoteException;
}
通常,Handle是由容器實現的。
五、編程限制:
下面列舉了一些EJB1.1規范的編程限制:
- Enterprise bean不允許管理線程和線程組。不能啟動一個新的線程,不能繼續一個掛起的線程,也不允許中斷或掛起一個正在運行的線程。另外,Enterprise bean不能改變一個線程的優先級,也不能改變線程的名字。
- Enterprise bean不能使用既可讀又可寫的靜態的字段。但可以使用只讀的靜態的字段。這樣,所有的靜態字段就必須聲明為final。
- Enterprise bean不允許使用線程同步原語來同步多個實例的執行。
- Enterprise bean不能使用java的AWT函數來輸出信息顯示到屏幕。也不能從鍵盤接受信息。
- Enterprise bean也不能使用java.io包來訪問文件系統的文件和目錄。
- Enterprise bean應該盡量少使用sockets。特別的,Enterprise bean不能夠監聽Sockets,不能接受Socket上的連接,或使用Socket來進行廣播。也不應該使用由SeverSocket,Socket建立的Socket工廠,或者由URL使用的流工廠。
- Enterprise bean不能訪問classes或package,也不能獲得關于classes的信息。在某種程度上不允許通過Java程序設計語言。或者說,classes對Enterprise bean是不可用的。
- Enteprise bean通常不允許訪問環境函數,這些環境函數通常是由容器來控制。例如:產生一個類裝載器,訪問或者修改上下文,設置或產生安全管理器,停止JVM,改變輸入,輸出或錯誤流。
- Enterprise bean不能為一段代碼獲得安全方針信息,否則會危及安全。
- Enterprise bean不能裝載本地庫。
- Enterprise bean不能在package中定義類。這個功能由于安全的原因被容器所保留。
- Enterprise bean不能使用子類或Java Serialiazation Protocol中的對象取代特性。
- 如果Enterprise bean使用了this作為參數或方法的返回值,需要萬分小心。使用SessionContext.getEJBObject()或EntityContext.getEJBObject來傳遞結果更安全一些。
- Enterprise bean不允許改變對象的安全配置。例如,不允許改變它的java.security.Identify。任何這樣的企圖都會拋出一個java.security.SecurityException異常。