| |
5.4 Bean管理持久性实体EJB |
| 2008-8-12 文章来源:培训网
责任编辑:zsol 字体: [ ] |
|
|
|
5.4 Bean管理持久性实体EJB
Bean管理持久性的EJB要求开发者维护EJB和数据库的映射关系,在Bean实现类的编写中,由开发者指定对数据库的操作。 示例文件包括:AccountHome.java,Account.java,AccountBean.java,ProcessingErrorException.java,Client.java,Servlet.java,ejb-jar.xml,weblogic-ejb-jar.xml。
5.4.1 编写源文件
1.编写主接口程序
编辑文件AccountHome.java并保存到C:\work\src\examples\ejb\basic\beanManaged目录下(或从附带光盘的src\examples\ejb\basic\beanManaged目录拷贝),其源文件如下:
//AccountHome.java //定义本接口在包examples.ejb.basic.beanManaged 中 package examples.ejb.basic.beanManaged; //本类用到的其他类。javax.ejb.*是开发EJB应用需要的类库。javax.naming.*是实现JNDI服务需要的类库。 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()"方法。 * @参数 accountID String 账号ID * @参数 initialBalance double 初始化结算值 * @返回 Account 远程对象 * @异常 javax.ejb.CreateException * 创建bean错误时抛出的异常 * @异常 RemoteException 当系统通讯发生故障时抛出 * @参看 examples.ejb.basic.beanManaged.AccountBean */ public Account create(String accountId, double initialBalance) throws CreateException, RemoteException;
/** * 根据主键对象,返回账号对象 * * @参数 primaryKey 主键 * @返回 Account 账号 * @异常 javax.ejb.FinderException * 访问数据库错误抛出的异常 * @异常 RemoteException 当系统通讯发生故障时抛出 * @参看 examples.ejb.basic.beanManaged.AccountBean */ public Account findByPrimaryKey(String primaryKey) throws FinderException, RemoteException;
/** * 找到所有结算值大于balanceGreaterThan的账号 * * @返回 Enumeration 所有账号枚举 * @参数 double balanceGreaterThan,给定的结算值 * @异常 javax.ejb.FinderException * 访问数据库错误抛出的异常 * @异常 RemoteException 当系统通讯发生故障时抛出 * @参看 examples.ejb.basic.beanManaged.AccountBean */ public Enumeration findBigAccounts(double balanceGreaterThan) throws FinderException, RemoteException; }
2.编写远程接口程序
编辑文件Account.java并保存到C:\work\src\examples\ejb\basic\beanManaged目录下(或从附带光盘的src\examples\ejb\basic\beanManaged目录拷贝),其源文件如下:
//Account.java //定义本接口在包examples.ejb.basic.beanManaged 中 package examples.ejb.basic.beanManaged; //本接口用到的其他类 //javax.ejb.*中定义了实现EJBean的接口。 import java.rmi.RemoteException; import javax.ejb.EJBObject;
/** * 这是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; }
3.编写实现类程序
编辑文件AccountBean.java并保存到C:\work\src\examples\ejb\basic\beanManaged目录下(或从附带光盘的src\examples\ejb\basic\beanManaged目录拷贝),其源文件如下:
//AccountBean.java //定义本接口在包examples.ejb.basic.beanManaged package examples.ejb.basic.beanManaged; //本类用到的其他类。javax.ejb.*是开发EJB应用需要的类库。javax.naming.*是实现JNDI服务需要的类库 import java.io.Serializable; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; 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.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource;
/** * AccountBean是实体EJB,它演示了: * EJBean管理的JDBC持续性管理和事务管理; * 在这个文件中的代码直接访问数据库; */ //这个类是实体Bean,必须实现接口 EntityBean public class AccountBean implements EntityBean { //设置是否打印控制台 final static private boolean VERBOSE = true; //声明实体上下文变量 private EntityContext ctx; private String accountId; // 这也是主键类 private double balance; /** * 为EJBean设置实体EJB上下文 * * @参数 ctx EntityContext */ public void setEntityContext(EntityContext ctx) { log("setEntityContext called"); this.ctx = ctx; }
/** * 取消实体上下文设置 * */ public void unsetEntityContext() { log("unsetEntityContext (" + id() + ")"); this.ctx = null; } /** * 这是本类必须实现的方法,在本例中没有用到 * */ public void ejbActivate() { log("ejbActivate (" + id() + ")"); }
/** * 这是本类必须实现的方法,在本例中没有用到 * */ public void ejbPassivate() { log("ejbPassivate (" + id() + ")"); }
/** * 从数据库中加载EJB * * @异常 javax.ejb.NoSuchEntityException * 如果在数据库中没有找到Bean * @异常 javax.ejb.EJBException * 通讯或系统错误 */ public void ejbLoad() { log("ejbLoad: (" + id() + ")"); //声明数据库连接对象 Connection con = null; //声明SQL命令预处理对象 PreparedStatement ps = null; //找到账号主键 accountId = (String) ctx.getPrimaryKey();
try { //获取数据库连接 con = getConnection(); //设置SQL命令,读取记录 ps = con.prepareStatement("select bal from ejbAccounts where id = ?"); //设置SQL命令 ps.setString(1, accountId); //执行SQL ps.executeQuery(); //获取SQL结果 ResultSet rs = ps.getResultSet(); if (rs.next()) { //取得数据 balance = rs.getDouble(1); } else { String error = "ejbLoad: AccountBean (" + accountId + ") not found"; log(error); throw new NoSuchEntityException (error); } } catch (SQLException sqe) { //数据库异常处理 log("SQLException: " + sqe); throw new EJBException(sqe); } finally { cleanup(con, ps); } }
/** * 数据库中存入EJBean * * @异常 javax.ejb.NoSuchEntityException * 如果在数据库中没有找到Bean * @异常 javax.ejb.EJBException * 通讯或系统错误 */ public void ejbStore() { log("ejbStore (" + id() + ")"); //声明数据库连接对象 Connection con = null; //声明SQL命令预处理对象 PreparedStatement ps = null;
try { //获取数据库连接 con = getConnection(); //设置SQL命令,更新数据库 ps = con.prepareStatement("update ejbAccounts set bal = ? where id = ?"); //设置SQL命令 ps.setDouble(1, balance); ps.setString(2, accountId); //执行SQL if (!(ps.executeUpdate() > 0)) { String error = "ejbStore: AccountBean (" + accountId + ") not updated"; log(error); throw new NoSuchEntityException (error); } } catch(SQLException sqe) { ///数据库次操作异常处理 log("SQLException: " + sqe); throw new EJBException (sqe); } finally { cleanup(con, ps); } }
/** * 这个方法和"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错误时抛出的异常 */ public String ejbCreate(String accountId, double initialBalance) throws CreateException { //日志信息 log("AccountBean.ejbCreate( id = accountId" + ", " + "initial balance = $ " + initialBalance + ")"); this.accountId = accountId; this.balance = initialBalance; //声明数据库连接 Connection con = null; PreparedStatement ps = null;
try { //获取数据库连接 con = getConnection(); //执行sql语句,插入记录 ps = con.prepareStatement("insert into ejbAccounts (id, bal) values (?, ?)"); ps.setString(1, accountId); ps.setDouble(2, balance); if (ps.executeUpdate() != 1) { String error = "JDBC did not create any row"; log(error); throw new CreateException (error); }
return accountId; } catch (SQLException sqe) { //异常处理 try { //查找主键 ejbFindByPrimaryKey(accountId); } catch(ObjectNotFoundException onfe) { String error = "SQLException: " + sqe; log(error); throw new CreateException (error); } String error = "An Account already exists in the database with Primary Key " + accountId; log(error); throw new DuplicateKeyException(error); } finally { cleanup(con, ps); } }
/** * 这是本类必须实现的方法,在本例中没有用到 */ public void ejbPostCreate(String accountId, double initialBalance) { log("ejbPostCreate (" + id() + ")"); }
/** * 从数据库中删除EJBean * * @异常 javax.ejb.NoSuchEntityException * 如果数据库中没找到这个ejb * @异常 javax.ejb.EJBException * 通信错误抛出的异常 */ public void ejbRemove() { log("ejbRemove (" + id() + ")"); //声明数据库连接 Connection con = null; PreparedStatement ps = null;
try { //获取连接 con = getConnection(); //获取主键 accountId = (String) ctx.getPrimaryKey(); //执行SQL语句,删除记录 ps = con.prepareStatement("delete from ejbAccounts where id = ?"); ps.setString(1, accountId); if (!(ps.executeUpdate() > 0)) { String error = "AccountBean (" + accountId + " not found"; log(error); throw new NoSuchEntityException (error); } } catch (SQLException sqe) { //异常处理 log("SQLException: " + sqe); throw new EJBException (sqe); } finally { //清除 cleanup(con, ps); } }
/** * 给定主键查找EJBean * * @参数 pk String 主键 * @返回 String 主键 * @异常 javax.ejb.ObjectNotFoundException * EJBean没发现抛出的异常 * @异常 javax.ejb.EJBException * if there is a communications or systems failure */ public String ejbFindByPrimaryKey(String pk) throws ObjectNotFoundException { log("ejbFindByPrimaryKey (" + pk + ")"); //声明数据库连接 Connection con = null; PreparedStatement ps = null;
try { //获取连接 con = getConnection(); //查询主键对应的记录 ps = con.prepareStatement("select bal from ejbAccounts where id = ?"); ps.setString(1, pk); ps.executeQuery(); //获取结果集 ResultSet rs = ps.getResultSet(); if (rs.next()) { balance = rs.getDouble(1); } else { //没有发现这个主键值的ejb String error = "ejbFindByPrimaryKey: AccountBean (" + pk + ") not found"; log(error); //抛出异常 throw new ObjectNotFoundException (error); } } catch (SQLException sqe) { //异常处理 log("SQLException: " + sqe); throw new EJBException (sqe); } finally { //清除 cleanup(con, ps); }
log("ejbFindByPrimaryKey (" + pk + ") found"); return pk; }
/** * 查找所有结算大于给定值的EJBeans * 返回主键枚举 * * @参数 balanceGreaterThan double Test Amount * @返回 主键枚举 * @异常 javax.ejb.EJBException * 通信错误抛出的异常 */ public Enumeration ejbFindBigAccounts(double balanceGreaterThan) { log("ejbFindBigAccounts (balance > " + balanceGreaterThan + ")"); //声明数据库连接 Connection con = null; PreparedStatement ps = null;
try { //获取连接 con = getConnection(); ps = con.prepareStatement("select id from ejbAccounts where bal > ?"); ps.setDouble(1, balanceGreaterThan); ps.executeQuery(); //获取结果集 ResultSet rs = ps.getResultSet(); Vector v = new Vector(); String pk; while (rs.next()) { pk = rs.getString(1); v.addElement(pk); } //返回枚举 return v.elements(); } catch (SQLException sqe) { //异常处理 log("SQLException: " + sqe); throw new EJBException (sqe); } finally { //清除 cleanup(con, ps); } }
/** * 存入一定数量 * * @参数 amount double Amount * @返回 double 结算 */ public double deposit(double amount) { log("Depositing $" + amount + " into ’" + accountId + "’"); balance += amount; return balance; }
/** * 提取 * * @参数 amount double 数量 * @返回 double 结算 * @异常 ProcessingErrorException * 如果数量大于结算 */ public double withdraw(double amount) throws ProcessingErrorException { log("Withdrawing $" + amount + " from ’" + accountId + "’"); if (amount > balance) { String error = "Request to withdraw $" + amount + " more than balance " + balance + " in account " + accountId; log(error); throw new ProcessingErrorException(error); }
balance -= amount; return balance; }
/** * 返回当前结算值 * * @返回 double 结算 */ public double balance() { return balance; }
/** * 从连接池中获取当前连接 * * @返回 连接 * @异常 javax.ejb.EJBException * 通信错误 */ private Connection getConnection() throws SQLException { //声明初始化上下文 InitialContext initCtx = null; try { initCtx = new InitialContext(); //查找数据源 DataSource ds = (javax.sql.DataSource) initCtx.lookup("java:comp/env/jdbc/demoPool"); //返回数据源连接 return ds.getConnection(); } catch(NamingException ne) { //有异常 log("UNABLE to get a connection from demoPool!"); log("Please make sure that you have setup the connection pool properly"); throw new EJBException(ne); } finally { try { if(initCtx != null) initCtx.close(); } catch(NamingException ne) { log("Error closing context: " + ne); throw new EJBException(ne); } } }
// 也可以使用WebLogic的日志服务 private void log(String s) { if (VERBOSE) System.out.println(s); }
// 返回这个beans的id private String id() { return "PK = " + (String) ctx.getPrimaryKey(); } //清除 private void cleanup(Connection con, PreparedStatement ps) { try { if (ps != null) ps.close(); } catch (Exception e) { log("Error closing PreparedStatement: "+e); throw new EJBException (e); }
try { if (con != null) con.close(); } catch (Exception e) { log("Error closing Connection: " + e); throw new EJBException (e);
} } }
4.编写处理异常程序
编辑文件ProcessingErrorException.java并保存到C:\work\src\examples\ejb\basic\beanManaged目录下(或从附带光盘的src\examples\ejb\basic\beanManaged目录拷贝),其源文件如下:
//ProcessingErrorException.java //定义本类在包examples.ejb.basic.beanManaged 中 package examples.ejb.basic.beanManaged;
/** * 这是用户定义的异常类 */ //用户定义的异常类必须继承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\beanManaged目录下(或从附带光盘的src\examples\ejb\basic\beanManaged目录拷贝),其源文件如下:
//Client.java //定义本类在包examples.ejb.basic.beanManaged 中 package examples.ejb.basic.beanManaged; //本类用到的其他类 import java.rmi.RemoteException; import java.util.Enumeration; import java.util.Properties; import java.util.Vector; //本类用到的EJB类 import javax.ejb.CreateException; import javax.ejb.EJBException; 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,并进行如下操作: */
public class Client { //声明变量 private String url;
private AccountHome home; //构造方法 public Client(String url) throws NamingException {
this.url = url; //查找主接口,lookupHome是本例自定义方法。 home = lookupHome(); }
/** * 在命令行运行这个实例: * java examples.ejb.basic.beanManaged.Client "t3://localhost:7001" * 参数是可选的 * @参数 url URL such as "t3://localhost:7001" of Server */ public static void main(String[] args) throws NamingException { System.out.println("\nBeginning beanManaged.Client...\n");
String url = "t3://localhost:7001";
// 解析命令行参数 if (args.length != 1) { System.out.println("Usage: java examples.ejb.basic.beanManaged.Client t3://hostname:port"); return; } else { url = args[0]; }
Client client = null;
try { //实例化本类 client = new Client(url); } catch (NamingException ne) { //异常处理 log("Unable to look up the beans home: " + ne.getMessage()); System.exit(1); }
try { //运行实例 client.example();
} 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 beanManaged.Client...\n"); } /** * 执行实例 * */ public void example() throws CreateException, RemoteException, FinderException, RemoveException {
int numBeans = 20; //声明并创建账号数组 Account [] accounts = new Account [numBeans];
// 创建20个账号 for (int i=0; i<numBeans; i++) { accounts [i] = findOrCreateAccount("ID: "+i, i * 1000); }
// 打印账号结算 for (int i=0; i<numBeans; i++) { log("Account: :"+accounts[i].getPrimaryKey()+ " has a balance of "+accounts[i].balance()); }
// 查找所有结算大于5000的账号 findBigAccounts(5000.0);
// 清除所有账号
log("Removing beans..."); for (int i=0; i<numBeans; i++) { accounts[i].remove(); } }
/** * 列出所有结算大于给定值的账号 * 这个finder方法演示返回枚举账号 */ private void findBigAccounts(double balanceGreaterThan) throws RemoteException, FinderException { log("\nQuerying for accounts with a balance greater than " + balanceGreaterThan + "..."); //调用主接口创建账号方法findBigAccounts,返回账号枚举 Enumeration enum = home.findBigAccounts(balanceGreaterThan);
if(! enum.hasMoreElements()) { log("No accounts were found!"); }
while (enum.hasMoreElements()) { //创建远程对象 Account bigAccount= (Account) PortableRemoteObject.narrow(enum.nextElement(), Account.class);
log("Account " + bigAccount.getPrimaryKey() + "; balance is $" + bigAccount.balance()); } }
/** * 如果对应id的账号以存在,则返回这个id,否则创建它 */ private Account findOrCreateAccount(String id, double balance) throws CreateException, RemoteException, FinderException { try { log("Trying to find account with id: "+id); return (Account) PortableRemoteObject.narrow(home.findByPrimaryKey(id), Account.class); } catch (ObjectNotFoundException onfe) { // 账号不存在,创建它 return (Account) PortableRemoteObject.narrow(home.create(id, balance), Account.class); } }
/** * 给定id和结算创建一个新的账号 */ private Account createAccount(String id, double balance) throws CreateException, RemoteException { log("Creating account " + id + " with a balance of " + balance + "..."); //创建远程账号对象 Account ac = (Account) PortableRemoteObject.narrow(home.create(id, balance), Account.class); log("Account " + id + " successfully created");
return ac; }
/** * 使用JNDI查找bean的主接口 */ private AccountHome lookupHome() throws NamingException { Context ctx = getInitialContext();
try { //查找主接口 Object home = ctx.lookup("beanManaged.AccountHome"); return (AccountHome) PortableRemoteObject.narrow(home, AccountHome.class);
} catch (NamingException ne) { //异常处理 log("The client was unable to lookup the EJBHome. Please make sure " + "that you have deployed the ejb with the JNDI name " + "beanManaged.AccountHome on the WebLogic server at "+url);
throw ne; } }
/** * 获取初始化上下文 */ private Context getInitialContext() throws NamingException {
try { // 设置属性对象 Properties h = new Properties(); h.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); h.put(Context.PROVIDER_URL, url); return new InitialContext(h); } catch (NamingException ne) { //异常处理 log("We were unable to get a connection to the WebLogic server at "+url); log("Please make sure that the server is running."); throw ne; } } //控制台输出 private static void log(String s) { System.out.println(s); } }
6.客户端程序
编辑文件Servlet.java并保存到C:\work\src\examples\ejb\basic\beanManaged目录下(或从附带光盘的src\examples\ejb\basic\beanManaged目录拷贝),其源文件如下:
//Servlet.java
//定义本接口在包examples.ejb.basic.beanManaged package examples.ejb.basic.beanManaged; //本类用到的其他类。javax.ejb.*是开发EJB应用需要的类库。javax.naming.*是实现JNDI服务需要的类库 import java.io.IOException; import java.io.OutputStream; import java.rmi.RemoteException; import java.util.Enumeration; import java.util.Properties; import java.util.Vector;
import javax.naming.Context; import javax.naming.InitialContext; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import weblogic.html.BreakElement; import weblogic.html.HeadingElement; import weblogic.html.ServletPage; import weblogic.html.StringElement;
/** * 这个servlet和Client类类似 * 这个servlet必须在web.xml文件中注册 * 使用url http://localhost:7001/examplesWebApp/beanManaged调用这个servlet */ public class Servlet extends HttpServlet {
static String accountId = "10020";
/** * 查找beanManaged主接口 * 创建beans并调用远程接口中定义的方法 * * @参数 req HttpServletRequest * @参数 res HttpServletResponse * @异常 java.io.IOException * 如果IO错误 */ public void service(HttpServletRequest req, HttpServletResponse res) throws IOException { //设置文档类型 res.setContentType("text/html"); OutputStream out = res.getOutputStream(); String title = "EJBean Bean-managed Persistence Servlet"; //ServletPage实例 ServletPage sp = new ServletPage(title); //编辑html元素 sp.getBody() .addElement(new HeadingElement(title, 1)); printElement("", sp);
// 获取参数 // "http://localhost:7001/beanManaged?user=foobar&password=FooBarNone" //用户名 String user = req.getParameter("user"); //密码 String password = req.getParameter("password");
if(user!=null && password!=null){ printElement("Using user <b>" + user + "</b> and password <b> " + password + "</b>", sp); printElement("", sp); } else { printElement("No user and password credentials", sp); printElement("", sp); }
double amount = 100; double balance = 3000; Vector v = new Vector();
try { // 获取上下文 Context ctx = getInitialContext(); //查找主接口 AccountHome home = (AccountHome) ctx.lookup("beanManaged.AccountHome");
// 查找Account或创建它 Account ac = null; try { printElement("Looking up account " + accountId + "...", sp); ac = (Account) home.findByPrimaryKey(accountId); } catch (Exception ee) { //异常处理 printElement("Did not find " + accountId, sp); }
if (ac == null) { printElement("Account " + accountId + " being created; opening balance is $" + balance, sp); //创建远程对象 ac = home.create(accountId, balance); } else { printElement("Account " + accountId + " found; balance is $" + ac.balance(), sp); } printElement("", sp);
// A部分: 存入和提取大于当前结算的金额,会抛出用户定义的异常
printElement("Part A: Depositing $" + amount, sp); //存入 balance = ac.deposit(amount); printElement("Current balance is $" + balance, sp); printElement("", sp);
amount = balance + 10; try { printElement("Withdrawing amount greater than current balance. Expecting an exception...", sp); //提取 balance = ac.withdraw(amount); printElement("Error: expected an exception.", sp); } catch (ProcessingErrorException pe) { //用户定义的异常 printElement("Received expected Processing Error:<br>" + pe, sp); } printElement("", sp);
// B部分: 创建一些新的用户,并给定不同的初始结算 // 查找结算大于给定值的所有账号 // 最后,删除所有新的账号
int numAccounts = 5; printElement("Part B: Creating " + numAccounts + " new accounts...", sp); long now = System.currentTimeMillis(); for (int i = 0; i < numAccounts; i++) { String id = "" + now + i; // 唯一的账号id balance = i*100; // 初始结算 v.addElement(home.create(id, balance)); printElement("Created account: " + id + "; balance is $" + balance, sp); } printElement("", sp);
if (v.size() == numAccounts) { printElement("" + numAccounts + " accounts successfully created", sp); } else { printElement("Error: Only " + v.size() + " accounts were created successfully", sp); } printElement("", sp);
double balanceGreaterThan = 200; printElement("Querying for accounts with a balance greater than " + balanceGreaterThan + "...", sp); //调用主接口的方法 Enumeration e = home.findBigAccounts(balanceGreaterThan); if (e != null) { while (e.hasMoreElements()) { //每个账号 Account bigAccount= (Account) e.nextElement(); //打印每个账号的主键 printElement("Account " + bigAccount.getPrimaryKey() + "; balance is $" + bigAccount.balance(), sp); Thread.sleep(1000); } } printElement("", sp);
printElement("Removing accounts just created...", sp); //清除所有账号 for (int i = 0; i < numAccounts; i++) { String id = "" + now + i; ((Account)(v.elementAt(i))).remove(); printElement("Removed account: " +id, sp); } printElement("", sp);
// 捕获异常 } catch (ProcessingErrorException pe) { printElement("Unexpected Processing Error: " + pe, sp); } catch (Exception e) { //其它异常 printElement(":::::::::::::: Unexpected Error :::::::::::::::::", sp); e.printStackTrace(); } finally { printElement("End beanManaged.Servlet...", sp); }
sp.output(out); out.flush(); }
/** * 基本的servlet信息 */ public String getServletInfo() { return "EJBean Servlet"; }
/** * 打印一个bean的HTML信息 */ static private void printAccount(Account account, ServletPage sp) throws RemoteException, IOException { printElement("Account " + account.getPrimaryKey() + "; balance is $" + account.balance(), sp); }
/** * 打印消息给浏览器 */ static private void printElement(String message, ServletPage sp) throws IOException { sp.getBody() .addElement(new BreakElement()) .addElement(new StringElement(message)); }
/** * 获取当前用户、密码和url的初始化上下文。 * * @return 上下文 * @异常 java.lang.Exception if there is * an error in getting the Context */ static public Context getInitialContext() throws Exception { Properties p = new Properties(); p.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); return new InitialContext(p); } }
7.编写ejb描述文件
编辑文件ejb-jar.Xml并保存到C:\work\src\examples\ejb\basic\beanManaged目录下(或从附带光盘的src\examples\ejb\basic\beanManaged目录拷贝),其源文件如下:
<?xml version="1.0"?>
<!DOCTYPE ejb-jar PUBLIC ’-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN’ ’http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd’>
<ejb-jar> <enterprise-beans> <entity> <ejb-name>beanManaged</ejb-name> <home>examples.ejb.basic.beanManaged.AccountHome</home> <remote>examples.ejb.basic.beanManaged.Account</remote> <ejb-class>examples.ejb.basic.beanManaged.AccountBean</ejb-class> <persistence-type>Bean</persistence-type> <prim-key-class>java.lang.String</prim-key-class> <reentrant>False</reentrant>
<resource-ref> <res-ref-name>jdbc/demoPool</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
</entity> </enterprise-beans> <assembly-descriptor> <container-transaction> <method> <ejb-name>beanManaged</ejb-name> <method-intf>Remote</method-intf> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> </assembly-descriptor> </ejb-jar>
8.编写ejb部署文件
编辑文件weblogic-ejb-jar.xml并保存到C:\work\src\examples\ejb\basic\beanManaged目录下(或从附带光盘的src\examples\ejb\basic\beanManaged目录拷贝),其源文件如下:
<?xml version="1.0"?>
<!DOCTYPE weblogic-ejb-jar PUBLIC ’-//BEA Systems, Inc.//DTD WebLogic 5.1.0 EJB//EN’ ’http://www.bea.com/servers/wls510/dtd/weblogic-ejb-jar.dtd’>
<weblogic-ejb-jar> <weblogic-enterprise-bean> <ejb-name>beanManaged</ejb-name> <caching-descriptor> <max-beans-in-cache>100</max-beans-in-cache> </caching-descriptor> <reference-descriptor>
<resource-description> <res-ref-name> jdbc/demoPool </res-ref-name> <jndi-name> examples-dataSource-demoPool </jndi-name> </resource-description>
</reference-descriptor>
<jndi-name>beanManaged.AccountHome</jndi-name> </weblogic-enterprise-bean> </weblogic-ejb-jar>
5.4.2 编译
(1)打开命令窗口,进入C:\work\src\examples\ejb\basic\beanManaged目录。 (2)运行设置环境变量命令脚本setEnv.cmd: c:\work\src\examples\ejb\basic\beanManaed>c:\work\setEnv setEnv.cmd在附带光盘的work目录下,可以直接把它拷贝到C:\work\目录。 (3)运行编译脚本build.cmd: c:\work\src\examples\ejb\basic\beanManaed>bukld 其中build.cmd代码如下:
@REM Copyright (c) 2000 BEA Systems, Inc. All Rights Reserved. @REM You must set your environment by running the setExamplesEnv shell script @REM prior to executing this script.
@REM Create the build directory, and copy the deployment descriptors into it mkdir build build\META-INF copy *.xml build\META-INF
@REM Compile EJB classes into the build directory (jar preparation) javac -d build Account.java AccountHome.java ProcessingErrorException.java AccountBean.java
@REM Make a EJB jar file, including XML deployment descriptors cd build jar cv0f std_ejb_basic_beanManaged.jar META-INF examples cd ..
@REM Run EJBC on jar file java -classpath %WL_HOME%/lib/weblogic_sp.jar;%WL_HOME%/lib/weblogic.jar weblogic.ejbc -compiler javac build\std_ejb_basic_beanManaged.jar %WL_HOME%\config\%DOMAIN_NAME%\applications\ejb_basic_beanManaged.jar
@REM Compile servlets and EJB interfaces into WEB-INF/classes directory of the Examples Web App @REM This ensures that the EJB can be accessed by JSPs and servlets of the Examples Web App javac -d %EX_WEBAPP_CLASSES% Servlet.java Account.java AccountHome.java ProcessingErrorException.java
@REM Compile EJB interfaces & client app into the clientclasses directory javac -d %CLIENT_CLASSES% Account.java AccountHome.java ProcessingErrorException.java Client.java
5.4.3 定义数据源
本示例使用数据源examples-dataSource-demoPool和连接池demoPool。前面已经定义了连接池demoPool,本节演示如何通过系统管理工具Console定义连接池demoPool的数据源。 (1)启动WebLogic服务 (2)启动系统管理控制台程序console(在浏览器URL中输入http://127.0.0.1:7001/console/,回车)。 (3)点出console控制台左面板的Services/JDBC/Data Sources,如图5-8所示。 (4)接下来是一个主要的步骤,点击控制台右面板的“Create a new JDBC ConnectionPool...”,创建新的连接池。进入图5-9的操作界面。定义新数据源名称“Name:”为“examples-dataSource-demoPool”,定义连接池名称“Pool Name:”为“demoPool”,然后点击“Create”创建。 (5)下面有一个重要的步骤,那就是创建完数据源后,还要把它部署到系统管理的服务器myserve中点击图5-9的Targets页,在Available栏中选中myserver,点击向右的箭头,点击“Apply”。如图6-10所示。
1.修改启动脚本
本示例使用WebLogic Server 6.0自带的小型关系数据库cloudscape。因此在WebLogic Server启动的时候,要对启动脚本文件startWebLogic.cmd进行修改。如果还没有修改,则参见上一个实例。
2.配置Servlet
本示例客户端测试程序除了Client.java之外,还提供了一个Servlet程序,它和Client具有一样的功能,以Servlet应用的方式使用。使用Sevlet前要进行注册。Servlet程序的注册信息都放在web.xml文件中。 要注册Servlet首先要编辑C:\bea\wlserver6.0\config\mydomain\applications\DefaultWebApp_myserver\WEB-INF路径下的web.xml文件。
<?xml version="1.0" ?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 1.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app> ... <!--chapter 6 -->
<servlet> <servlet-name>beanManaged</servlet-name> <servlet-class>examples.ejb.basic.beanManaged.Servlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>beanManaged</servlet-name> <url-pattern>/beanManaged*</url-pattern> </servlet-mapping> ... </web-app> 其中虚线表示在web.xml中注册的其它Servlets。 编辑完web.xml要重新启动服务器以使其生效。
3.运行测试
(1)测试Client 运行测试程序。继续使用前几个步骤使用的命令窗口,执行: C:\work\src\examples\ejb\basic\beanManaged>java examples.ejb.basic.beanManaged.Client t3://127.0.0.1:7001/ 观察命令窗口的运行情况,如图5-11所示。
(2)测试Servlet 打开浏览器,在地址栏中输入http://127.0.0.1:7001/beanManage,回车。会出现如图5-12所示的页面。
|
|
|
| |
 |
热门院校推荐 |
 |
|
|
|
|
|
|
 |
| |
| |
| |
|
|
|