Ok let me give this a stab, this might help you.... Please find the attached files, not sure if the attached file's makes its way to the list....
SampleCode = Sample code, that gets the connection etc DBConnectionManager = manages the connection pool DBUtil = DB utility System.properties = configuration DBoptions = DB options etc All you have to do is change the system.properties to fit your need and compile. -----Original Message----- From: Scott Purcell [mailto:[EMAIL PROTECTED] Sent: Friday, April 15, 2005 4:56 PM To: user@struts.apache.org Subject: Database Assistance Needed I have had some issues this past week, trying to come up with a way to cleanly connect to my, MySQL database. I know this is not necessarily a struts issue, but I am betting that there is no one on this list who is not using some type of database in the back-end. Now I have the O'Reilly book on Struts, and using the ObjectRelationalBridge is a little too large for me to take on currently, same as Hibernate or anything else I would have to research thoroughly. I just need a solid, simple way to grab a connection from a pool, use it in a Business Object and call it a day. Since I am running on Tomcat 5.5, I have tried to incorporate the DBCP from jakarta into my struts stuff. Problem is most examples do not work, or are incomplete for the 5.5 Tomcat, and I cannot find any decent examples of doing this. I am basically Running Mysql, and Tomcat 5.5, and struts 1.2. I really do not want to use the data-source in struts, as I intend to use a solution that will not be depreciated in the next release. Could anyone throw me a bone here. I have searched google to death for good examples, but come up with outdated examples, or incomplete. The examples for Tomcat make you use JNDI, and I am not sure if that is the way to go. Any assistance would be sincerely appreciated. Thanks, Scott --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
public boolean isMemberAvailableByUserName(String memberUserName) throws SQLException { boolean memberPresent = false; Connection connection = null; PreparedStatement statement = null; ResultSet resultSet = null; StringBuffer sql = new StringBuffer(512); sql.append("SELECT MemberUserName"); sql.append(" FROM " + TABLE_NAME); sql.append(" WHERE MemberUserName = ?"); try { connection = DBUtils.getConnection(); statement = connection.prepareStatement(sql.toString()); statement.setString(1, memberUserName); resultSet = statement.executeQuery(); if (resultSet.next()) { memberPresent = true; } } catch (SQLException sqle) { sqle.printStackTrace(); logger.fatal("Error executing " + sql + memberUserName); } finally { DBUtils.closeResultSet(resultSet); DBUtils.closeStatement(statement); DBUtils.closeConnection(connection); } return memberPresent; }
import java.sql.*; import java.util.*; import org.apache.commons.logging.*; /** * DBConnectionManager * * This class is a Singleton that provides access to the * connection pool. A client gets access to the single * instance through the static getInstance() method * and can then check-out and check-in connections from a pool. * When the client shuts down it should call the release() method * to close all opened connections and do other clean up. */ public class DBConnectionManager { /** * Logger */ private static Log logger = LogFactory.getLog(DBConnectionManager.class); /** * TIME_BETWEEN_RETRIES */ private static final int TIME_BETWEEN_RETRIES = 500; // O.5 second /** * DBConnectionManager instance */ static private DBConnectionManager instance = null; // The single instance /** * DBConnectionPool pool */ private DBConnectionPool pool = null;// please be careful if u want to make this variable static /** * A private constructor since this is a Singleton Note: This constructor is * lightweight since DBConnectionPool is lightweight, so no connection is * created until the first time getConnection() is called * * @param option DBOptions */ private DBConnectionManager(DBOptions option) { try { Class.forName(option.driverClassName).newInstance(); } catch (Exception e) { logger.fatal("DBConnectionManager: Unable to load driver = " + option.driverClassName); } //if (pool == null) {//uncomment since pool is an instance variable pool = new DBConnectionPool(option.databaseURL, option.databaseUser, option.databasePassword, option.maxConnection); //} } /** * Returns the single instance, creating one if it's the * first time this method is called. * * @return DBConnectionManager The single instance. */ static synchronized public DBConnectionManager getInstance() { if (instance == null) { DBOptions option = new DBOptions(); instance = new DBConnectionManager(option); } return instance; } /** * Returns the single instance, creating one if it's the first time this * method is called. * * @return DBConnectionManager The single instance. * @param option DBOptions */ static synchronized public DBConnectionManager getInstance(DBOptions option) { if (instance == null) { if (option == null) { option = new DBOptions(); } instance = new DBConnectionManager(option); } return instance; } /** * Returns a connection to the pool. * * @throws SQLException * @param con Connection */ public void freeConnection(Connection con) throws SQLException { pool.freeConnection(con); } /** * Returns an open connection. If no one is available, and the max number of * connections has not been reached, a new connection is created. * * @return Connection The connection or null * @throws SQLException */ public Connection getConnection() throws SQLException { return pool.getConnection(); } /** * Returns an open connection. If no one is available, and the max number of * connections has not been reached, a new connection is created. If the max * number has been reached, waits until one is available or the specified * time has elapsed. * * @param time The number of milliseconds to wait * @return Connection The connection or null * @throws SQLException */ public /*synchronized*/ Connection getConnection(long time) throws SQLException { return pool.getConnection(time); } /** * Closes all open connections. */ public void release() { pool.release(); } /** * This inner class represents a connection pool. It creates new * connections on demand, up to a max number if specified. * It also checks to make sure that the connection is still open * before it is returned to a client. */ class DBConnectionPool { private int checkedOut = 0; private Vector freeConnections = new Vector(); private int maxConn = 0; private String password = null; private String url = null; private String user = null; /** * Creates new connection pool. * NOTE: new an instance of this class is lightweight since it does not create any connections * * @param url The JDBC URL for the database * @param user The database user, or null * @param password The database user password, or null * @param maxConn The maximal number of connections, or 0 for no limit */ public DBConnectionPool(String url, String user, String password, int maxConn) { this.url = url; this.user = user; this.password = password; this.maxConn = maxConn; } /** * Checks in a connection to the pool. Notify other Threads that * may be waiting for a connection. * * @todo: Maybe we dont need notifyAll(); ??? * * @param con The connection to check in */ synchronized void freeConnection(Connection con) { // Put the connection at the end of the Vector if (con != null) { //make sure that the connection is not null // note that we dont have to check if the connection is not connected // this will be check in the getConnection method freeConnections.addElement(con); // FIXME: posible negative value checkedOut--; // NOTE: this number can be negative (in case connection does not come from the pool) notifyAll(); // can I remove it ??? } } /** * Checks out a connection from the pool. If no free connection is * available, a new connection is created unless the max number of * connections has been reached. If a free connection has been closed by * the database, it's removed from the pool and this method is called * again recursively. * * @throws SQLException * @return Connection */ synchronized Connection getConnection() throws SQLException{ Connection con = null; while ( (freeConnections.size() > 0) && (con == null) ) { // Pick the first Connection in the Vector // to get round-robin usage con = (Connection) freeConnections.firstElement(); freeConnections.removeElementAt(0); try { if (con.isClosed()) { logger.info("Removed bad connection in DBConnectionPool."); con = null; // to make the while loop to continue } } catch (SQLException e) { con = null; // to make the while loop to continue } } // while if (con == null) {// cannot get any connection from the pool if (maxConn == 0 || checkedOut < maxConn) {// maxConn = 0 means unlimited connections try{ con = newConnection(); } catch(SQLException ex){ logger.fatal("Unable to connect the Database."); throw new SQLException("Unable to connect the Database."); } } } if (con != null) { checkedOut++; } return con; } /** * Checks out a connection from the pool. If no free connection * is available, a new connection is created unless the max * number of connections has been reached. If a free connection * has been closed by the database, it's removed from the pool * and this method is called again recursively. * <P> * If no connection is available and the max number has been * reached, this method waits the specified time for one to be * checked in. </P> * * Note that this method is not synchronized since it relies on the * getConnection(void) method I also believe that this method SHOULD NOT * synchronized because I use #sleep() method * * @todo: check if we should synchronize this method and use wait * instead of sleep ??? * * @param timeout long The timeout value in milliseconds * @throws SQLException * @return Connection */ Connection getConnection(long timeout) throws SQLException{ long startTime = System.currentTimeMillis(); Connection con; while ((con = getConnection()) == null) { long elapsedTime = System.currentTimeMillis() - startTime; if (elapsedTime >= timeout) { // Timeout has expired return null; } long timeToWait = timeout - elapsedTime; if (timeToWait > TIME_BETWEEN_RETRIES){ timeToWait = TIME_BETWEEN_RETRIES; // we dont want to wait for more than TIME_BETWEEN_RETRIES second each time } try { Thread.sleep(timeToWait); } catch (InterruptedException e) {} } return con; } /** * Closes all available connections. */ synchronized void release() { Enumeration allConnections = freeConnections.elements(); while (allConnections.hasMoreElements()) { Connection con = (Connection) allConnections.nextElement(); try { con.close(); } catch (SQLException e) { logger.error("Can't close connection in DBConnectionPool."); } } freeConnections.removeAllElements(); } /** * Creates a new connection, using a userid and password if specified. * * @todo: check if this method need synchronized * @throws SQLException * @return Connection */ private Connection newConnection() throws SQLException{ Connection con = null; try { if (user == null) { con = DriverManager.getConnection(url); } else { con = DriverManager.getConnection(url, user, password); } } catch (SQLException e) { logger.error("Can't create a new connection in DBConnectionPool. URL = " + url, e); throw new SQLException("Unable to connect to the Database"); // return null; } return con; } } }
import java.sql.*; import javax.sql.DataSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * DBUtils * */ public final class DBUtils { /** * Log logger */ private static Log logger = LogFactory.getLog(DBUtils.class); /** * DATABASE_UNKNOWN */ public static final int DATABASE_UNKNOWN = 0; /** * DATABASE_GENERAL */ public static final int DATABASE_GENERAL = 1; /** * DATABASE_NOSCROLL */ public static final int DATABASE_NOSCROLL = 2; /** * DATABASE_ORACLE */ public static final int DATABASE_ORACLE = 10; /** * int DATABASE_SQLSERVER */ public static final int DATABASE_SQLSERVER = 11; /** * int DATABASE_DB2 */ public static final int DATABASE_DB2 = 12; /** * int DATABASE_SYBASE */ public static final int DATABASE_SYBASE = 13; /** * int DATABASE_IMFORMIX */ public static final int DATABASE_IMFORMIX = 14; /** * int DATABASE_MYSQL */ public static final int DATABASE_MYSQL = 15; /** * int DATABASE_POSTGRESQL */ public static final int DATABASE_POSTGRESQL = 16; /** * int DATABASE_HSQLDB */ public static final int DATABASE_HSQLDB = 17; /** * int DATABASE_ACCESS */ public static final int DATABASE_ACCESS = 18; /** * int databaseType */ private static int databaseType = DATABASE_UNKNOWN; /** * boolean useDatasource */ private static boolean useDatasource = false; /** * int maxTimeToWait */ private static int maxTimeToWait = 2000;// 2 seconds /** * DBConnectionManager connectionManager */ private static DBConnectionManager connectionManager = null; /** * DataSource dataSource */ private static DataSource dataSource = null; // static init of the class static { DBOptions option = new DBOptions(); if (option.useDatasource) { useDatasource = true; try { javax.naming.Context context = new javax.naming.InitialContext(); // sample data source = java:comp/env/jdbc/MysqlDataSource dataSource = (DataSource) context.lookup(option.datasourceName); logger.info("DBUtils : use datasource = " + option.datasourceName); } catch (javax.naming.NamingException e) { logger.error("Cannot get DataSource: datasource name = " + option.datasourceName, e); } } else { useDatasource = false; maxTimeToWait = option.maxTimeToWait; connectionManager = DBConnectionManager.getInstance(option); logger.info("DBUtils : use built-in DBConnectionManager (maxTimeToWait = " + maxTimeToWait + ")"); } } /** * contructor */ private DBUtils() {// so cannot new an instance } /** * Use this method to get the database type. This method will automatically * detect the database type. You could override this value by modifying * the value in system.properties * @return : the database type */ public static int getDatabaseType() { if (databaseType == DATABASE_UNKNOWN) { Connection connection = null; try { connection = DBUtils.getConnection(); DatabaseMetaData dbmd = connection.getMetaData(); String databaseName = dbmd.getDatabaseProductName().toLowerCase(); if (databaseName.indexOf("oracle") != -1) { databaseType = DATABASE_ORACLE; } else if (databaseName.indexOf("sql server") != -1) { databaseType = DATABASE_SQLSERVER; } else if (databaseName.indexOf("mysql") != -1) { databaseType = DATABASE_MYSQL; } else if (databaseName.indexOf("postgresql") != -1) { databaseType = DATABASE_POSTGRESQL; } else if (databaseName.indexOf("hsql") != -1) { databaseType = DATABASE_HSQLDB; } else { databaseType = DATABASE_GENERAL; } } catch (Exception ex) { logger.error("Error when running getDatabaseType", ex); } finally { DBUtils.closeConnection(connection); } } return databaseType; } /** * Get a connection from the connection pool. The returned connection * must be closed by calling DBUtils.closeConnection() * * @return Connection a new connection from the pool if succeed * @throws SQLException : if cannot get a connection from the pool */ public static Connection getConnection() throws SQLException { Connection conection = null; if (useDatasource) { if (dataSource != null) { conection = dataSource.getConnection(); } } else { if (connectionManager != null) { conection = connectionManager.getConnection(maxTimeToWait); } else { logger.fatal("Assertion: DBUtils.connectionManager == null"); } } if (conection == null) { throw new SQLException("DBUtils: Cannot get connection from Connection Pool."); } return conection; } /** * Use this method to return the connection to the connection pool * Do not use this method to close connection that is not from * the connection pool * @param connection : the connection that needs to be returned to the pool */ public static void closeConnection(Connection connection) { if (connection == null){ return; } if (useDatasource) { try { connection.close(); } catch (SQLException e) { logger.error("DBUtils: Cannot close connection.", e); } } else { try { connectionManager.freeConnection(connection); } catch (SQLException ex) { // } } } /** * Use this method to reset the MaxRows and FetchSize of the Statement * to the default values * @param statement : the statement that needs to be reseted */ public static void resetStatement(Statement statement) { if (statement != null) { try { statement.setMaxRows(0); //reset to the default value } catch (SQLException e) { logger.error("DBUtils: Cannot reset statement MaxRows.", e); } try { statement.setFetchSize(0); //reset to the default value } catch (SQLException sqle) { //do nothing, postgreSQL doesnt support this method } } } /** * Use this method to close the Statement * @param statement : the statement that needs to be closed */ public static void closeStatement(Statement statement) { try { if (statement != null){ statement.close(); } } catch (SQLException e) { logger.error("DBUtils: Cannot close statement.", e); } } /** * Use this method to close the ResultSet * @param rs : the resultset that needs to be closed */ public static void closeResultSet(ResultSet rs) { try { if (rs != null){ rs.close(); } } catch (SQLException e) { logger.error("DBUtils: Cannot close resultset.", e); } } /* public static void main(String[] args) { //DBUtils DBUtils1 = new DBUtils(); //log.info("i = " + dataSource1); }*/ }
import java.util.ResourceBundle; import java.util.MissingResourceException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * DBOptions * */ class DBOptions { private static Log logger = LogFactory.getLog(DBOptions.class); properties = new Properties(); InputStream is = null; try { is = getClass().getResourceAsStream("system.properties"); properties.load(is); logger.info("Loaded the Property file... system.properties"); } catch (Exception exception) { logger.fatal("Can't read the properties file. /system.properties"); } finally { try { if (is != null) { is.close(); } } catch (IOException exception) { // ignored } } //default values boolean useDatasource = false; // MUST NOT refer to DBUtils, not we will get an infinite recurse int databaseType = 0; //DATABASE_UNKNOWN // if useDatasource = true String datasourceName = ""; // if useDatasource = false String driverClassName = "org.gjt.mm.mysql.Driver"; String databaseURL = "jdbc:mysql://localhost/test"; String databaseUser = "user"; String databasePassword = "password"; int maxConnection = 20; int maxTimeToWait = 2000;// 2 seconds DBOptions() { try { String strUseDatasource = "false"; try { strUseDatasource = cfg.getValue("USE_DATASOURCE").trim(); } catch (MissingResourceException ex) { // ignore exception } try { databaseType = Integer.parseInt(cfg.getValue("DATABASE_TYPE").trim()); } catch (Exception ex) { logger.error("Fail to read DATABASE_TYPE, use default value = " + databaseType); } if (strUseDatasource.equals("true")) { useDatasource = true; datasourceName = cfg.getValue("DATASOURCE_NAME").trim(); } else { useDatasource = false; driverClassName = cfg.getValue("DRIVER_CLASS_NAME").trim(); databaseURL = cfg.getValue("DATABASE_URL").trim(); databaseUser = cfg.getValue("DATABASE_USER").trim(); databasePassword = cfg.getValue("DATABASE_PASSWORD").trim(); try { maxConnection = Integer.parseInt(cfg.getValue("DATABASE_MAXCONNECTION").trim()); } catch (Exception ex) { logger.error("Fail to read DATABASE_MAXCONNECTION, use default value = " + maxConnection, ex); } try { maxTimeToWait = Integer.parseInt(cfg.getValue("MAX_TIME_TO_WAIT").trim()); } catch (Exception ex) { logger.error("Fail to read MAX_TIME_TO_WAIT, use default value = " + maxTimeToWait, ex); } } } catch (Exception e) { String message = "system.properties: Can't read the properties file. Make sure the file is in your CLASSPATH"; logger.error(message, e); } }//constructor }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]