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: [email protected]
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]