-
1. Re: EJB specification, BMP / CMPs, transaction
davidjencks Dec 14, 2001 6:21 PM (in response to jcordonn)You don't say where your connection comes from. In jboss there currently is a limitation that you must get your connection after the tx starts and close it before it ends. (apparently may not be so true with bmt, but definitely with cmt). So, you can cache the datasource, but you have to get a new connection within each transaction.
Holding onto a connection over a transaction boundary kills it and it usually won't get disposed of properly, thus the pool exhaustion. -
2. Re: EJB specification, BMP / CMPs, transaction
jcordonn Feb 1, 2002 4:46 AM (in response to jcordonn)Hi ! That's my code ! After a couple of create/remove, the client hangs on a remove,....any idea ?
Thanks
/Joel
/**
* @ejb:bean name="ftp/FtpBean" type="BMP" jndi-name="ejb/ftp/FtpBean" view-type="remote"
* @ejb:home generate="remote"
* @ejb:interface generate="remote"
*
* @ejb:finder signature="Collection findAll()"
*
* @ejb:resource-ref res-name="jdbc/wpsDS" res-type="javax.sql.DataSource" res-auth="Container"
*
* @jboss:resource-ref res-ref-name="jdbc/wpsDS" resource-name="wpsDS"
* @jboss:resource-manager res-man-name="wpsDS" res-man-jndi-name="java:/wpsDS"
* @jboss:table-name "WETTER"
* @jboss:create-table "true"
* @jboss:remove-table "true"
* @jboss:tuned-updates "true"
* @jboss:read-only "false"
*/
public abstract class FtpBMPBean implements EntityBean {
private EntityContext context;
private DataSource datasource;
private Connection con;
private String tablename = "WETTER";
private String DS = "java:comp/env/jdbc/wpsDS";
// public methods -----------------------------------------------------
/**
* @ejb:pk-field
* @ejb:persistent-field
* @ejb:interface-method
*/
public abstract int getLocationValue();
/**
* @ejb:interface-method
*/
public abstract void setLocationValue(int value);
/**
* @ejb:persistent-field
* @ejb:interface-method
*/
public abstract String getLocationName();
/**
* @ejb:interface-method
*/
public abstract void setLocationName(String name);
/**
* @ejb:persistent-field
* @ejb:interface-method
*/
public abstract byte[] getXml();
/**
* @ejb:interface-method
*/
public abstract void setXml(byte[] xml);
/**
*/
public abstract void setData(FtpBeanData data);
/**
* @ejb:interface-method
*/
public abstract FtpBeanData getData();
// private methods -----------------------------------------------------
/**
* @ejb:create-method
* @ejb:transaction type="Required"
*/
public FtpBeanPK ejbCreate(int value, String name, byte[] xml) throws CreateException {
try {
// makeConnection already called when calling setEntityContext();
// acquire the connection IN a already started transaction
Connection mycon = datasource.getConnection();
insertRow(mycon, value, name, xml);
mycon.close(); // explicitly close the connection before the transaction complete.
} catch (Exception ex) {
throw new CreateException("ejbCreate: " + ex.getMessage());
}
FtpBeanData data = getData();
data.setLocationValue(value);
data.setLocationName(name);
data.setXml(xml);
FtpBeanPK pk = new FtpBeanPK();
pk.locationValue = value;
return pk;
}
public void ejbPostCreate(int value, String name, byte[] xml) {
}
public FtpBeanPK ejbFindByPrimaryKey(FtpBeanPK primaryKey) throws FinderException {
boolean result = true;
try {
result = selectByPrimaryKey(primaryKey);
} catch (Exception ex) {
throw new RuntimeException("ejbFindByPrimaryKey" + ex.getMessage());
}
if (result) {
return primaryKey;
}
else {
throw new FinderException
("Row for id " + primaryKey + " not found.");
}
}
/**
* @ejb:transaction type="Required"
*/
public void ejbRemove() throws RemoveException {
try {
// acquire the connection IN a already started transaction
Connection mycon = datasource.getConnection();
deleteRow(mycon, (FtpBeanPK)context.getPrimaryKey());
mycon.close();
} catch (Exception ex) {
throw new RemoveException("ejbRemove: " +
ex.getMessage());
}
}
/**
*/
public void setEntityContext(EntityContext context) {
this.context = context;
try {
getDatasource(); // cache the datasource and the connection
} catch (Exception ex) {
throw new RuntimeException("Unable to connect to database. " +
ex.getMessage());
}
}
/**
*/
public void unsetEntityContext() {
try {
con.close();
} catch (SQLException ex) {
throw new RuntimeException("unsetEntityContext: " + ex.getMessage());
}
}
public void ejbActivate() {
}
public void ejbPassivate() {
}
/**
*/
public void ejbLoad() {
try {
loadRow();
} catch (Exception ex) {
throw new RuntimeException("ejbLoad: " + ex.getMessage());
}
}
/**
*/
public void ejbStore() {
try {
storeRow();
} catch (Exception ex) {
throw new RuntimeException("ejbStore: " + ex.getMessage());
}
}
private void getDatasource() throws NamingException, SQLException {
InitialContext ic = new InitialContext();
datasource = (DataSource) ic.lookup(DS); // cached datasource
con = datasource.getConnection(); // cached connection
}
/**
get connection only when required. cf transaction context.
*/
/*
private void getConnection() throws SQLException {
if(con == null)
con = datasource.getConnection();
}
*/
/**
* BE CAREFUL: if you want the the insertRow method excutes in a
* transaction, be careful to open and close the datasource connection
* after and before the transaction complete.
*/
private void insertRow (Connection connnection, int value, String name, byte[] xml)
throws SQLException {
String insertStatement =
"insert into " + tablename + " values ( ? , ? , ?)";
PreparedStatement prepStmt =
connnection.prepareStatement(insertStatement);
prepStmt.setInt(1, value);
prepStmt.setString(2, name);
prepStmt.setBytes(3, xml);
prepStmt.executeUpdate();
prepStmt.close();
}
private void deleteRow(Connection aConnection, FtpBeanPK pk) throws SQLException {
String deleteStatement =
"delete from " + tablename + " where value = ?";
PreparedStatement prepStmt =
aConnection.prepareStatement(deleteStatement);
prepStmt.setInt(1, pk.locationValue);
prepStmt.executeUpdate();
prepStmt.close();
}
private boolean selectByPrimaryKey(FtpBeanPK pk) throws SQLException {
String selectStatement =
"SELECT name, value" +
" FROM " + tablename + " WHERE value = ?";
PreparedStatement prepStmt =
con.prepareStatement(selectStatement);
prepStmt.setInt(1, pk.locationValue);
ResultSet rs = prepStmt.executeQuery();
boolean result = rs.next();
prepStmt.close();
return result;
}
private void loadRow() throws SQLException, FinderException {
String selectStatement =
"select name, xml from " + tablename + " where value = ?";
PreparedStatement prepStmt =
con.prepareStatement(selectStatement);
FtpBeanPK pk = (FtpBeanPK)context.getPrimaryKey();
prepStmt.setInt(1, pk.locationValue);
ResultSet rs = prepStmt.executeQuery();
if (rs.next()) {
FtpBeanData data = getData();
data.setLocationName(rs.getString(1));
data.setXml(rs.getBytes(2));
prepStmt.close();
}
else {
prepStmt.close();
throw new FinderException("No row for locationValue " + pk.locationValue +
" not found in database.");
}
}
private void storeRow() throws SQLException {
String updateStatement =
"update " + tablename + " set xml = ? where value = ? and name = ?";
PreparedStatement prepStmt =
con.prepareStatement(updateStatement);
FtpBeanData data = getData();
prepStmt.setBytes(1, data.getXml()); // convert the String to a byte array
prepStmt.setInt(2, data.getLocationValue());
prepStmt.setString(3, data.getLocationName());
int rowCount = prepStmt.executeUpdate();
prepStmt.close();
if (rowCount == 0) {
throw new RuntimeException("Storing row for locationName " + data.getLocationName() +
" and locationValue " + data.getLocationValue() + " failed.");
}
}
}