Thread: PGPoolingDataSource problem.

PGPoolingDataSource problem.

From
Date:

I am using the JDBC3 PGPoolingDataSource to create a pool of 5 connections (for test) to my database.

 

public class DatabasePool {

      private static PGPoolingDataSource dbp = null;

      private static Connection conn = null;

     

      public static PGPoolingDataSource getInstance(){

            if (dbp == null){

                  dbp = new PGPoolingDataSource();

                 

                  try{

                        PGPoolingDataSource source = new PGPoolingDataSource();

                        source.setDataSourceName("DataSource");

                        source.setServerName("XX.XX.XX.XX");

                        source.setDatabaseName("dbname");

                        source.setUser("user");

                        source.setPassword("password");

                        source.setMaxConnections(5);

                       

                        dbp = source;

                  }catch(Exception e){

                        e.printStackTrace();

                  }

            }

           

            return dbp;

      }

     

      public Connection getConnection(){

            PGPoolingDataSource pgdb = (PGPoolingDataSource)getInstance();

            conn = null;

           

            try{

                  conn = pgdb.getConnection();

            }catch(Exception e){

                  e.printStackTrace();

            }

           

            return conn;

      }

     

      public static void closeConnection(){

            if (conn != null){

                  try{conn.close();conn = null;}catch(Exception e){}

            }

      }

}

 

I get a leaked connections when I grab more than one connection from the pool at a time.

 

Public void insertData(){

                DatabasePool db = new DatabasePool();

                Try{

                                PreparedStatement ps = db.getConnection().preparedStatement(sql);

                                Ps.setString(1, getValue(XX);

                                Ps.execute();

                }catch(Exception e){

                                e.printStackTrace();

} finally{

                                try{rs.close();rs=null;}catch(Exception e){}

            try{ps.close();ps=null;}catch(Exception e){}

      try{DatabasePool.closeConnection();db=null;}catch(Exception e){}

                }

}

 

Private String getValue(String XX){

                DatabasePool db = new DatabasePool();

                String retVal = “”;

                Try{

                                PreparedStatement ps  = db.getConnection().preparedStatement(sql);

                                ResultSet rs = ps.executeQuery();

                                While (rs.next()){

                                                retVal = rs.getString(1);

                                }

                }catch(Exception e){

                                e.printStackTrace();

}finally{

                                try{rs.close();rs=null;}catch(Exception e){}

            try{ps.close();ps=null;}catch(Exception e){}

      try{DatabasePool.closeConnection();db=null;}catch(Exception e){}

}

}

 

After running through insertData() once, can see 2 connections on the database. But if I run through it again, then there are 3 connections when I expect there to still be only two. It works fine until I hit the maxConnections and then everything craps out. When I move the getValue(XX) to before opening the first connection, everything works as I should.

 

Changed insertData()

 

Public void insertData(){

                DatabasePool db = new DatabasePool();

                Try{

                                String myValue = getValue(XX);

                                PreparedStatement ps = db.getConnection().preparedStatement(sql);

                                Ps.setString(1, myValue);

                                Ps.execute();

                }catch(Exception e){

                                e.printStackTrace();

} finally{

                                try{rs.close();rs=null;}catch(Exception e){}

            try{ps.close();ps=null;}catch(Exception e){}

      try{DatabasePool.closeConnection();db=null;}catch(Exception e){}

                }

}

 

Attachment

Re: PGPoolingDataSource problem.

From
"David Johnston"
Date:
You have two major programming issues:

1) You ignore exceptions
2) You use static variables / singleton pattern without understanding

Get yourself a good debugger, where you can step through the code
line-by-line, and watch what happens to various "connection" variables
during your two procedures.  It will be obvious why and where you "released"
the original connection without closing it.

See notes below (in bold) to help you figure out where to focus your
efforts.

David J.

From: pgsql-jdbc-owner@postgresql.org
[mailto:pgsql-jdbc-owner@postgresql.org] On Behalf Of
Benjamin.Galaviz@LSGSkyChefs.com
Sent: Wednesday, June 08, 2011 1:37 PM
To: pgsql-jdbc@postgresql.org
Subject: [JDBC] PGPoolingDataSource problem.

      private static Connection conn = null;

      public Connection getConnection(){ ---- You are returning a static
variable from a non-static method...
            PGPoolingDataSource pgdb = (PGPoolingDataSource)getInstance();
            conn = null; ---- and what if there was already another
connection present..

            try{
                  conn = pgdb.getConnection();
            }catch(Exception e){
                  e.printStackTrace();
            }

            return conn;
      }

      public static void closeConnection(){
            if (conn != null){
                  try{conn.close();conn = null;}catch(Exception e){} ----
NEVER IGNORE EXCEPTIONS; ESPECIALLY CATCH (Exception e)
            }
      }

      try{DatabasePool.closeConnection();db=null;}catch(Exception e){}
