實體EJB用在處理客戶端請求大量、并發的情況,它在實現業務邏輯的同時,作為數據庫的一個緩沖。在服務量大的情況下,減輕數據庫的負擔,提高業務處理能力。本章介紹實體EJB、兩種持久性管理方法、編程模型和實例開發過程。
5.1 實體EJB編程模型
1.實體EJB
實體EJB封裝了業務邏輯實現,并且可以供多個客戶使用。除了實現業務邏輯外,實體EJB的屬性用來代表商業過程中處理的永久性數據。一個簡單的實體Bean可以定義成代表數據庫表的一個記錄,也就是每一個實體對象代表 一條具體的記錄。更復雜的實體Bean可以代表數據庫表間關聯視圖。
2.實體EJB的持久性
持久性是實體EJB的一個重要概念。
圖5-1 EJB客戶端視圖
和會話Bean的編程模型一樣,實體EJB的客戶端視圖也是由主接口和遠程接口組成。主接口實現類負責實體對象的創建和查詢,遠程接口實現類負責邏輯方法的調用。
3.定位一個會話Bean主接口
客戶端使用JNDI定位一個實體Bean主接口。例如,Account實體Bean的主接口可使用以下代碼進行查找:
Context initialContext = new InitialContext();
AccountHome accountHome = (AccountHome)
javax.rmi.PortableRemoteObject.narrow(initialContext.lookup("java:comp/env/ejb/accounts"),
AccountHome.class);
一個客戶端的JNDI命名空間可以配置起來包含網絡上在不同機器上的、不同EJB容器中的EJB的主接口。而EJB容器的實際位置對使用企業Bean的客戶端來說是透明的。
4.實體Bean主接口
部署在容器中實體Bean的主接口的實現是由容器提供的。并且,容器確??蛻舳四軌蛲ㄟ^JNDI訪問到部署在容順中的每個實體Bean的主接口。實現實體Bean主接口的對象是EJBHome。
通過實體Bean主接口,客戶端可以進行如下操作:
·創建新的實體對象。
·查找存在的實體對象。
·刪除實體對象。
·執行主邏輯方法。
·獲取主接口的句柄。
主句柄能被序列化,并且能被寫入存儲設備中。然后,句柄可以在另一個不同的JVM中,從固定存儲器中反序列化,獲取主接口的引用。
實體Bean主接口必須擴展javax.ejb.EJB主接口,并遵循Java語言遠程接口規范。
5.create方法
實體Bean主接口可以定義多個create方法,每種方法都能創建一個實體對象。create方法的參數一般用來初始化實體對象的狀態。每種create方法名的前綴是“create”。
create方法的返回類型是實體bean的遠程接口。每個create方法都要定義拋出兩個異常java.rmi.RemoteException和javax.ejb.CreateExcention。也可以包含其它的引用級異常。例如:下面主接口定義中演示了三個create方法:
public Interface AccountHome extends javax.ejb.EJBHome{
public Account create(String firstName,String lastName,double initialBalance)
throws RemoteException,CreateException;
public Account create(String accountNumber,double initialBalance)
throws RemoteException,CreateException,LowInitialBalanceException;
public Account createLargeAccount(String firstname,String lastname,
double initialBalance)
throws RemoteException,CreateException;
...
}
下面代碼演示客戶端程序如何創建一個新的實體對象:
AccountHome accountHome =...;
Account account = accountHome.create("John","Smith",500.00);
6.finder方法
實體Bean主接口可以定義一個或多個finder方法,每個方法定義一種查詢一個實體EJB和多個EJB對象的方法。
finder方法必須以“find”為前綴,如findLargeAccounts(...),參數由實體Bean的來定位請求的實體對象。finder方法的返回值必須是實體Bean的遠程接口,或者是實現實體Bean遠程接口對象的集合。定義finder方法的異常有java.rmi.RemoteException和javax.ejb.FinderException。
每個實體Bean的主接口包含一個findByPrimaryKey(primaryKey)方法。它允許客戶端使用主鍵定位一個實體對象,它的名字總是findByPrimaryKey,只有一個參數,這個參數具有和實體Bean主鍵相同的類型,返回類型是實體Bean的遠程接口。每個實體Bean有惟一的findByPrimaryKey(primaryKey)方法,該方法不能被重載,其實現必須確保實體對象存在。下面代碼片斷演示findByPrimaryKey方法:
public Interface AccountHome extends javax.ejb.EJBHome{
...
public Account findByPrimaryKey(String AccountNumber)
throws RemoteException,FinderException;
}
下面代碼片斷演示客戶端如何使用findByPrimaryKey方法:
AccountHome=...;
Account account = account 主findByPrimaryKey("100-3450-3333");
7.remove方法
javax.ejb.EJBHome接口定義了允許客戶端刪除實體對象的方法:
public Interface EJBHome extends Remote{
void remove(Handle handle) throws RemoteException,RemoveException;
void remove(Object primaryKey) throws RemoteException,RemoveException;
}
實體對象刪除后,客戶端訪問實體對象會產生java.rmi.NoSuchObjectException異常。
8.Home方法
實體Bean的主接口可以定義一個或多個主方法。主方法是不特定于某個實體Bean實例業務邏輯方法。主方法的名字必須以“create”、“ind”或“remove”作為開關。主方法的參數被實體Bean的實現類使用,不依賴于某個特定的實體Bean實例。方法的參數和返回值必須是RMI-IIOP的合法類型。
主方法的定義必須招聘java.rmi.RemoteException異常。也可以包括其它引用級異常。
下面代碼片斷演示兩個方法:
public Interface EmployeeHome extends javax.ejb.EJBHome{
...
public float livingIndex(String state,float Salary)
throws RemoteExcetption;
public void addBonus(float company_share_index)
throws RemoteException,ShareIndexOutOfRangeException;
...
}
9.主鍵和對象標識
每個實體對象有一個惟一的標識。如果兩個實體對象有相同的主鍵,則它們是同一的。EJB架構允許主鍵是任何合法類型的類。
擁有實體對象遠程接口引用的客戶端可以通過getPrimaryKey()方法獲取主鍵標識。和引用聯系的對象標識在被引用期間不會改變。
客戶端可以測試兩個實體對象是否指向同一個實體對象,用isIdentical(EJBObject)方法。也可以采用equals方法比較它們的主鍵。
下面代碼片斷演示使用isIdentical方法測試指向同一個實體對象的兩個對象引用:
Account acc1 = ...;
Account acc2 = ...;
if (acc1.isIdentical(acc2)){
//acc和acc2是同一個實體對象
}else{
//acc1和acc2是不同一個實體對象
}
如果客戶端知道實體對象的主鍵,則調用實體Bean主接口的findByPrimaryKey(key)方法,可以獲得實體對象的的引用。
注意,比較兩個引用是否指向同一個實體對象,不能使用Object.equals(Object obj)方法,只能使用isIdentical方法。
10.實體Bean的遠程接口
客戶端通過實體Bean的遠程接口訪問實體對象。實體Bean的遠程接口必須擴展javax.ejb.EJBObject接口。遠程接口定義客戶端使用的邏輯方法。
下面代碼片斷演示實體Bean遠程接口的定義:
public Interface Account extends javax.ejb.EJBObject{
void debit(double amount)
throws java.rmi.RemoteException,InsufficientBalanceException;
void credit(double amount)
throws java.rmi.RemoteException;
double getBalance()
throws java.rmi.RemoteException;
}
javax.ejb.EJBObject接口定義允許客戶端使用實體對象引用進行,如下操作:
·獲取實體對象的主接口。
·刪除實體對象。
·獲取實體對象句柄。
·獲取實對象主鍵。
容器實現javax.ejb.EJBObject接口中定義的方法,而業務方法以EJB的形式,以代理的方式被調用。
注意 實體對象沒有把javax.ejb.EnterpriseBean中定義的方法暴露給客戶端,這些方法是被容器調用的。
11.實體Bean的句柄
實體對象的句柄是在網絡上標識實體的,擁有實體對象的遠程接口客戶端可以通過調用getHandle()方法獲取實體對象句柄,該句柄類繼承java.io.Serializable,所以客戶端可以序列化句柄??蛻舳丝梢栽诹硪粋€進程和消息系統中,反序列化該句柄,以重新獲得實體對象的引用。
客戶端代碼必須使用javax.rmi.PortableRemoteObject.narrow(...)方法來把getEJBObject()方法的結果轉換成實體Bean遠程接口類型。
下面代碼片斷演示了句柄的使用:
//客戶端獲取account實體句柄,并保存
ObjectOutputStream stream = ...;
Account account = ...;
Handle bandle = account.getHandle();
stream.writeObject(handle);
//客戶端可以從存儲設備中讀取句柄,使用句柄獲取
//account實體對象的引用
ObjectInputStream stream = ...;
Handle handle=(Handle)stream.readObject(handle);
Account account = (Account)javax.rmi.PortableRemoteObject.narrow(
handle.getEJBObject(),Account.class);
account.debit(100.00);
12.實體主句柄
EJB規范允許客戶端獲取主接口的句柄??蛻舳税褜嶓wBean的主接口引用以句柄的方式存到存儲設備中,然后可以重新獲取。當客戶端不知道主接口的JNDI名,又想使用主接口,這是個解決的辦法。
主接口的句柄必須實現javax.ejb.HomeHandle接口。
客戶端代碼必須使用java.rmi.PortableRemoteObject.narrow(...)方法來把getEJBHome()方法的結果轉化成主接口類型。
5.2 實體對象的生命周期
實體對象在創建后,有一個標識??蛻舳耸褂脤嶓wBean的主接口創建實體對象。創建成功后,客戶端獲取這個新創建的實體對象的引用。
實體對象可以通過create方法以外的其他方式創建(如直接插入數據庫一條記錄),它仍可以通過finder方法訪問。同時,實體對象可以不使用remove()方法,而是直接刪除(如直接刪除數據庫一條記錄)。
客戶端可以通過多種方式獲取一個實體對象的遠程接口引用:
·在方法調用中,引用作為參數傳遞過來。
·使用實體Bean主接口中定義的finder方法找到實體對象。
·從實體對象句柄中獲取引用。
擁有實體對象遠程接口引用的客戶端能做下面的事:
·通過遠程接口調用實體對象的業務邏輯方法。
·獲取主接口的引用。
·把引用作為參數或作為遠程方法調用的返回值。
·獲取實體對象的主鍵。
·獲取實體對象的句柄。
·刪除實體對象。
使用不存在實體對象的引用是無效的。調用不存在的實體對象引用的方法會拋出異常java.rmi.NoSuchObjectException。
多個客戶端可以同時訪問實體對象。事務處理把每個客戶端分離開。
5.3 容器管理持久性實體EJB
5.3.1實例說明
本示例演示容器管理持久性實體EJB實例的開發過程,內容包括:
(1)實體EJB主接口、遠程接口定義和實現類編寫;
(2)EJB說明文件和部署文件的編寫;
(3)EJB屬性與數據表字段映射文件的編寫:
(4)如何定義連接池;
(5)如何編譯EJB程序;
(6)測試EJB程序。
示例文件包括:
AccountHome.java,Account.java,AccountBean.java,ProcessingErrorException.java,Client.java,ejb-jar.xml,weblogic-cmp-rdbms-jar.xml,weblogic-ejb-jar.xml。
5.3.2編寫源文件
1.編寫主接口程序
編輯文件AccountHome.java并保存到C:\work\src\examples\ejb\basic\containerManaged目錄下(或從附帶光盤的src\examples\ejb\basic\containerManaged目錄拷貝)。AccountHome.java源文件如下:
//AccountHome.java
//定義本接口在包examples.ejb.basic.containerManaged中
package examples.ejb.basic.containerManaged;
//本接口用到的其他類
//javax.ejb.*中定義了實現EJBean的接口。
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
import javax.ejb.FinderException;
import java.rmi.RemoteException;
import java.util.Enumeration;
/**
* 這是AccontBean的主接口定義,這個接口是被EJB容器產生的類AccontBeanC實現的。
* 在這里只需定義EJB創建的方法,這些方法要和EJBean中的"ejbCreate"方法對應。
*/
//EJBean主接口必須繼承javax.ejb.EJBHome接口
public interface AccountHome extends EJBHome {
/**
* 這個方法和"AccountBean.java"中定義的的Bean的"ejbCreate"方法相對應
* 這兩個方法的參數應該相同。當客戶端調用"TraderHome.create()"方法時,EJB容器
* 會找到EJBean的實例,并調用它的"ejbCreate()"方法。
* 對容器管理的ejb,ejbCreate方法返回為null,而bean管理的ejb,返回的是主鍵類。
* @參數 accountID String 賬號ID
* @參數 initialBalance double 初始化結算值
* @參數 type String 賬號類型
* @返回 Account 遠程對象
* @異常 javax.ejb.CreateException
* 創建bean錯誤時拋出的異常
* @異常 RemoteException 當系統通訊發生故障時拋出
* @參看 examples.ejb.basic.containerManaged.AccountBean
*/
public Account create(String accountId, double initialBalance, String type)
throws CreateException, RemoteException;
/**
* 根據主鍵對象,返回賬號對象
*
* @參數 primaryKey 主鍵
* @返回 Account 賬號
* @異常 javax.ejb.FinderException
* 訪問數據庫錯誤拋出的異常
* @異常 RemoteException 當系統通訊發生故障時拋出
* @參看 examples.ejb.basic.containerManaged.AccountBean
*/
public Account findByPrimaryKey(String primaryKey)
throws FinderException, RemoteException;
/**
* 找到所有結算值等于balanceEqual的賬號
*
* @返回 Account 賬號
* @參數 double balanceEqual,給定的結算值
* @異常 javax.ejb.FinderException
* 訪問數據庫錯誤拋出的異常
* @異常 RemoteException 當系統通訊發生故障時拋出
* @參看 examples.ejb.basic.containerManaged.AccountBean
*/
public Account findAccount(double balanceEqual)
throws FinderException, RemoteException;
/**
* 找到所有結算值大于balanceGreaterThan的賬號
*
* @返回 Enumeration 所有賬號枚舉
* @參數 double balanceGreaterThan,給定的結算值
* @異常 javax.ejb.FinderException
* 訪問數據庫錯誤拋出的異常
* @異常 RemoteException 當系統通訊發生故障時拋出
* @參看 examples.ejb.basic.containerManaged.AccountBean
*/
public Enumeration findBigAccounts(double balanceGreaterThan)
throws FinderException, RemoteException;
/**
* 找到所有類型為'null'的EJBeans。
*
* @返回 Enumeration 所有賬號枚舉
* @異常 javax.ejb.FinderException
* 訪問數據庫錯誤拋出的異常
* @異常 RemoteException 當系統通訊發生故障時拋出
* @參看 examples.ejb.basic.containerManaged.AccountBean
*/
public Enumeration findNullAccounts()
throws FinderException, RemoteException;
}
2.編寫遠程接口程序
編輯文件Account.java并保存到C:\work\src\examples\ejb\basic\containerManaged目錄下(或從附帶光盤的src\examples\ejb\basic\containerManaged目錄拷貝)。Account.java源文件如下:
//Account.java
//定義本接口在包examples.ejb.basic.containerManaged中
package examples.ejb.basic.containerManaged;
//本接口用到的其他類
//javax.ejb.*中定義了實現EJBean的接口。
import java.rmi.RemoteException;
import javax.ejb.*;
/**
* 這是AccontBean的遠程接口定義。遠程接口中定義了客戶端能遠程調用EJBean的方法。這些方法除了
* 要拋出異常java.rmi.RemoteException之外,和EJBean中的定義是一致的。但并不是EJBean來實
* 現這個接口,而是由容器自動產生的類AccontBeanE實現的。
*/
//這個接口必須繼承javax.ejb.EJBObject接口
public interface Account extends EJBObject {
/**
* 遠程方法:存入一定數目的金額
*
* @參數 amount 存入金額的數量
* @返回 double 操作實際結果
* @異常 RemoteException 當系統通訊發生故障時拋出
*/
public double deposit(double amount)
throws RemoteException;
/**
* 遠程方法:提取一定數目的金額
*
* @參數 amount 提取金額的數量
* @返回 double 操作實際結果
* @異常 RemoteException 當系統通訊發生故障時拋出
* @異常 ProcessingErrorException
* 購買操作出錯時拋出的異常
*/
public double withdraw(double amount)
throws ProcessingErrorException, RemoteException;
/**
* 遠程方法:結算
* @返回 double 結算值
* @異常 RemoteException 當系統通訊發生故障時拋出
*/
public double balance()
throws RemoteException;
/**
* 返回賬號類型
*
* @返回 String 賬號類型
* @異常 RemoteException 當系統通訊發生故障時拋出
*/
public String accountType()
throws RemoteException;
}
3.編寫實現類程序
編輯文件AccountBean.java并保存到C:\work\src\examples\ejb\basic\containerManaged目錄下(或從附帶光盤的src\examples\ejb\basic\containerManaged目錄拷貝)。AccountBean.java源文件如下:
//AccountBean.java
//定義本接口在包examples.ejb.basic.containerManaged中
package examples.ejb.basic.containerManaged;
//本類用到的其他類。javax.ejb.*是開發EJB應用需要的類庫。javax.naming.*是實現JNDI服務需要的類庫。
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;
import javax.ejb.CreateException;
import javax.ejb.DuplicateKeyException;
import javax.ejb.EJBException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.ejb.FinderException;
import javax.ejb.NoSuchEntityException;
import javax.ejb.ObjectNotFoundException;
import javax.ejb.RemoveException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
/**
* AccountBean是實體EJB,它演示了:
* 容器管理的JDBC持續性管理和事務管理;
* 在這個文件中的代碼并沒有直接訪問數據庫;
* 用戶定義的異常;
* 使用isModified方法,這個方法改變容器管理的字段,通過設置isDirty
*/
//這個類是實體Bean,必須實現接口 EntityBean
public class AccountBean implements EntityBean {
//設置是否打印控制臺
final static boolean VERBOSE = true;
//聲明實體上下文變量
private EntityContext ctx;
//聲明實體EJB屬性變量
public String accountId; // 這也是主鍵類
public double balance;
public String accountType;
private transient boolean isDirty; // 決定bean是否謝數據庫的標志
/**
* 為EJBean設置實體EJB上下文
*
* @參數 ctx EntityContext
*/
public void setEntityContext(EntityContext ctx) {
log("setEntityContext called (" + id() + ")");
this.ctx = ctx;
}
/**
* 取消實體上下文設置
*
*/
public void unsetEntityContext() {
log("AccountBean.unsetEntityContext (" + id() + ")");
this.ctx = null;
}
/**
* 返回EJBean是否被改變
*
* 這個方法必須為public 以使被容器調用
*
* @返回 boolean isDirty
*/
public boolean isModified() {
log("isModified(): isDirty = " + (isDirty ? "true" : "false"));
return isDirty;
}
/**
* 設置EJBean的改變標志
*
* @參數 flag 改變標志
*/
public void setModified(boolean flag) {
isDirty = flag;
log("setModified(): " + id() + (String) (flag ? ": requires saving"
: ": saving not required"));
}
/**
* 返回標識這個EJBean的主鍵
*
* @返回 String 標志
*/
private String id() {
return "" + System.identityHashCode(this) + ", PK = " +
(String) ((ctx == null) ? "nullctx"
: ((ctx.getPrimaryKey() == null ?
"null" : ctx.getPrimaryKey().toString()))) +
"; isDirty = " + isDirty;
}
/**
* 這是本類必須實現的方法,在本例中沒有用到
*
*/
public void ejbActivate() {
log("AccountBean.ejbActivate (" + id() + ")");
}
/**
* 這是本類必須實現的方法,在本例中沒有用到
*
*/
public void ejbPassivate() {
log("AccountBean.ejbPassivate (" + id() + ")");
}
/**
* 這是本類必須實現的方法,在本例中沒有用到
*
*/
public void ejbLoad() {
log("AccountBean.ejbLoad (" + id() + ")");
}
/**
* 設置EJBean的改變標記為false
*
*/
public void ejbStore() {
log("AccountBean.ejbStore (" + id() + ")");
setModified(false);
}
/**
* 這是本類必須實現的方法,在本例中沒有用到
*
*/
public void ejbRemove()
throws RemoveException
{
log("AccountBean.ejbRemove (" + id() + ")");
}
/**
* 這個方法和"AccountBean.java"中定義的的Bean的"ejbCreate"方法相對應
* 這兩個方法的參數應該相同。當客戶端調用"TraderHome.create()"方法時,EJB容器
* 會找到EJBean的實例,并調用它的"ejbCreate()"方法。
* 對容器管理的ejb,ejbCreate方法返回為null,而bean管理的ejb,返回的是主鍵類。
* @參數 accountID String 賬號ID
* @參數 initialBalance double 初始化結算值
* @參數 type String 賬號類型
* @異常 javax.ejb.CreateException
* 創建bean錯誤時拋出的異常
* @參看 examples.ejb.basic.containerManaged.AccountHome
*/
public String ejbCreate(String accountId, double initialBalance, String type)
throws CreateException
{
log("AccountBean.ejbCreate( id = " + System.identityHashCode(this) + ", PK = " +
accountId + ", " + "initial balance = $ " + initialBalance + ")");
this.accountId = accountId;
this.balance = initialBalance;
this.accountType = type;
return null; // See 9.4.2 of the EJB 1.1 specification
}
/**
* 這是本類必須實現的方法,在本例中沒有用到
*/
public void ejbPostCreate(String accountId, double initialBalance, String type)
{
log("AccountBean.ejbPostCreate (" + id() + ")");
}
// 應用程序定義的方法
/**
* 存入一定金額
*
* @參數 amount double 數量
* @返回 double 結算
*/
public double deposit(double amount)
{
log("AccountBean.deposit: Depositing $" + amount + " into '" + accountId + "'");
//業務邏輯計算
balance += amount;
//設置改變標記
setModified(true);
return balance;
}
/**
* 提取一定數量的金額
*
* @參數 amount double 數量
* @返回 double 結算
* @exception ProcessingErrorException
* 如果提取的數量大于結算值
*/
public double withdraw(double amount)
throws ProcessingErrorException
{
log("AccountBean.withdraw: Withdrawing $" + amount + " from '" + accountId + "'");
if (amount > balance) {
//拋出用戶定義異常
throw new ProcessingErrorException("Request to withdraw $" + amount +
"; is more than balance $" + balance +
" in account " + accountId);
}
//業務邏輯計算
balance -= amount;
//設置改變標記
setModified(true);
return balance;
}
/**
* 返回當前的結算
*
* @返回 double 結算
*/
public double balance() {
log("AccountBean.balance (" + id() + ")");
return balance;
}
/**
* 返回賬號類型
*
* @返回 String 賬號類型
*/
public String accountType() {
log("AccountBean.accountType (" + id() + ")");
return accountType;
}
//控制臺輸出
private void log(String s) {
if (VERBOSE) System.out.println(s);
}
}
4.編寫處理異常程序
用文本編輯器編輯文件ProcessingErrorException.java并將它保存到C:\work\src\examples\ejb\basic\containerManaged目錄下(或從附帶光盤的src\examples\ejb\basic\containerManaged目錄拷貝)。其源文件如下:
//ProcessingErrorException.java
//定義本類在包examples.ejb.basic.containerManaged 中
package examples.ejb.basic.containerManaged;
/**
* 這是用戶定義的異常類
*/
//用戶定義的異常類必須繼承Exception
public class ProcessingErrorException extends Exception {
/**
* 獲取沒有字符串參數的異常
*
*/
public ProcessingErrorException() {}
/**
* 用特定的字符串構造異常
*
* @參數 message Exception 消息
*/
public ProcessingErrorException(String message) {super(message);}
}
5.編寫客戶端測試程序
編輯文件Client.java并將它保存到C:\work\src\examples\ejb\basic\containerManaged目錄下(或從附帶光盤的src\examples\ejb\basic\containerManaged目錄拷貝)。其源文件如下:
//Client.java
//定義本類在包examples.ejb.basic.containerManaged 中
package examples.ejb.basic.containerManaged;
//本類用到的其他類
import java.rmi.RemoteException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;
//本類用到的EJB類
import javax.ejb.CreateException;
import javax.ejb.DuplicateKeyException;
import javax.ejb.FinderException;
import javax.ejb.ObjectNotFoundException;
import javax.ejb.RemoveException;
//本類用到的名稱服務類
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
/**
* 這個類演示了如何調用一個實體EJB,并進行如下操作:
* A:創建一個Account遠程對象,存入一些錢。然后試圖提取超過當前結算的金額?;驋伋鲇脩舳x的異常,
* 最后,清除Account遠程對象。
* B:創建一些新的賬號,它們有不同的結算值。找到所有計算值大于給定數值的賬號。找到結算職為0的賬號。
* 試圖查找賬號類型為null的賬號。最后,刪除所有新創立的賬號。
* 這個例子同時演示了怎樣在JNDI樹查找EJB主接口。
*/
public class Client {
//聲明變量
private String url;
private String accountId;
private AccountHome home;
//構造方法
public Client(String url, String accountId)
throws NamingException {
this.url = url;
this.accountId = accountId;
//找找主接口,lookupHome是本例自定義方法。
home = lookupHome();
}
/**
* 在命令行運行這個實例:
* java examples.ejb.basic.containerManaged.Client "t3://localhost:7001"
* 參數是可選的
* @參數 url URL such as "t3://localhost:7001" of Server
* @參數 accountID String Account ID to test, default "10020"
*/
public static void main(String[] args) {
System.out.println("\nBeginning containerManaged.Client...\n");
String url = "t3://localhost:7001";
String accountId = "10020";
// Parse the argument list
switch(args.length) {
case 2:
accountId = args[1];
// fall through
case 1:
url = args[0];
break;
}
Client client = null;
try {
//實例化本類
client = new Client(url, accountId);
} catch (NamingException ne) {
//異常處理
log("Unable to look up the beans home: " + ne.getMessage());
System.exit(1);
}
try {
//運行實例A
client.runExamplePartA();
//運行實例B
client.runExamplePartB();
} catch (Exception e) {
//異常處理
log("There was an exception while creating and using the Accounts.");
log("This indicates that there was a problem communicating with the server: "+e);
}
System.out.println("\nEnd containerManaged.Client...\n");
}
/**
* 執行實例A
*