package com.oreilly.jent.ejb.beanManaged;
/**
* In general, you may use the code in this book in your programs and
* documentation. You do not need to contact us for permission unless
* you're reproducing a significant portion of the code. For example,
* writing a program that uses several chunks of code from this book does
* not require permission. Selling or distributing a CD-ROM of examples
* from O'Reilly books does require permission. Answering a question by
* citing this book and quoting example code does not require permission.
* Incorporating a significant amount of example code from this book into
* your product's documentation does require permission.
*
* We appreciate, but do not require, attribution. An attribution usually
* includes the title, author, publisher, and ISBN. For example:
*
* "Java Enterprise in a Nutshell, Third Edition,
* by Jim Farley and William Crawford
* with Prakash Malani, John G. Norman, and Justin Gehtland.
* Copyright 2006 O'Reilly Media, Inc., 0-596-10142-2."
*
* If you feel your use of code examples falls outside fair use or the
* permission given above, feel free to contact us at
* permissions@oreilly.com.
*/
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.Properties;
import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.ejb.FinderException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import com.oreilly.jent.ejb.DuplicateProfileException;
public class ProfileBean implements EntityBean {
// Entries in the profile (name/value pairs)
public Properties mEntries;
// Our EJB context (non-persistent)
public EntityContext mContext = null;
//--------------------------------------------------
// Entity bean methods
//--------------------------------------------------
// EJB activation method. During activation, create our entry lookup table.
public void ejbActivate() {
mEntries = new Properties();
System.out.println("ProfileBean activated.");
}
// Load bean from persistent store. In this case, we're managing the dbase
// storage, so we store our profile entries as independent records in a
// separate "PROFILE_ENTRY" table.
public void ejbLoad() {
try {
String key = (String)mContext.getPrimaryKey();
loadFromDB(key);
}
catch (Exception e) {
System.out.println("Failed to load ProfileBean: ");
e.printStackTrace();
throw new EJBException("ejbLoad failed: ", e);
}
System.out.println("ProfileBean load finished.");
}
protected void loadFromDB(String key) throws FinderException {
boolean found = false;
Connection conn = null;
Statement s = null;
try {
conn = getConnection();
s = conn.createStatement();
s.executeQuery("select name from profile where name = '" + key + "'");
ResultSet rs = s.getResultSet();
if (rs.next()) {
found = true;
s.executeQuery("select key, value from profile_entry where name = '" +
key + "'");
rs = s.getResultSet();
while (rs.next()) {
String pKey = rs.getString(1);
String pValue = rs.getString(2);
mEntries.put(pKey, pValue);
}
}
}
catch (SQLException e) {
throw new FinderException("Failed to load profile entries from DB: " +
e.toString());
}
catch (NamingException ne) {
throw new FinderException("Failed to access DataSource from server: " +
ne.toString());
}
finally {
try { s.close(); } catch (Exception e) {}
try { conn.close(); } catch (Exception e) {}
}
if (!found) {
throw new FinderException("No profile found for " + key);
}
}
// Store bean to persistent store. Properties are stored as records in the
// PROFILE_ENTRY table.
public void ejbStore() {
String key = (String)mContext.getPrimaryKey();
Connection conn = null;
Statement s = null;
try {
conn = getConnection();
s = conn.createStatement();
// Clear out old profile entries and replace with the current ones
s.executeUpdate("delete from profile_entry where name = '" + key + "'");
Enumeration pKeys = mEntries.propertyNames();
while (pKeys.hasMoreElements()) {
String pKey = (String)pKeys.nextElement();
String pValue = mEntries.getProperty(pKey);
s.executeUpdate("insert into profile_entry (name, key, value) values "
+ "('" + key + "', '" + pKey + "', '" + pValue + "')");
}
}
catch (Exception e) {
System.out.println("Failed to store ProfileBean: ");
e.printStackTrace();
throw new EJBException("ejbStore failed: ", e);
}
finally {
try { s.close(); } catch (Exception e) {}
try { conn.close(); } catch (Exception e) {}
}
System.out.println("ProfileBean store finished.");
}
// Remove this named profile from the database.
public void ejbRemove() {
// Get this profile's name
String key = (String)mContext.getPrimaryKey();
Connection conn = null;
Statement s = null;
try {
conn = getConnection();
s = conn.createStatement();
// Clear out any profile entries
s.executeUpdate("delete from profile_entry where name = '" + key + "'");
// Clear out the profile itself
s.executeUpdate("delete from profile where name = '" + key + "'");
System.out.println("ProfileBean removed.");
}
catch (SQLException se) {
System.out.println("Error removing profile for " + key);
se.printStackTrace();
}
catch (NamingException ne) {
System.out.println("Error accessing DataSource");
ne.printStackTrace();
}
finally {
try { s.close(); } catch (Exception e) {}
try { conn.close(); } catch (Exception e) {}
}
}
// When we're passivated, release our entry table.
public void ejbPassivate() {
mEntries = null;
System.out.println("ProfileBean passivated.");
}
// Get context from container.
public void setEntityContext(EntityContext context) {
mContext = context;
System.out.println("ProfileBean context set.");
}
// Container is removing our context.
public void unsetEntityContext() {
mContext = null;
System.out.println("ProfileBean context unset.");
}
// Since we're managing persistence here in the bean, we need to
// implement the finder methods.
public String ejbFindByPrimaryKey(String key) throws FinderException {
loadFromDB(key);
return key;
}
public Collection ejbFindByEntryValue(String key, String value)
throws FinderException {
LinkedList userList = new LinkedList();
// Get a new connection from the EJB server
Connection conn = null;
Statement s = null;
try {
conn = getConnection();
s = conn.createStatement();
// Issue a query for matching profile entries, grabbing just the name
s.executeQuery("select distinct(name) from profile_entry where " +
" key = '" + key + "' and value = '" + value + "'");
// Convert the results in primary keys and return an enumeration
ResultSet results = s.getResultSet();
while (results.next()) {
String name = results.getString(1);
userList.add(name);
}
}
catch (SQLException se) {
// Failed to do database lookup
throw new FinderException();
}
catch (NamingException ne) {
// Failed to access DataSource
throw new FinderException();
}
finally {
try { s.close(); } catch (Exception e) {}
try { conn.close(); } catch (Exception e) {}
}
return userList;
}
// Create method with name of profile owner.
public String ejbCreate(String name)
throws DuplicateProfileException, CreateException {
Connection conn = null;
Statement s = null;
try {
conn = getConnection();
s = conn.createStatement();
s.executeUpdate("insert into profile (name) values ('" + name + "')");
}
catch (SQLException se) {
System.out.println("Error creating profile, assuming duplicate.");
try {
StringWriter strw = new StringWriter();
PrintWriter prntw = new PrintWriter(strw);
se.printStackTrace(prntw);
throw new DuplicateProfileException(
"SQL error creating profile for " +
name + ": " + se.toString() +
"\n" + strw.toString());
}
catch (Exception e) {}
}
catch (NamingException ne) {
System.out.println("Error accessing DataSource");
throw new CreateException("Error accessing DataSource.");
}
finally {
try { s.close(); } catch (Exception e) {}
try { conn.close(); } catch (Exception e) {}
}
System.out.println("ProfileBean created for " + name + ".");
return name;
}
// Post-creation notification. Nothing to do here, but we need
// to provide an implementation.
public void ejbPostCreate(String name) {
System.out.println("ProfileBean post-create called for " + name + ".");
}
//--------------------------------------------------
// Utility methods
//--------------------------------------------------
// Get a connection from our J2EE data source.
private Connection getConnection() throws SQLException, NamingException {
Context ctx = new InitialContext();
DataSource profileDB =
(DataSource)ctx.lookup("java:comp/env/jdbc/profileDB");
return profileDB.getConnection();
}
//--------------------------------------------------
// Business methods
//--------------------------------------------------
// Returns the name of the owner of this profile.
public String getName() {
return (String)mContext.getPrimaryKey();
}
// Returns the value of the given entry in this profile, or null
// if the given property isn't present in this profile.
public String getEntry(String key) {
return mEntries.getProperty(key);
}
// Sets the value of the property to the given value.
public void setEntry(String key, String value) {
if (mEntries == null) {
mEntries = new Properties();
}
mEntries.put(key, value);
}
}
|