---- NEVER IGNORE EXCEPTIONS; ESPECIALLY CATCH (Exception e)

!!!!!! You are likely capturing - then ignoring - a NullPointerException
here !!!!!!!!!

Private String getValue(String XX){
                                PreparedStatement ps  =
db.getConnection().preparedStatement(sql);
                                ResultSet rs = ps.executeQuery();
                                While (rs.next()){
                                                retVal = rs.getString(1);
                                }
             try{DatabasePool.closeConnection();db=null;}catch(Exception
e){}
       }
}

--- Open and close within the same function is OK IF there was no connection
already open

                                String myValue = getValue(XX);   ----Open
and Close
                                PreparedStatement ps =
db.getConnection().preparedStatement(sql);   --- Open
             try{DatabasePool.closeConnection();db=null;}catch(Exception
e){} ----Close




Re: PGPoolingDataSource problem.

From
Craig Ringer
Date:
On 09/06/11 01:36, Benjamin.Galaviz@LSGSkyChefs.com wrote:
> I am using the JDBC3 PGPoolingDataSource to create a pool of 5
> connections (for test) to my database.

I'd recommend using a proper connection pool like C3P0 or DBCP. It'll be
less work in the long run, as PGPoolingDataSource is more of a
toy/testing tool.

What's your environment, anyway? Are you running in a standalone JVM
(j2SE) or in an application server context? If you're in an appserver or
servlet container you should be getting connections from the container
environment.

--
Craig Ringer

Re: PGPoolingDataSource problem.

From
Radosław Smogura
Date:
 On Thu, 09 Jun 2011 12:07:32 +0800, Craig Ringer wrote:
> On 09/06/11 01:36, Benjamin.Galaviz@LSGSkyChefs.com wrote:
>> I am using the JDBC3 PGPoolingDataSource to create a pool of 5
>> connections (for test) to my database.
>
> I'd recommend using a proper connection pool like C3P0 or DBCP. It'll
> be
> less work in the long run, as PGPoolingDataSource is more of a
> toy/testing tool.
>
> What's your environment, anyway? Are you running in a standalone JVM
> (j2SE) or in an application server context? If you're in an appserver
> or
> servlet container you should be getting connections from the
> container
> environment.
>
> --
> Craig Ringer

 From other posts, it looks like C3P0 is only JDBC2 aware.  so you will
 automatic mange them.

 Actually PoolingDataSource could track leak and add auto-close, I was
 sure it could do this, but I'm wrong.

 Backing to original post...

 From design point of view your implementation in not quite good, bad
 not bad.

 - You use singleton pattern to manage DataSource and it's good.
 - But private static Connection conn = null; should it really be
 static? getConnection is not static this causes leak.
 - And one tip - when I make singleton pattern I, mainly, create for
 class keeping this value private default constructor, so no one who use
 my code will not accidental call new Singleton, instead of
 Singleton.getInstance().
 - Just fix pool, and if you have time wrap your connections managed by
 pool in WeakReference (eventually adding pool to this reference). This
 is how pools are implemented. Everyone know to close connection but
 smart developers know that many forget it, and adding leaking support
 may save your time in future on writing try / catch trees.

 Have a luck.

 Regards,
 Radek


Re: PGPoolingDataSource problem.

From
Craig Ringer
Date:
On 9/06/2011 3:30 PM, Radosław Smogura wrote:

>  From other posts, it looks like C3P0 is only JDBC2 aware. so you will
> automatic mange them.

Eh? What does the JDBC level supported have to do with how you manage
the connections?

Can you link to the posts in question? I'm a bit confused by that.

--
Craig Ringer

Tech-related writing at http://soapyfrogs.blogspot.com/

Re: PGPoolingDataSource problem.

From
Radosław Smogura
Date:
 On Thu, 09 Jun 2011 17:39:05 +0800, Craig Ringer wrote:
