package examples.ejb.extensions.finderEnumeration;
// FIXME mshinn@weblogic.com 2000-Mar-13 -- We may be able to axe some of these
// imports if we can axe code below.
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;
import weblogic.ejb.pstore.FindEnumeration;
import weblogic.ejb.pstore.KeyValuePairImpl;
// FIXME mshinn@weblogic.com 2000-Mar-13 -- Modify comments
/**
* AccountBean is an EntityBean. This EJBean illustrates:
* <ul>
* <li> EJBean-managed persistence and transactions;
* the code in this file directly accesses the data storage.
* <li> Application-defined exceptions.
* </ul>
*
* @author Copyright (c) 1998 by WebLogic, Inc. All Rights Reserved.
* @author Copyright (c) 1998-1999 by BEA Systems, Inc. All Rights Reserved.
*/
public class AccountBean implements EntityBean {
final static private boolean VERBOSE = true;
private EntityContext ctx;
private String accountId; // also the primary Key
private double balance;
/**
* Sets the EntityContext for the EJBean.
*
* @param ctx EntityContext
*/
public void setEntityContext(EntityContext ctx) {
log("setEntityContext called");
this.ctx = ctx;
}
/**
* Unsets the EntityContext for the EJBean.
*/
public void unsetEntityContext() {
log("unsetEntityContext (" + id() + ")");
this.ctx = null;
}
/**
* Required by the EJB specification, this method is not used
* by this example.
*/
public void ejbActivate() {
log("ejbActivate (" + id() + ")");
}
/**
* This method is required by the EJB Specification,
* but is not used by this example.
*/
public void ejbPassivate() {
log("ejbPassivate (" + id() + ")");
}
/**
* Loads the EJBean from the persistent storage.
*
* @exception javax.ejb.NoSuchEntityException
* if the bean is not found in the database
* @exception javax.ejb.EJBException
* if there is a communications or systems failure
*/
public void ejbLoad() {
log("ejbLoad: (" + id() + ")");
Connection con = null;
PreparedStatement ps = null;
accountId = (String) ctx.getPrimaryKey();
try {
con = getConnection();
ps = con.prepareStatement("select bal from finderEnum where id = ?");
ps.setString(1, accountId);
ps.executeQuery();
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) {
String error = "SQLException: " + sqe.getMessage();
log(error);
throw new EJBException (error);
} finally {
cleanup(con, ps);
}
}
/**
* Stores the EJBean in the persistent storage.
*
* @exception javax.ejb.NoSuchEntityException
* if the bean is not found in the database
* @exception javax.ejb.EJBException
* if there is a communications or systems failure
*/
public void ejbStore() {
log("ejbStore (" + id() + ")");
Connection con = null;
PreparedStatement ps = null;
try {
con = getConnection();
ps = con.prepareStatement("update finderEnum set bal = ? where id = ?");
ps.setDouble(1, balance);
ps.setString(2, accountId);
if (!(ps.executeUpdate() > 0)) {
String error = "ejbStore: AccountBean (" + accountId + ") not updated";
log(error);
throw new NoSuchEntityException (error);
}
} catch(SQLException sqe) {
String error = "SQLException: " + sqe.getMessage();
log(error);
throw new EJBException (error);
} finally {
cleanup(con, ps);
}
}
/**
* 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
* <code>AccountHome.create()</code>, the container allocates an instance
* of this bean and calls <code>AccountBean.ejbCreate()</code>.
* <p>
* For bean-managed persistence, <code>ejbCreate()</code> 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 String Primary Key
* @exception javax.ejb.CreateException
* if there is a problem creating the bean
* @exception javax.ejb.DuplicateKeyException
* if a create is attempted using a Primary Key
* already in the database
* @exception javax.ejb.EJBException
* if there is a communications or systems failure
*/
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();
ps = con.prepareStatement("insert into finderEnum (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) {
// Check to see if this SQLException is due to a unique constraint
// violation on our database table (ie. there is already a pk with the
// value of accountId in the table). If so, throw a
// DuplicateKeyException else throw a CreateException.
try {
ejbFindByPrimaryKey(accountId);
} catch(ObjectNotFoundException onfe) {
String error = "SQLException: " + sqe.getMessage();
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);
}
}
/**
* Required by the EJB specification, this method is not used
* by this example.
*
* @param accountID String Account Identification
* @param initialBalance double Initial Balance
*/
public void ejbPostCreate(String accountId, double initialBalance) {
log("ejbPostCreate (" + id() + ")");
}
/**
* Deletes the EJBean from the persistent storage.
*
* @exception javax.ejb.NoSuchEntityException
* if the bean is not found in the database
* @exception javax.ejb.EJBException
* if there is a communications or systems failure
*/
public void ejbRemove() {
log("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();
accountId = (String) ctx.getPrimaryKey();
ps = con.prepareStatement("delete from finderEnum 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) {
String error = "SQLException: " + sqe.getMessage();
log(error);
throw new EJBException (error);
} finally {
cleanup(con, ps);
}
}
/**
* Attempts to find the EJBean with a given Primary Key from
* the persistent storage.
*
* @param pk String Primary Key
* @return String Primary Key
* @exception javax.ejb.ObjectNotFoundException
* thrown if the EJBean cannot be found
* @exception 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 finderEnum where id = ?");
ps.setString(1, pk);
ps.executeQuery();
ResultSet rs = ps.getResultSet();
if (rs.next()) {
balance = rs.getDouble(1);
} else {
String error = "ejbFindByPrimaryKey: AccountBean (" + pk + ") not found";
log(error);
throw new ObjectNotFoundException (error);
}
} catch (SQLException sqe) {
String error = "SQLException: " + sqe.getMessage();
log(error);
throw new EJBException (error);
} finally {
cleanup(con, ps);
}
log("ejbFindByPrimaryKey (" + pk + ") found");
return pk;
}
/**
* Finds all EJBeans with a balance equal to a given amount.
* Returns an Enumeration of found EJBean primary keys.
*
* @return Enumeration EJBean Primary Keys
* @param findBalance double Test Amount
* @exception javax.ejb.EJBException
* if there is a communications or systems failure
*/
public Enumeration ejbFindAccountsWithBalance(double findBalance) {
log("\nejbFindAccountsWithBalance (balance = " + findBalance + ")");
Connection con = null;
PreparedStatement ps = null;
try {
con = getConnection();
ps = con.prepareStatement("select id from finderEnum where bal = ?");
ps.setDouble(1, findBalance);
ps.executeQuery();
ResultSet rs = ps.getResultSet();
Vector v = new Vector();
while (rs.next()) {
String id = rs.getString(1);
v.addElement(id);
}
return v.elements();
} catch (SQLException sqe) {
String error = "SQLException: " + sqe.getMessage();
log(error);
throw new EJBException (error);
} finally {
cleanup(con, ps);
log("End ejbFindAccountsWithBalance (balance = " + findBalance + ")\n");
}
}
/**
* Finds all EJBeans with a balance equal to a given amount.
* Returns a WebLogic FindEnumeration of WebLogic KeyValuePairs. Each
* KeyValuePair is made up of a found EJBean primary key and its
* corresponding bean. Returning a FindEnumeration will cause the EJB
* container to load each bean into the EJB cache.
*
* @param findBalance double Test Amount
* @return weblogic.ejb.pstore.FindEnumeration Enumeration
* of weblogic.ejb.pstore.KeyValuePairs.
* @exception javax.ejb.EJBException
* if there is a communications or systems failure
*/
public FindEnumeration ejbFindAndLoadAccountsWithBalance(double findBalance) {
log("\nejbFindAndLoadAccountsWithBalance (balance = " +
findBalance + ")");
Connection con = null;
PreparedStatement ps = null;
try {
con = getConnection();
ps = con.prepareStatement("select id, bal from finderEnum where bal = ?");
ps.setDouble(1, findBalance);
ps.executeQuery();
ResultSet rs = ps.getResultSet();
Vector v = new Vector();
while (rs.next()) {
AccountBean bean = new AccountBean();
String id = rs.getString(1);
double bal = rs.getDouble(2);
bean.setAccountId(id);
bean.setBalance(bal);
KeyValuePairImpl kvp = new KeyValuePairImpl(id, bean);
v.addElement(kvp);
}
final Enumeration enum = v.elements();
return new FindEnumeration() {
public boolean hasMoreElements() {
return enum.hasMoreElements();
}
public Object nextElement() {
return enum.nextElement();
}
public void close() {}
};
} catch (SQLException sqe) {
String error = "SQLException: " + sqe.getMessage();
log(error);
throw new EJBException (error);
} finally {
cleanup(con, ps);
log("End ejbFindAndLoadAccountsWithBalance (balance = " +
findBalance + ")\n");
}
}
/**
* Adds amount to balance.
*
* @param amount double Amount
* @return double balance
*/
public double deposit(double amount) {
log("Depositing $" + amount + " into '" + accountId + "'");
balance += amount;
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
{
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;
}
/**
* Returns current balance.
*
* @return double Balance
*/
public double balance() {
log("Buisness method 'balance()' called");
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
/**
* Gets current connection to the connection pool.
*
* @return Connection
* @exception javax.ejb.EJBException
* if there is a communications or systems failure
*/
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) {
String error = "Error looking up connection: " + ne.getMessage();
log(error);
throw new EJBException(error);
} finally {
try {
if(initCtx != null) initCtx.close();
} catch(NamingException ne) {
String error = "Error closing context: " + ne.getMessage();
log(error);
throw new EJBException(error);
}
}
}
// You might also consider using WebLogic's log service
private void log(String s) {
if (VERBOSE) System.out.println(s);
}
// Return a String that contains this 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) {
String error = "Error closing PreparedStatement: " + e.getMessage();
log(error);
throw new EJBException (error);
}
try {
if (con != null) con.close();
} catch (Exception e) {
String error = "Error closing Connection: " + e.getMessage();
log(error);
throw new EJBException (error);
}
}
}