Example: Coding beanUserDefinedPushDownMethodsImpl and a stored procedure CMP EJB

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;
    }

Related concepts
Stored procedure support for CMP EJB
Related tasks
Deploying a CMP EJB that uses stored procedure
Developing a CMP EJB that uses stored procedure
Related topics
WSPushDownHelperFactory
WSPushDownHelper
WSRelationalPushDownHelper
WSProceduralPushDownHelper



Searchable topic ID:   rdat_storbankxmp
Last updated: Jun 21, 2007 8:07:48 PM CDT    WebSphere Business Integration Server Foundation, Version 5.0.2
http://publib.boulder.ibm.com/infocenter/wasinfo/index.jsp?topic=/com.ibm.wasee.doc/info/ee/ae/rdat_storbankxmp.html

Library | Support | Terms of Use | Feedback