package examples.ejb.extensions.isModifiedBeanManaged; import java.io.Serializable; import java.rmi.RemoteException; import javax.ejb.*; import java.util.*; import java.sql.*; /** * AccountBean is an EntityBean. This EJBean illustrates: * * * @author Copyright (c) 1998 by WebLogic, Inc. All Rights Reserved. * @author Copyright (c) 1998-1999 by BEA WebXpress. All Rights Reserved. */ public class AccountBean implements EntityBean { final static boolean VERBOSE = true; // ----------------------------------------------------------------- // private variables private transient EntityContext ctx; // ----------------------------------------------------------------- // public bean-managed variables public String accountId; // also the primary Key public double balance; private transient boolean isDirty; // "dirty" flag // ----------------------------------------------------------------- // EntityBean implementation /** * Returns whether the EJBean has been modified or not. * * @return boolean isDirty */ public boolean isModified() { if (VERBOSE) System.out.println ("isModified(): isDirty = " + (isDirty ? "true" : "false")); return isDirty; } /** * Sets the EJBean as modified. * * @param flag boolean Flag */ public void setModified(boolean flag) { isDirty = flag; if (VERBOSE) System.out.println("setModified(): " + id() + (String) (flag ? ": requires saving" : ": saving not required")); } /** * Returns the Primary Key identifying this EJBean. * * @return String Identification */ private String id() { return "" + System.identityHashCode(this) + ", PK = " + (String) ((ctx == null) ? "nullctx" : ((ctx.getPrimaryKey() == null ? "null" : ctx.getPrimaryKey().toString()))); } /** * Forces reload of EJBean by setting modified flag true. * */ public void ejbActivate() { if (VERBOSE) System.out.println("ejbActivate(): " + id()); setModified(true); // to force writing in ejbStore } /** * Sets the EntityContext for the EJBean. * * @param ctx EntityContext */ public void setEntityContext(EntityContext ctx) { if (VERBOSE) System.out.println("setEntityContext(): " + id()); this.ctx = ctx; setModified(true); // to force writing in ejbStore } /** * Unsets the EntityContext for the EJBean. * */ public void unsetEntityContext() { if (VERBOSE) System.out.println("unsetEntityContext(): " + id()); this.ctx = null; } /** * Sets the dirty flag when the EJBean is passivated. * */ public void ejbPassivate() { if (VERBOSE) System.out.println("ejbPassivate(): " + id()); setModified(true); // to force writing in ejbStore }; /** * Refreshes the EJBean from the persistent storage. * * @exception java.rmi.RemoteException * if there is a communications or systems failure */ public void ejbLoad() throws RemoteException { if (VERBOSE) System.out.println("ejbLoad: (" + id() + ")"); try { refresh((AccountPK) ctx.getPrimaryKey()); } catch (FinderException fe) { throw new RemoteException (fe.getMessage()); } } /** * Given a Primary Key, refreshes the EJBean from * the persistent storage. * * @param pk AccountPK Primary Key * @return AccountPK Primary Key * @exception javax.ejb.FinderException * thrown if the EJBean cannot be found */ public AccountPK ejbFindByPrimaryKey(AccountPK pk) throws FinderException { if (VERBOSE) System.out.println("ejbFindByPrimaryKey(): " + id()); if ((pk == null) || (pk.accountId == null)) throw new FinderException ("primary key cannot be null"); if (VERBOSE) System.out.println("ejbFindByPrimaryKey(): " + pk.accountId + ")"); refresh(pk); if (VERBOSE) System.out.println("ejbFindByPrimaryKey(): " + pk.accountId + ") found"); return pk; } /** * Refreshes the EJBean corresponding to the primary key * from the persistent storage. * * @param pk AccountPK Primary Key * @exception javax.ejb.FinderException * thrown if the EJBean cannot be found */ private void refresh(AccountPK pk) throws FinderException { if (VERBOSE) System.out.println("refresh(): " + id()); if (pk == null) { throw new FinderException ("primary key cannot be null"); } if (VERBOSE) System.out.println("About to refresh (" + id() + ")"); Connection con = null; PreparedStatement ps = null; try { con = getConnection(); ps = con.prepareStatement("select bal from ejbAccounts where id = ?"); ps.setString(1, pk.accountId); ps.executeQuery(); ResultSet rs = ps.getResultSet(); if (rs.next()) { accountId = pk.accountId; balance = rs.getDouble(1); } else { throw new FinderException ("Refresh: AccountBean (" + pk.accountId + ") not found"); } setModified(false); // to avoid writing if (VERBOSE) System.out.println("Refreshed (" + id() + ")"); } catch (SQLException sqe) { throw new FinderException(sqe.getMessage()); } finally { try { ps.close(); con.close(); } catch (Exception e) { throw new FinderException (e.getMessage()); } } } /** * Stores the EJBean in the persistent storage * if it has been modified. * * @exception java.rmi.RemoteException * if there is a communications or systems failure */ public void ejbStore() throws RemoteException { if (VERBOSE) System.out.println("ejbStore(): " + id()); if (!isModified()) return; Connection con = null; PreparedStatement ps = null; try { con = getConnection(); ps = con.prepareStatement("update ejbAccounts set bal = ? where id = ?"); ps.setDouble(1, balance); ps.setString(2, accountId); int i = ps.executeUpdate(); if (i == 0) { throw new RemoteException ("ejbStore: AccountBean (" + accountId + ") not updated"); } setModified(false); // to avoid writing } catch (RemoteException re) { throw re; } catch (SQLException sqe) { throw new RemoteException (sqe.getMessage()); } finally { try { ps.close(); con.close(); } catch (Exception ignore) {} } } /** * Deletes the EJBean from the persistent storage. * * @exception javax.ejb.RemoveException * if the EJBean does not allow removing the EJBean * @exception java.rmi.RemoteException * if there is a communications or systems failure */ public void ejbRemove() throws RemoveException, RemoteException { if (VERBOSE) System.out.println("ejbRemove(): " + id()); // we need to get the primary key from the context because // it is possible to do a remove right after a find, and // ejbLoad may not have been called. Connection con = null; PreparedStatement ps = null; try { con = getConnection(); AccountPK pk = (AccountPK) ctx.getPrimaryKey(); ps= con.prepareStatement("delete from ejbAccounts where id = ?"); ps.setString(1, pk.accountId); int i = ps.executeUpdate(); if (i == 0) { throw new RemoteException ("AccountBean (" + pk.accountId + " not found"); } setModified(true); // to force writing in ejbStore } catch (RemoteException re) { throw re; } catch (SQLException sqe) { throw new RemoteException (sqe.getMessage()); } finally { try { ps.close(); con.close(); } catch (Exception ignore) {} } } /** * This method corresponds to the create method in the home interface * "AccountHome.java". * The parameter sets of the two methods are identical. When the client calls * AccountHome.create(), the container (which in WebLogic EJB is * also the home) allocates an instance of this bean and * calls AccountBean.ejbCreate(). *

* For bean-managed persistence, ejbCreate() returns * a primary key, unlike the case of container-managed * persistence, where it returns a void. * * @param accountID String Account ID * @param initialBalance double Initial Balance * @return AccountPK * @exception javax.ejb.CreateException * if there is a problem creating the bean * @exception java.rmi.RemoteException * if there is a communications or systems failure */ public AccountPK ejbCreate(String accountId, double initialBalance) throws CreateException, RemoteException { if (VERBOSE) System.out.println("AccountBean.ejbCreate( id = " + System.identityHashCode(this) + ", PK = " + accountId + ", " + "initial balance = $ " + initialBalance + ")"); this.accountId = accountId; this.balance = initialBalance; Connection con = null; PreparedStatement ps = null;; try { con = getConnection(); ps = con.prepareStatement("insert into ejbAccounts (id, bal) values (?, ?)"); ps.setString(1, accountId); ps.setDouble(2, balance); if (ps.executeUpdate() != 1) { throw new CreateException ("JDBC did not create any row"); } AccountPK primaryKey = new AccountPK(); primaryKey.accountId = accountId; return primaryKey; } catch (CreateException ce) { throw ce; } catch (SQLException sqe) { throw new CreateException (sqe.getMessage()); } finally { try { ps.close(); con.close(); } catch (Exception e) { throw new RemoteException (e.getMessage()); } } } /** * Sets the EJBean's modified flag to false. * * @param accountID String Account Identification * @param initialBalance double Initial Balance */ public void ejbPostCreate(String accountId, double initialBalance) { if (VERBOSE) System.out.println("ejbPostCreate(): " + id()); setModified(false); // to avoid writing } // Application defined methods /** * Finds all EJBeans with a balance greater than a given amount. * Returns an Enumeration of found EJBean primary keys. * * @param balanceGreaterThan double Test Amount * @return Enumeration EJBean Primary Keys * @exception javax.ejb.FinderException * if an error occurs while accessing * the persistent storage * @exception java.rmi.RemoteException * if there is a communications or systems failure */ public Enumeration ejbFindBigAccounts(double balanceGreaterThan) throws FinderException, RemoteException { if (VERBOSE) System.out.println("ejbFindBigAccounts (balance > " + balanceGreaterThan + ")"); Connection con = null; PreparedStatement ps = null; ResultSet rs = null; try { con = getConnection(); ps = con.prepareStatement("select id, bal from ejbAccounts where bal > ?"); ps.setDouble(1, balanceGreaterThan); ps.executeQuery(); rs = ps.getResultSet(); Vector v = new Vector(); AccountPK pk; while (rs.next()) { pk = new AccountPK(); pk.accountId = rs.getString(1); v.addElement(pk); } rs.close(); return v.elements(); } catch (SQLException sqe) { throw new FinderException(sqe.getMessage()); } finally { try { if (rs != null) rs.close(); if (ps != null) ps.close(); if (con!= null) con.close(); } catch (Exception e) { throw new RemoteException(e.getMessage()); } } } /** * Adds amount to balance. * * @param amount double Amount * @return double balance * @exception ProcessingErrorException * if there is an error making a deposit */ public double deposit(double amount) throws ProcessingErrorException { if (VERBOSE) System.out.println("deposit(): Depositing $" + amount + " into '" + accountId + "'"); balance += amount; setModified(true); // to force writing in ejbStore return balance; } /** * Subtracts amount from balance. * * @param amount double Amount * @return double Balance * @exception ProcessingErrorException * if Amount > Balance. */ public double withdraw(double amount) throws ProcessingErrorException { if (VERBOSE) System.out.println("withdraw(): Withdrawing $" + amount + " from '" + accountId + "'"); if (amount > balance) { throw new ProcessingErrorException("Request to withdraw $" + amount + " more than balance " + balance + " in account " + accountId); } balance -= amount; setModified(true); // to force writing in ejbStore return balance; } /** * Returns current balance. * * @return double Balance */ public double balance() { if (VERBOSE) System.out.println("balance(): balance $" + balance); return balance; } /** * Forces static initialization of weblogic.jdbc.jts.Driver * */ static { new weblogic.jdbc.jts.Driver(); // force static initialization } /** * Gets current connection to the connection pool. * * @return Connection * @exception java.sql.SQLException * if there is an error getting a Connection */ private Connection getConnection() throws SQLException { return DriverManager.getConnection("jdbc:weblogic:jts:demoPool"); } }