The following code segments illustrate how to code the beanUserDefinedPushDownMethodsImp templates, and how to code a CMP bean that uses a stored procedure.
In the following examples, a BankAccountBean has two CRUD methods and one abstract data logic method.
Abstract BankAccountBean class
package com.ibm.websphere.sample; import com.ibm.websphere.sample.exception.InvalidTransactionTypeException; /** * Bean implementation class for Enterprise Bean: BankAccount */ public abstract class BankAccountBean implements javax.ejb.EntityBean { private javax.ejb.EntityContext myEntityCtx; /** * setEntityContext */ public void setEntityContext(javax.ejb.EntityContext ctx) { myEntityCtx = ctx; } /** * getEntityContext */ public javax.ejb.EntityContext getEntityContext() { return myEntityCtx; } /** * unsetEntityContext */ public void unsetEntityContext() { myEntityCtx = null; } /** * ejbActivate */ public void ejbActivate() { } /** * ejbLoad */ public void ejbLoad() { } /** * ejbPassivate */ public void ejbPassivate() { } /** * ejbRemove */ public void ejbRemove() throws javax.ejb.RemoveException { } /** * ejbStore */ public void ejbStore() { } /** * Get accessor for persistent attribute: accountId */ public abstract java.lang.String getAccountId(); /** * Set accessor for persistent attribute: accountId */ public abstract void setAccountId(java.lang.String newAccountId); /** * Get accessor for persistent attribute: balance */ public abstract float getBalance(); /** * Set accessor for persistent attribute: balance */ public abstract void setBalance(float newBalance); /** * ejbCreate * * @param accountId * @param balance account balance */ public com.ibm.websphere.sample.BankAccountKey ejbCreate(java.lang.String accountId, float balance) throws javax.ejb.CreateException { setAccountId(accountId); setBalance(balance); return null; } /** * ejbPostCreate */ public void ejbPostCreate(java.lang.String accountId, float balance) throws javax.ejb.CreateException { } /** * This method gets the number of transactions of a particular transaction * type in a certain range of time, for example, how many times the * account has been withdrawn in the past month. * * This method uses stored procedure * getNumberOfTransactions(String id, String transactionType, Timestamp fromTime, Timestamp toTime). * This stored procedure gets the number of transactions of a particular transaction type * within a certain time period. * * @param transactionType The transaction type * @param startTime The start time for the search. * @param startTime The end time for the search. * * @return int The number of the transactions */ public abstract int getNumberOfTransactions( String transactionType, java.sql.Timestamp startTime, java.sql.Timestamp endTime) throws InvalidTransactionTypeException; }
BankAccountBean UserDefinedPushDownMethodsImpl
The following BankAccountBeanUserDefinedPushDownMethodsImpl example shows only the abstract create, findByPrimaryKey, findByBalance and data logic method getNumberOfTransactions().
package com.ibm.websphere.sample.websphere_deploy.jdbc; import java.sql.*; import com.ibm.websphere.sample.BankAccountBean; import com.ibm.websphere.sample.websphere_deploy.BankAccountBeanUserDefinedPushDownMethods; import com.ibm.ejs.ras.TraceComponent; import com.ibm.ejs.ras.Tr; import com.ibm.websphere.appprofile.accessintent.AccessIntent; import com.ibm.websphere.rsadapter.WSRelationalPushDownHelper; import com.ibm.websphere.rsadapter.WSPushDownHelperFactory; import javax.resource.ResourceException; import javax.resource.cci.IndexedRecord; import javax.resource.cci.Record; // *** insert any necessary additional import statements here *** /** * JDBC implementation of the UserDefinedPushDownMethods interface * for the BankAccountBean CMP entity bean. Roughly speaking, this is where you * would put the connectivity code that would have been in the bean * implementation class of a BMP entity bean. * * @see com.ibm.websphere.ejbpersistence.EJBToRAAdapter */ public class BankAccountBeanUserDefinedPushDownMethodsImpl implements BankAccountBeanUserDefinedPushDownMethods { private static final TraceComponent tc = Tr.register(BankAccountBeanUserDefinedPushDownMethodsImpl.class, null, null); private WSRelationalPushDownHelper helper = null; // *** insert any necessary additional fields here *** /** * Constructor for BankAccountBeanUserDefinedPushDownMethodsImpl * * @param pdHelper WSRelationalPushDownHelper instance, * used by the push down method implementations */ public BankAccountBeanUserDefinedPushDownMethodsImpl(WSRelationalPushDownHelper pdHelper) { helper = pdHelper; // *** insert any necessary additional constructor code here *** } /** * User-defined push-down method ejbCreate. * * @param bean Reference to the bean implementation class * @param connection The CCI connection to the back-end system. This * connection was previously obtained (by the EJBToRAAdapter implementation) * via connectionFactory.getConnection(connectionSpec). For non-CCI based * beans, this will be null and the user will have to manually connect to * the back-end system. * * @exception javax.ejb.CreateException Thrown if an exception occurs creating bean data * @exception ResourceException Any other exceptions are wrapped in a * ResourceException. */ public void ejbCreate( BankAccountBean bean, Object connection) throws javax.ejb.CreateException, ResourceException { if (tc.isEntryEnabled()) Tr.entry(tc, "ejbCreate(BankAccountBean, Object)", new Object[] {bean, connection}); java.sql.CallableStatement callableStatement = null; try { callableStatement = helper.prepareCall(connection, "{call createAccount(?, ?)}"); // Begin customer-written code to populate callableStatement // Place code here like: callableStatement.setXXX(X, argX); callableStatement.setString(1, bean.getAccountId()); callableStatement.setDouble(2, bean.getBalance()); // End customer-written code to populate callableStatement callableStatement.execute(); } catch (Exception e) { ResourceException re = helper.createResourceException(e, this.getClass()); if (tc.isEntryEnabled()) Tr.exit(tc, "ejbCreate(BankAccountBean, Object)", re); throw re; } //Note that if the return code from the back-end datastore interaction //indicated that a user-defined exception (declared in the push-down //method's signature) should be thrown, then throw it here. if (tc.isEntryEnabled()) Tr.exit(tc, "ejbCreate(BankAccountBean, Object)"); } /** * User-defined push-down method ejbFindByPrimaryKey. * * @param arg0 Push-down method Parameter #0 * @param accessIntent Reference to the access intent settings to be used for this method * @param connection The CCI connection to the back-end system. This * connection was previously obtained (by the EJBToRAAdapter implementation) * via connectionFactory.getConnection(connectionSpec). For non-CCI based * beans, this will be null and the user will have to manually connect to * the back-end system. * * @return The return type of this finder method is a Record of Records, * each of which contains the values of the CMP fields of the desired bean, * with primitives wrapped (such as a java.lang.Integer for an int). The * order of the fields is as follows: * Position #0: accountId * Position #1: balance * * @exception javax.ejb.FinderException Thrown if an exception occurs retrieving bean data * @exception ResourceException Any other exceptions are wrapped in a * ResourceException. */ public Record ejbFindByPrimaryKey( com.ibm.websphere.sample.BankAccountKey arg0, AccessIntent accessIntent, Object connection) throws javax.ejb.FinderException, ResourceException { if (tc.isEntryEnabled()) Tr.entry(tc, "ejbFindByPrimaryKey(com.ibm.websphere.sample.BankAccountKey, AccessIntent, Object)", new Object[] {arg0, accessIntent, connection}); IndexedRecord returnValue = helper.createCCIIndexedRecord(); //Change above returnValue type to Record if returning a ResultSet java.sql.CallableStatement callableStatement = null; try { callableStatement = helper.prepareCall(connection, "{call getAccountByAccountID(?,?)}"); // Begin customer-written code to populate callableStatement // Place code here like: callableStatement.setXXX(X, argX); callableStatement.setString(1, arg0.getAccountId()); callableStatement.registerOutParameter(2, Types.DOUBLE); // End customer-written code to populate callableStatement callableStatement.execute(); //The returnValue variable should be set to the appropriate value double b = callableStatement.getDouble(2); if (b == -1) { // If the return value is -1, we know this account doesn't exist. throw new ResourceException("No account has been found"); } IndexedRecord rec = helper.createCCIIndexedRecord(); rec.add(arg0.getAccountId()); rec.add(new Double(b)); returnValue.add(rec); } catch (Exception e) { ResourceException re = helper.createResourceException(e, this.getClass()); if (tc.isEntryEnabled()) Tr.exit(tc, "ejbFindByPrimaryKey(com.ibm.websphere.sample.BankAccountKey, AccessIntent, Object)", re); throw re; } //Note that if the return code from the back-end datastore interaction //indicated that a user-defined exception (declared in the push-down //method's signature) should be thrown, then throw it here. if (tc.isEntryEnabled()) Tr.exit(tc, "ejbFindByPrimaryKey(com.ibm.websphere.sample.BankAccountKey, AccessIntent, Object)", returnValue); return returnValue; } /** * User-defined push-down method ejbFindByBalance. * * @param arg0 Push-down method Parameter #0 * @param arg1 Push-down method Parameter #1 * @param accessIntent Reference to the access intent settings to be used for this method * @param connection The CCI connection to the back-end system. This * connection was previously obtained (by the EJBToRAAdapter implementation) * via connectionFactory.getConnection(connectionSpec). For non-CCI based * beans, this will be null and the user will have to manually connect to * the back-end system. * * @return The return type of this finder method is a Record of Records, * each of which contains the values of the CMP fields of the desired bean, * with primitives wrapped (such as a java.lang.Integer for an int). The * order of the fields is as follows: * Position #0: accountId * Position #1: balance * * @exception javax.ejb.FinderException Thrown if an exception occurs retrieving bean data * @exception ResourceException Any other exceptions are wrapped in a * ResourceException. */ public Record ejbFindByBalance( float arg0, float arg1, AccessIntent accessIntent, Object connection) throws javax.ejb.FinderException, ResourceException { if (tc.isEntryEnabled()) Tr.entry(tc, "ejbFindByBalance(float, float, AccessIntent, Object)", new Object[] {new Float(arg0), new Float(arg1), accessIntent, connection}); Record returnValue = helper.createCCIIndexedRecord(); //Change above returnValue type to Record if returning a ResultSet java.sql.CallableStatement callableStatement = null; try { callableStatement = helper.prepareCall(connection, "{call getAccountByBalance(?, ?,?)}"); int lockType = helper.getLockType(connection,accessIntent); callableStatement.setInteger(3, lockType); // Begin customer-written code to populate callableStatement // Place code here like: callableStatement.setXXX(X, argX); callableStatement.setDouble(1, arg0); callableStatement.setDouble(2, arg1); // End customer-written code to populate callableStatement callableStatement.execute(); //The returnValue variable should be set to the appropriate value ResultSet rs = callableStatement.getResultSet(); returnValue = helper.createCCIResultSet(rs, conn); } catch (Exception e) { ResourceException re = helper.createResourceException(e, this.getClass()); if (tc.isEntryEnabled()) Tr.exit(tc, "ejbFindByBalance(float, float, AccessIntent, Object)", re); throw re; } //Note that if the return code from the back-end datastore interaction //indicated that a user-defined exception (declared in the push-down //method's signature) should be thrown, then throw it here. if (tc.isEntryEnabled()) Tr.exit(tc, "ejbFindByBalance(float, float, AccessIntent, Object)", returnValue); return returnValue; } } }
CMR in BankAccountBean
This example demonstrates the use of stored procedure in a Container Managed Relationship (CMR). Assume the BankAccount CMP bean has a one-to-many relationship with TransactionHistory the CMP bean. The following two methods are added to the BankAccountBean class.
BankAccountBean /** * Get the transaction histories of this account. * * @return a collection of transaction histories. */ public abstract java.util.Collection getTransactionHistories(); /** * Set the transaction histories of this account. * * @param transactionHistories a collection of transaction histories. */ public abstract void setTransactionHistories(java.util.Collection transactionHistories); Assume the CMR getter getTransactionHistories uses stored procedure. This stored procedure will be called in the finder method of the FunctionSet class of TransactionHistory CMP bean.
TransactionHistoryBeanUserDefinedPushDownMethodsImpl
This example shows only the getTransactionHistories method. The remaining methods for the FunctionSet are not shown here.
public class TransactionHistoryBeanUserDefinedPushDownMethodsImpl implements com.ibm.websphere.rsadapter.UserDefinedPushDownMethods { /** /** * User-defined push-down method ejbFindTransactionHistoriesByBankAccountKey. * * @param arg0 Push-down method Parameter #0 * @param accessIntent Reference to the access intent settings to be used for this method * @param connection The CCI connection to the back-end system. This * connection was previously obtained (by the EJBToRAAdapter implementation) * via connectionFactory.getConnection(connectionSpec). For non-CCI based * beans, this will be null and the user will have to manually connect to * the back-end system. * * @return The return type of this finder method is a Record of Records, * each of which contains the values of the CMP fields of the desired bean, * with primitives wrapped (such as a java.lang.Integer for an int). The * order of the fields is as follows: * Position #0: accountId * Position #1: transactionType * Position #2: transactionAmount * Position #3: transactionDateTime * * @exception javax.ejb.FinderException Thrown if an exception occurs retrieving bean data * @exception ResourceException Any other exceptions are wrapped in a * ResourceException. */ public Record ejbFindTransactionHistoriesByBankAccountKey( com.ibm.websphere.sample.BankAccountKey arg0, AccessIntent accessIntent, Object connection) throws javax.ejb.FinderException, ResourceException { if (tc.isEntryEnabled()) Tr.entry(tc, "ejbFindTransactionHistoriesByBankAccountKey(com.ibm.websphere.sample.BankAccountKey, AccessIntent, Object)", new Object[] {arg0, accessIntent, connection}); IndexedRecord returnValue = helper.createCCIIndexedRecord(); //Change above returnValue type to Record if returning a ResultSet java.sql.CallableStatement callableStatement = null; try { callableStatement = helper.prepareCall(connection, "{call getAccountHistoryByType(?)}"); // Begin customer-written code to populate callableStatement // Place code here like: callableStatement.setXXX(X, argX); callableStatement.setString(1, arg0.getAccountId()); // End customer-written code to populate callableStatement callableStatement.execute(); //The returnValue variable should be set to the appropriate value ResultSet rs = callableStatement.getResultSet(); IndexedRecord item = null; // this is a record for each row data while (rs.next()) { item = helper.createCCIIndexedRecord(); item.add(rs.getString(1)); item.add(rs.getString(2)); item.add(new Float(rs.getDouble(3))); item.add(rs.getTimestamp(4)); returnValue.add(item); } } catch (Exception e) { ResourceException re = helper.createResourceException(e, this.getClass()); if (tc.isEntryEnabled()) Tr.exit(tc, "ejbFindTransactionHistoriesByBankAccountKey(com.ibm.websphere.sample.BankAccountKey, AccessIntent, Object)", re); throw re; } //Note that if the return code from the back-end datastore interaction //indicated that a user-defined exception (declared in the push-down //method's signature) should be thrown, then throw it here. if (tc.isEntryEnabled()) Tr.exit(tc, "ejbFindTransactionHistoriesByBankAccountKey(com.ibm.websphere.sample.BankAccountKey, AccessIntent, Object)", returnValue); return returnValue; } //End of code example return outputRecord; }