0

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();
    }
Lemmy
  • 397
  • 8
  • 18

2 Answers2

1

You might want to look at JdbcTemplate from the spring framework. You can use it standalone, as Spring has the claim to provide many helper classes. That provides a simplification for the connection/statement/resultset nesting problem. Also it handles the querying simpler.

I know for learning purposes you probably won't use JdbcTemplate, but the class design is interesting.

On pooling there already is an answer from @duffymo.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • Thanks I will take a look at that. I'm still not clear whether I am on the wrong track with the existing approach though. All the examples I can find use a datasource set on the web server. – Lemmy Feb 16 '12 at 13:58
  • I found this example, which is a similar approach with a static datasource: http://stackoverflow.com/questions/1458693/jdbc-connection-pooling-using-c3p0 – Lemmy Feb 16 '12 at 14:33
  • If you're just looking for confirmation, what are you here for? – duffymo Feb 16 '12 at 18:20
  • 1
    @duffymo : as I point out in my reply to Joop's helpful answer, the original question still has not been answered. Therefore I provided some context for anyone else who is also interested in finding a reply to the question. I'm not looking for confirmation. If you don't have anything constructive to add, what are you here for? – Lemmy Feb 24 '12 at 19:13
  • Hi Lemmy, I'll put my rep here up against yours every day of the week. And look at that, Joop pointed out my answer as being pertinent. It seems to me that you're looking for confirmation. – duffymo Feb 24 '12 at 19:23
  • Hi, I just noticed your response. Not very constructive was it. I'm sure your 'rep' is very important to you. So I'm not sure why you persist in posting irrelevant responses. Your original answer completely misunderstood the question. Then you suggested a library to use rather than addressing the actual question. Some of us are interested in actually understanding code rather than choosing from other people's libraries. Anyway, feel free to add more ad hominem remarks, and good luck to you. – Lemmy Apr 26 '12 at 20:45
  • @Lemmy, thanks, I just got red ears, because you are dead right: I let myself answer to just point to an alternative "better" formulation. – Joop Eggen Apr 26 '12 at 22:22
  • Hi Joop, no problem - I found your answer constructive. My comment was directed at the other guy, duffymo. – Lemmy Apr 27 '12 at 09:15
0

I think this is the wrong idea in every way.

You want multiple connections in a connection pool. Let the pool manage the lifecycle; it'll amortize the creation cost over every request.

A singleton will mean one request for every one. That makes no sense to me.

Your app should use connections this way: one per request. Acquire it, use it, return it to the pool in the scope of a single method. It'll scale better that way. Less code for you to write as well. Set it up as a JNDI data resource and you're good to go.

duffymo
  • 305,152
  • 44
  • 369
  • 561
  • 1
    The singleton means one datasource. But the datasource provides multiple connections. Or do I have that wrong? – Lemmy Feb 16 '12 at 12:13
  • The idea is to prevent a new datasource being instantiated every time a db connection is required, and to make sure that the one datasource is used along with its connection pool. – Lemmy Feb 16 '12 at 13:45
  • You're reinventing a wheel here. I agree with Joop Eggen: Spring's SimpleJdbcTemplate does it better than you ever will. I wouldn't write my own. – duffymo Feb 16 '12 at 13:50