Pool de conexões não funciona como deveria!

8 respostas
G

Estava fazendo uma inserção no banco, deixei ele ligado a noite toda, e quando cheguei hoje me deparei com a seguinte exceção:

org.postgresql.util.PSQLException: FATAL: sorry, too many clients already
        at org.postgresql.core.v3.ConnectionFactoryImpl.readStartupMessages(ConnectionFactoryImpl.java:444)
        at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:99)
        at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:66)
        at org.postgresql.jdbc2.AbstractJdbc2Connection.<init>(AbstractJdbc2Connection.java:124)
        at org.postgresql.jdbc3.AbstractJdbc3Connection.<init>(AbstractJdbc3Connection.java:30)
        at org.postgresql.jdbc4.AbstractJdbc4Connection.<init>(AbstractJdbc4Connection.java:29)
        at org.postgresql.jdbc4.Jdbc4Connection.<init>(Jdbc4Connection.java:24)
        at org.postgresql.Driver.makeConnection(Driver.java:386)
        at org.postgresql.Driver.connect(Driver.java:260)
        at java.sql.DriverManager.getConnection(DriverManager.java:582)
        at java.sql.DriverManager.getConnection(DriverManager.java:185)
        at org.apache.commons.dbcp.DriverManagerConnectionFactory.createConnection(DriverManagerConnectionFactory.java:65)
        at org.apache.commons.dbcp.PoolableConnectionFactory.makeObject(PoolableConnectionFactory.java:294)
        at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:840)
        at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:96)
        at dao.FabricaConexao.getConnection(FabricaConexao.java:132)
        at dao.Consulta.<init>(Consulta.java:14)
        at execution.InsertDomain.inserirDominio(InsertDomain.java:10)
        at execution.MainExe.main(MainExe.java:19)
Será que o pool que foi feito não está fazendo sua função? Minha Fabrica de Conexão é a seguinte:
package dao;

public class FabricaConexao {

        public static Connection getConnection(){
            try {
            	Class.forName("org.postgresql.Driver");
                 } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                 }

        DataSource dataSource = setupDataSource("jdbc:postgresql://10.0.0.210:5432/myDB");

        Connection conn = null;

        try {

            conn = dataSource.getConnection();
            
            return conn;
            
            } catch(SQLException e) {
            	e.printStackTrace();
            }
            
            return conn;
	}

    public static DataSource setupDataSource(String connectURI) {

        ObjectPool connectionPool = new GenericObjectPool(null);

        ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(connectURI,"postgres", "password");

        PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory,connectionPool,null,null,false,true);

        PoolingDataSource dataSource = new PoolingDataSource(connectionPool);

        return dataSource;
    }
}

Obrigado!

8 Respostas

T

Quem abre fecha e quem pega emprestado devolve. As conexões estão sendo fechadas explicitamente no código?

G

Obrigado thingol, acho que consegui resolver… vou deixar ele rodando aqui pra testar, mas o que você falou eu ja tinha colocado no código só que dentro de um método que criava uma nova instância de Connection, agora estou passando o objeto conn pelo parâmetro do método e creio que isso resolverá o problema.
Qualquer coisa eu voltarei a posta…

Muito Obrigado!

G

Bom, Pensava que tudo estava dando certo, até que um certo ponto hoje a exceção voltou… peguei o fonte diretamente do site da Apache e pensava que iria funcionar normalmente… por favor, me deêm alguma luz… o que está errado?

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package dao;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;

//
// Here are the dbcp-specific classes.
// Note that they are only used in the setupDataSource
// method. In normal use, your classes interact
// only with the standard JDBC API
//
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.commons.dbcp.ConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.DriverManagerConnectionFactory;

//
// Here's a simple example of how to use the PoolingDataSource.
// In this example, we'll construct the PoolingDataSource manually,
// just to show how the pieces fit together, but you could also
// configure it using an external conifguration file in
// JOCL format (and eventually Digester).
//

//
// Note that this example is very similiar to the PoolingDriver
// example.  In fact, you could use the same pool in both a
// PoolingDriver and a PoolingDataSource
//

//
// To compile this example, you'll want:
//  * commons-poo-1.3.jar
//  * commons-dbcp-1.2.2.jar
//  * j2ee.jar (for the javax.sql classes)
// in your classpath.
//
// To run this example, you'll want:
//  * commons-poo-1.3.jar
//  * commons-dbcp-1.2.2.jar
//  * j2ee.jar (for the javax.sql classes)
//  * the classes for your (underlying) JDBC driver
// in your classpath.
//
// Invoke the class using two arguments:
//  * the connect string for your underlying JDBC driver
//  * the query you'd like to execute
// You'll also want to ensure your underlying JDBC driver
// is registered.  You can use the "jdbc.drivers"
// property to do this.
//
// For example:
//  java -Djdbc.drivers=oracle.jdbc.driver.OracleDriver \
//       -classpath commons-pool-1.3.jar:commons-dbcp-1.2.2.jar:j2ee.jar:oracle-jdbc.jar:. \
//       ManualPoolingDataSourceExample
//       "jdbc:oracle:thin:scott/tiger@myhost:1521:mysid"
//       "SELECT * FROM DUAL"
//
public class ConnectionFac {

