I have a java web app running in Blackboard learning software, which uses Tomcat 5.5. The app connects to an external database.
I don't have access to declare a datasource on the Blackboard server, so I am trying to package everything in the web app. I have had a problem with my commons-based pooling approach running out of connections, in spite of carefully closing all resultsets, statements and connections after use. I am now switching to a C3P0 pooling method, but I'm not sure that my general approach is correct.
I am using a singleton class to create a datasource, with the aim of minimizing the creation and destruction of datasources which implement connection pooling. The following classes should illustrate this clearly. Is this a reasonable approach, or is it likely to have contributed to my previous problem of running out of connections?
Thanks.
EDIT. Updated question to clarify purpose of singleton approach. I am trying to avoid creating a datasource everytime I need a db connection. This seems to nullify the benefits of having connection pooling.
Datasource class:
import java.beans.PropertyVetoException;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import com.mchange.v2.c3p0.*;
public class MyDataSource {
private static MyDataSource mds = new MyDataSource();
public static DataSource ds;
private MyDataSource() {
try {
ds = getDataSource();
} catch (NamingException e) {
e.printStackTrace();
}
}
public static MyDataSource getInstance(){
return mds;
}
public Connection getConnection() throws SQLException, NamingException {
Connection myConnect = ds.getConnection();
return myConnect;
}
private DataSource getDataSource() throws NamingException {
ComboPooledDataSource cpds = new ComboPooledDataSource();
try {
cpds.setDriverClass( "com.mysql.jdbc.Driver" );
} catch (PropertyVetoException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
cpds.setJdbcUrl( "jdbc:mysql://195.195.xx.xx:3306/dbName" );
cpds.setUser("lemmy");
cpds.setPassword("xxx");
cpds.setMaxIdleTime(180);
cpds.setMaxPoolSize(100);
return cpds;
}
}
Connection class:
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
public class DbConnection {
public Connection c;
public DbConnection() throws NamingException, SQLException {
c = getConnection();
}
public Connection getConnection() throws SQLException, NamingException {
Connection myConnect = MyDataSource.getInstance().getConnection();
return myConnect;
}
public void close(){
JDBCUtils.close(this.c);
}
}
Closing connections etc.
import java.sql.*;
public class JDBCUtils {
static public void close (ResultSet rs) {
try { if (rs!=null) rs.close(); } catch (Exception e) {}
}
// Works for PreparedStatement also since it extends Statement.
static public void close (Statement stmt) {
try { if (stmt!=null) stmt.close(); } catch (Exception e) {}
}
static public void close (java.sql.Connection conn) {
try { if (conn!=null) conn.close(); } catch (Exception e) {}
}
}
Example usage:
String myQuery = null;
DbConnection myConnect = null;
Statement myStatement = null;
ResultSet rs = null;
try {
myConnect = new DbConnection();
myStatement = myConnect.c.createStatement();
// Do stuff here
}catch (SQLException e) {
out.println("SQL Error: "+e);
} finally {
JDBCUtils.close(rs);
JDBCUtils.close(myStatement);
myConnect.close();
}