Boa tarde galera…
é o seguinte, tenho um programa aki rodando no tomcat 4.1.24 que utiliza o pool de conexões de conexões gerenciado pelo próprio servidor. O que acontece é que o servidor tem aberto uma conexão para cada usuário e após algum tempo de uso o programa não consegue mais obter conexões e trava. Alguém tem alguma idéia??
Abaixo segue as configurações e o código fonte das classes que estou utilizando:
##Configuração do server.xml##
<Context path="MyApp" docBase="C:\\MyApp" debug="5" reloadable="true" crossContext="true" charsetMapperClass="org.apache.catalina.util.CharsetMapper">
<Logger className="org.apache.catalina.logger.FileLogger" prefix="localhost_myapp_log." suffix=".txt" timestamp="true"/>
<Resource name="jdbc/mydb" auth="Container" type="javax.sql.DataSource"/>
<ResourceParams name="jdbc/mydb">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>org.postgresql.Driver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:postgresql://servidor/mydb</value>
</parameter>
<parameter>
<name>username</name>
<value>user</value>
</parameter>
<parameter>
<name>password</name>
<value>passwd</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>1</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>0</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>5000</value>
</parameter>
<parameter>
<name>removeAbandoned</name>
<value>true</value>
</parameter>
<parameter>
<name>removeAbandonedTimeout</name>
<value>20</value>
</parameter>
<parameter>
<name>logAbandoned</name>
<value>true</value>
</parameter>
</ResourceParams>
</Context>
##Classe que retorna as conexões do pool##
package myapp.sql;
import javax.sql.DataSource;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.sql.Connection;
import java.sql.SQLException;
/**
* Classe que implementa a tecnologia JNDI para acesso ao banco de dados. Esta
* tecnologia também oferece suporte ao Pool de conexão, controlada pelo
* WebServer( Tomcat ).
*
* @author Diego R. Drumond
* @version 1.0 13.08.2004
*/
public class DataSourceConnection
{
/**
* String para recuperar o objeto via JNDI
*/
public static final String JNDI_URL = "java:/comp/env/jdbc/myapp";
/**
*
*/
private String JNDI_JDBC = null;
/**
* Retorna um DataSource com a conexão com o banco de dados feita através de
* JNDI.
*/
protected DataSource ds = null;
/**
* Retorna contexto da aplicação que contém o JNDI que será utilizado para
* conexão com o banco de dados.
*/
protected InitialContext ic = null;
public DataSourceConnection( ) throws NamingException
{
this.ic = new InitialContext( );
this.ds = ( DataSource )ic.lookup( adi.componentes.sql.DataSourceConnection.JNDI_URL );
}
/**
* Método que retorna uma conexão com o banco de dados. Caso não exista mais
* nenhuma conexão a ser aberta, o método aguarda a liberação de uma
* conexão.
*/
public Connection getConexao( ) throws NamingException, SQLException
{
Connection con = null;
if( ds == null || ic == null )
{
ic = new InitialContext( );
ds = ( DataSource )ic.lookup( adi.componentes.sql.DataSourceConnection.JNDI_URL );
}
con = ds.getConnection( );
con.setTransactionIsolation( java.sql.Connection.TRANSACTION_READ_COMMITTED );
return con;
}
/**
* Retorna URL do JNDI que está sendo utilizado.
*/
public String getJNDI_URL( )
{
return DataSourceConnection.JNDI_URL;
}
}
##Quando o usuário acessa o sistema, uma instância deste objeto é criada e inserida à sessão do mesmo.##
package myapp.sql;
import myapp.erros.GeneralException;
import myapp.log.LogDB;
import myapp.log.LogException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.io.PrintWriter;
import javax.naming.NamingException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Classe utilizada na manipulação de dados no banco de dados. Possui métodos de
* abertura e fechamento de conexões, além de métodos para execução de comandos
* SQL.
*
* @author Diego R. Drumond
* @version 1.0 13.08.2004
*/
public class DBConnection
{
/**
* Conexão retornada pela classe DataSourceConnection
*/
private Connection con = null;
/**
* Efetua conexão com o banco dados, verficando se existe alguma conexão
* disponível.
*/
protected DataSourceConnection dsc = null;
/**
* Objeto utilizado para fazer redirecionamento do usuário
*/
private HttpServletResponse response = null;
/**
* Sessão atual do usuário.
*/
protected HttpSession session = null;
/**
* Faz log de acesso ao banco de dados.
*/
protected LogDB log = null;
/**
* Contexto da aplicação.
*/
protected ServletContext application = null;
/**
* Objeto java.sql.Statement para enviar comandos ao banco de dados.
*/
private Statement stmt = null;
/**
* Erro ocorrido durante a execução da classe.
*/
private String erro = null;
/**
* Construtor
*/
public DBConnection( )
{
log = new LogDB( );
}
public DBConnection( Connection con, Statement stmt, DataSourceConnection dsc, LogDB log, ServletContext application, HttpSession session, String erro )
{
this.con = con;
this.stmt = stmt;
this.dsc = dsc;
this.log = log;
this.application = application;
this.session = session;
this.erro = erro;
}
/**
* Define se será usado controle de transação.
*/
public void setAutoCommit( boolean transaction ) throws Exception
{
try
{
if( con != null )
{
con.setAutoCommit( transaction );
}
}
catch( SQLException e )
{
throw trataErro( "setAutoCommit(boolean transaction)", new GeneralException( e ) );
}
}
/**
* Define contexto da aplicação. Obs.: O contexto deve ser definido antes da
* sessão.
*
* @param context Objeto application do JSP.
*/
public void setContext( ServletContext context )
{
this.application = context;
log.setContext( context );
}
/**
* Retorna uma String contendo uma mensagem de erro retornado pelo SGDB
* formatada. Este solicita o código da mensagem de erro ao método
* <code>getCodErro</code>. Depois busca no web.xml a mensagem
* correspondente ao código obtido.
*/
public String getMsgErro( )
{
String err = this.erro;
this.erro = null;
return err;
}
/**
* Define response.
*
* @param response Objeto response do JSP
*/
public void setResponse( HttpServletResponse response )
{
this.response = response;
}
/**
* Define a sessão como a do usuário atual.
*
* @param session Objeto session do JSP.
*/
public void setSessao( HttpSession session )
{
this.session = session;
log.setSessao( session );
log.setJDBC( null );
log.setURL( null );
}
/**
* Abre uma conexão com o banco de dados. A classe DataSourceConnection
* busca uma conexão não utilizada e retorna um objeto do tipo 'Connection'
* que é usado pela classe para execução dos SQL's.
*
* @param transaction Define se será feito controle de transação.
* @return True se uma conexão com o banco de dados for estabelecida.
*/
public boolean abreConexao( boolean transaction ) throws Exception
{
//caso a sessão não tenha sido definida retorna erro.
if( ( this.session == null ) || ( this.application == null ) )
{
//trataErro( "abreConexao(boolean transaction)", new Exception( "Verifique se a sessão e o contexto foram definidos e se nenhum dos valores é [null]." ) );
return false;
}
//
if( this.dsc == null )
throw trataErro( "abreConexao(boolean transaction)", new Exception( "Verifique a chamada ao método 'start'." ) );
try
{
//verifica se já existe uma conexão.
if( con == null )
con = dsc.getConexao( );
//evita abrir outra conexão caso já exista uma ativa.
else if( con.isClosed( ) )
con = dsc.getConexao( );
con.setAutoCommit( !transaction );
stmt = con.createStatement( );
DatabaseMetaData dbmd = con.getMetaData( );
log.setJDBC( dbmd.getDriverName( ) + ", " + dbmd.getDriverVersion( ) );
}
catch( SQLException e )
{
throw trataErro( "abreConexao(boolean transaction)", new GeneralException( e ) );
}
catch( NamingException e )
{
String[] vars =
{
adi.componentes.sql.DataSourceConnection.JNDI_URL )
};
throw trataErro( "setSessao(HttpSession session)", new GeneralException( e, vars ) );
}
System.out.println( "aberta - " + this.con );
return true;
}
/**
* Executa comandos SQL.
*
* @return True se o comando for executado corretamente.
*/
public boolean executa( String sql ) throws Exception
{
if( !abreConexao( true ) )
return false;
try
{
stmt.execute( sql );
}
catch( SQLException e )
{
log.setSQL( sql );
String[] vars =
{
sql,
""
};
throw trataErro( "executa(String sql)", new GeneralException( e, vars ) );
}
return true;
}
/**
* Executa um comando SQL e retorna um ResultSet com os dados retornados
* pelo banco.
*
* @param sql Comando SQL a ser executado.
* @return Instância da classe ResultSet com os dados retornados pela
* execução da Query.
*/
public ResultSet executaQuery( String sql ) throws Exception
{
ResultSet rs = null;
if( !abreConexao( true ) )
return rs;
try
{
rs = stmt.executeQuery( sql );
}
catch( SQLException e )
{
log.setSQL( sql );
String[] vars =
{
sql,
""
};
throw trataErro( "executaQuery(String sql)", new GeneralException( e, vars ) );
}
return rs;
}
/**
* Executa SQL's do tipo INSERT, UPDATE, DELETE.
*
* @param sql Comando SQL a ser executado.
* @return Número de colunas afetados pela execução do comando.
*/
public int executaUpdate( String sql ) throws Exception
{
int rows = -1;
if( !abreConexao( true ) )
return rows;
try
{
rows = stmt.executeUpdate( sql );
}
catch( SQLException e )
{
log.setSQL( sql );
String[] vars =
{
sql,
""
};
throw trataErro( "executaUpdate(String sql)", new GeneralException( e, vars ) );
}
return rows;
}
/**
* Encerra a conexão com o banco de dados.
*
* @param commit define se será feito commit ou rollback. True = commit.
* @return Retorna True se a conexão com o banco de dados for encerrada.
*/
public boolean fechaConexao( boolean commit )
{
System.out.println( "fechando - " + con );
boolean closed = true;
try
{
if( con.isClosed( ) )
{
con = null;
return closed;
}
}
catch( SQLException e )
{
con = null;
return !closed;
}
catch( NullPointerException e )
{
con = null;
return closed;
}
try
{
//verifica se é feito controle de transação.
if( !con.getAutoCommit( ) )
{
if( commit )
con.commit( );
else
con.rollback( );
}
stmt.close( );
con.close( );
stmt = null;
con = null;
}
catch( SQLException e )
{
con = null;
System.out.println( trataErro( "fechaConexao(boolean commit)", new GeneralException( e ) ) );
}
finally
{
if( stmt != null )
{
try
{
stmt.close( );
}
catch( SQLException e ) { }
stmt = null;
}
if( con != null )
{
try
{
con.close();
}
catch (SQLException e) { }
con = null;
}
}
System.out.println( "fechada!" );
return closed;
}
/**
* Cria um objeto <code>java.sql.PreparedStatement</code> para enviar
* comandos SQL parametrizados para o banco de dados.
*/
public PreparedStatement preparaSQL( String sql ) throws Exception
{
PreparedStatement ps = null;
if( !abreConexao( true ) )
return ps;
try
{
ps = con.prepareStatement( sql );
}
catch( SQLException e )
{
log.setSQL( sql );
String[] vars =
{
sql,
""
};
throw trataErro( "preparaSQL(String sql)", new GeneralException( e, vars ) );
}
return ps;
}
/**
* Inicializa a execução da classe.
*/
public boolean start( ) throws Exception
{
dsc = null;
if( ( this.session == null ) || ( this.application == null ) )
throw trataErro( "setSessao(HttpSession session)", new Exception( "Verifique se o contexto e a sessão foram definidos." ) );
try
{
dsc = new DataSourceConnection( );
log.setJDBC( "" );
log.setURL( dsc.getJNDI_URL( ) );
}
catch( NamingException e )
{
String[] vars =
{
adi.componentes.sql.DataSourceConnection.JNDI_URL )
};
throw trataErro( "setSessao(HttpSession session)", new GeneralException( e, vars ) );
}
catch( Exception e )
{
throw trataErro( "setSessao(HttpSession session)", new Exception( e ) );
}
return true;
}
/**
*
*/
public String getErrorPage( )
{
return application.getInitParameter( "excessoesPath" ) + "/erro.jsp";
}
/**
*
*/
public String getExceptionVar( )
{
int i = 0;
while( session.getAttribute( "exception" + i ) != null )
i++;
return "exception"+i;
}
/**
* Gera log.
*/
protected Exception trataErro( String metodo, Exception exception )
{
fechaConexao( false );
this.erro = String.valueOf( exception );
log.setMetodo( "adi.componentes.sql.DBConnection." + metodo );
log.setException( String.valueOf( exception ) );
try
{
log.gerarLog( );
}
catch( LogException e )
{
}
return exception;
/*
this.session.setAttribute( "exception", exception );
if( response != null )
{
this.erro = null;
try
{
//response.sendRedirect( application.getInitParameter( "excessoesPath" ) + "/erro.jsp" + "?redirect=1" );
response.resetBuffer( );
response.reset( );
response.sendError( 500, exception.toString( ) );
}
catch( Exception e )
{
System.out.println( "Erro de redirect - " + e );
/*
try
{
response.reset( );
response.setContentType( "text/html" );
PrintWriter out = response.getWriter( );
//out.flush( );
out.write( "<html><head>" );
out.write( "<script>top.location.href='" + application.getInitParameter( "excessoesPath" ) + "/erro.jsp" + "?redirect=2'</script>" );
out.write( "</head></html>" );
out.flush( );
response.flushBuffer( );
//força toda a liberação do buffer.
while( response.isCommitted( ) );
}
catch( Exception e1 )
{
System.out.println( "Erro de redirecionamento do usuário > " + e1 );
}
}
}
}
catch( LogException e )
{
}
*/
}
/**
* Retorna objeto Connection utilizado pela classe.
*/
public Connection getConnection( )
{
return this.con;
}
/**
*
*/
public Object clone( ) throws CloneNotSupportedException
{
return new DBConnection( con, stmt, dsc, log, application, session, erro );
}
}
Bom… são esses ai os arquivos… obrigado pela atenção… Flws!