> On 9/06/2011 3:30 PM, Radosław Smogura wrote:
>
>>  From other posts, it looks like C3P0 is only JDBC2 aware. so you
>> will
>> automatic mange them.
>
> Eh? What does the JDBC level supported have to do with how you manage
> the connections?
>
> Can you link to the posts in question? I'm a bit confused by that.

 http://archives.postgresql.org/pgsql-jdbc/2011-06/msg00004.php

 It means you may pool, but you will have limited access to other API
 methods.

 Regards,
 Radek

Re: PGPoolingDataSource problem.

From
Chris Wareham
Date:
On 06/08/11 18:36, Benjamin.Galaviz@LSGSkyChefs.com wrote:
> I am using the JDBC3 PGPoolingDataSource to create a pool of 5 connections
> (for test) to my database.
>
> public class DatabasePool {
>

Improved and corrected (albeit untested) versions of your code below -
but please read my comment at the end of this message on why you don't
want to reinvent the wheel.

public class ConnectionFactory {
     private static PGPoolingDataSource ds;

     private ConnectionFactory() {
         // enforce singleton
     }

     private static synchronized DataSource getDataSource() throws
SQLException {
         if (ds == null){
             ds = new PGPoolingDataSource();
             ds.setDataSourceName("DataSource");
             ds.setServerName("XX.XX.XX.XX");
             ds.setDatabaseName("dbname");
             ds.setUser("user");
             ds.setPassword("password");
             ds.setMaxConnections(5);
         }

         return ds;
     }

     public static Connection getConnection() throws SQLException {
         return getDataSource.getConnection();
     }

     public static void releaseConnection(final Connection connection) {
         if (connection != null) {
             try {
                 connection.close();
             } catch (SQLException exception) {
                 // log warning ...
             }
         }
     }
}
>
> I get a leaked connections when I grab more than one connection from the
> pool at a time.
>
> Public void insertData(){
>
> Private String getValue(String XX){
>

public void insertData(final String sql) throws SQLException {
     Connection connection = null;

     try {
         connection = ConnectionFactory.getConnection();

         PreparedStatement ps = connection.preparedStatement(sql);
         ps.setString(1, "foo");
         ps.executeUpdate();
         ps.close();
     } finally{
         ConnectionFactory.releaseConnection(connection);
     }
}

public String getValue(final String sql, final String foo) throws
SQLException {
     String value = null;

     Connection connection = null;

     try {
         connection = ConnectionFactory.getConnection();

         PreparedStatement ps = connection.preparedStatement(sql);

         ResultSet rs = ps.executeQuery();

         if (rs.next()) {
             value = rs.getString(1);
         }

         rs.close();

         ps.close();
     } finally{
         ConnectionFactory.releaseConnection(connection);
     }

     return value;
}

However, you'd be much better served by using a framework that hides
the verboseness of JDBC. The Spring framework has an excellent wrapper
for JDBC that also supports pooling, and deals well with the various
niggles that such a wrapper exposes.

Chris




Chris Wareham
Senior Software Engineer
London & Partners
6th floor,
2 More London Riverside
London SE1 2RR

Tel: +44 (0)20 7234 5848
Fax: +44 (0)20 7234 5753

http://www.londonandpartners.com/


'London & Partners Limited' is registered in England under No.7493460;
Registered Office:London & Partners, City Hall, The Queen's Walk, London SE1 2AA.

London & Partners is the official promotional agency for London attracting and delivering value to businesses, students
andvisitors. London & Partners is a not-for-profit public private partnership, funded by the Mayor of London and our
networkof commercial partners. 

The information contained in this e-mail is confidential and intended for the named recipient(s) only. If you have
receivedit in error, please notify the sender immediately and then delete the message. If you are not the intended
recipient,you must not use, disclose, copy or distribute this email. The views expressed in this e-mail are those of
theindividual and not of London & Partners Limited. We reserve the right to read and monitor any email or attachment
enteringor leaving our systems without prior notice. 

 Please don't print this e-mail unless you really need to.

Re: PGPoolingDataSource problem.

From
Craig Ringer
Date:
On 06/09/2011 06:01 PM, Radosław Smogura wrote:

> It means you may pool, but you will have limited access to other API
> methods.

OK, then use DBCP 1.4, which supports JDBC4, instead of C3P0.

Thanks for the clarification of what you meant.

--
Craig Ringer