    //public static void main(String[] args) {
    public static boolean getConnection(String tipo, String domain){	
    	//String tipo = "setDomain", domain = "testedogustavositer.com.br";
        //
        // First we load the underlying JDBC driver.
        // You need this if you don't use the jdbc.drivers
        // system property.
        //
        //System.out.println("Loading underlying JDBC driver.");
        try {
            Class.forName("org.postgresql.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //System.out.println("Done.");

        //
        // Then, we set up the PoolingDataSource.
        // Normally this would be handled auto-magically by
        // an external configuration, but in this example we'll
        // do it manually.
        //
        //System.out.println("Setting up data source.");
        DataSource dataSource = setupDataSource("jdbc:postgresql://10.0.0.210:5432/myDB");
        //System.out.println("Done.");

        //
        // Now, we can use JDBC DataSource as we normally would.
        //
        Connection conn = null;
        Statement stmt = null;
        ResultSet rset = null;
        boolean result = false;

        try {
            //System.out.println("Creating connection.");
            conn = dataSource.getConnection();
            //System.out.println("Creating statement.");
            stmt = conn.createStatement();
            //System.out.println("Executing statement.");
            
            if(tipo.equalsIgnoreCase("isInDB")){
            	result = isInDataBase(domain, rset, stmt);
            }else if(tipo.equalsIgnoreCase("setDomain")){
            	setDomainDB(domain, stmt);
            }
            
        } catch(SQLException e) {
            e.printStackTrace();
        } finally {
            try { rset.close(); } catch(Exception e) { }
            try { stmt.close(); } catch(Exception e) { }
            try { conn.close(); } catch(Exception e) { }
        }
        
        //System.out.println("Result " + result);
        return result;
    }

    public static DataSource setupDataSource(String connectURI) {
        //
        // First, we'll need a ObjectPool that serves as the
        // actual pool of connections.
        //
        // We'll use a GenericObjectPool instance, although
        // any ObjectPool implementation will suffice.
        //
        ObjectPool connectionPool = new GenericObjectPool(null);

        //
        // Next, we'll create a ConnectionFactory that the
        // pool will use to create Connections.
        // We'll use the DriverManagerConnectionFactory,
        // using the connect string passed in the command line
        // arguments.
        //
        ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(connectURI, "postgres", "mypassword");

        //
        // Now we'll create the PoolableConnectionFactory, which wraps
        // the "real" Connections created by the ConnectionFactory with
        // the classes that implement the pooling functionality.
        //
        PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory,connectionPool,null,null,false,true);

        //
        // Finally, we create the PoolingDriver itself,
        // passing in the object pool we created.
        //
        PoolingDataSource dataSource = new PoolingDataSource(connectionPool);

        return dataSource;
    }
    
	public static void setDomainDB(String domain, Statement stmt) throws SQLException{
		
		System.out.println("Inserindo o domínio: " + domain);

		stmt.executeUpdate("insert into domains (dominio) values ('" + domain + "')");

	}
	
	public static boolean isInDataBase(String domain, ResultSet rset, Statement stmt) throws SQLException{
		
			rset = stmt.executeQuery("select * from domains where dominio = '" + domain + "'");
			
			if(rset.next() == true){
				return true;
			}

		return false;
	}    
}

E a exceção é exatamente a mesma que eu postei… alguém, por favor?

F

Você esta fechando as conexões, resultsets e statement que são abertos?

G

Estou fechando eles nas seguintes linhas:

} finally {  
            try { rset.close(); } catch(Exception e) { }  
            try { stmt.close(); } catch(Exception e) { }  
            try { conn.close(); } catch(Exception e) { }  
        }

Não está certo???

PS: Esta exceção ocorre depois de um bom tempo rodando… ocorre de tempos em tempos, mas creio que com o pool implementado isso não deveria acontecer, certo?

A

Usar um pool simplesmente não vai resolver seus problemas. É preciso verificar como está a configuração do pool (quantas conexões poderão ser abertas ao mesmo tempo) e se vc está fechando todas as conexões abertas. Se sua aplicação precisar abrir 10 conexões ao mesmo tempo e vc tiver apenas 5 conexões máximas configurado, isso vai gerar um problema.

G

andrepestana:

PS: Esta exceção ocorre depois de um bom tempo rodando… ocorre de tempos em tempos, mas creio que com o pool implementado isso não deveria acontecer, certo?

Usar um pool simplesmente não vai resolver seus problemas. É preciso verificar como está a configuração do pool (quantas conexões poderão ser abertas ao mesmo tempo) e se vc está fechando todas as conexões abertas. Se sua aplicação precisar abrir 10 conexões ao mesmo tempo e vc tiver apenas 5 conexões máximas configurado, isso vai gerar um problema.

Valeu andrepestana!
Mas aonde eu verifico isso? pois este é o exemplo que possui no site do Apache, e pelo que eu me lembre não vi nada a respeito de configurações de conexões neste exemplo… isto tem que ser definido em algum arquivo de configuração do próprio BD? (postgreSQL)

Muito Obrigado.

A

Alguém tem algum código que funcione, para Pool de Conexão?

Criado 29 de maio de 2009
Ultima resposta 8 de fev. de 2011
Respostas 8
Participantes 5