Estou utilizando Spring/Hibernate para fazer a conexão de dados com o MySQL e utilizando o Tomcat.
Tenho duas aplicações rodando distintamente na mesma instância do Tomcat, uma é meu Webservice Restfull que compõe a parte de inserção/busca/deleção de dados e um frontend JSF/Richfaces consumindo estes serviços.
Inicio o Tomcat normalmente, a aplicação sobe e tudo roda normal, até um momento que acontece algo (provavelmente um erro da aplicação) e tenho a mensagem mascarada:
MySQLNonTransientConnectionException: could not create connection to database server Attempted to reconnect 3 times.
Ai a parte web para de funcionar e não consigo utilizar mais nada…
Meu MySQL esta recusando a conexão por algum motivo que não sei e minha aplicação não roda mais, como posso proceder neste caso e qual o motivo de o MySQL recusar a conexão após acontecer um erro em meu software?
Alguma solução para que mesmo após um erro no sistema, o MySQL parar de recusar minha conexão?
Grato, Edson.
nao seria pq sua conexao fica idle por muito tempo então é fechada, dai no momento que vai ser reutilizada acontece isso?
vc tem um pool de conexoes?
abrasss
[quote=renanreismartins]nao seria pq sua conexao fica idle por muito tempo então é fechada, dai no momento que vai ser reutilizada acontece isso?
vc tem um pool de conexoes?
abrasss[/quote]
Opa não sou eu que gerencio a conexão em si…
o Hibernate faz isso pra mim, mas esta configurado no aplicationContext.xml …
porém eu abro e fecho seções com o banco a partir do meu dao utilizando um gerenciador de transações…
então não sei se o problema esta ai, mas vou colocar o código :
<!-- Connection Pool -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- JPA EntityManagerFactory -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="${jdbc.database}"/>
<property name="showSql" value="${jdbc.showSql}"/>
</bean>
</property>
</bean>
public void addUsuarios(Usuarios usuarios) throws Exception {
try {
usuariosDAO.createSession();
List<Usuarios> listUsuario = usuariosDAO.selectUsuarios(usuarios.getId(),usuarios.getUsuario());
if(listUsuario == null || listUsuario.size() > 0){
throw new Exception("Usuário já existênte = " + usuarios.getUsuario());
}
List<Empresas> listEmpresas = empresasDAO.selectEmpresas(usuarios.getEmpresa());
if(listEmpresas == null || listEmpresas.size() == 0){
throw new Exception("Não existe Empresas com id = " + usuarios.getEmpresa().getIdEmpresa());
}
usuarios.setEmpresa(listEmpresas.get(0));
List<Usuarios> list = new ArrayList<Usuarios>();
list.add(usuarios);
usuariosDAO.addUsuarios(list, true);
usuariosDAO.closeSession();
} catch (Exception e) {
throw e;
}
}
@Override
public void deleteUsuarios(Usuarios usuarios) throws Exception {
try {
usuariosDAO.createSession();
List<Usuarios> list = new ArrayList<Usuarios>();
if (usuarios == null)
throw new Exception("null pointer exception");
list = usuariosDAO.selectUsuarios(usuarios);
usuariosDAO.deleteUsuarios(list, true);
usuariosDAO.closeSession();
} catch (Exception e) {
throw e;
}
}
package com.gaia.tracker.dao;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.id.SequenceIdentityGenerator.Delegate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
@Repository
@Component
public abstract class GerenciadorDAO {
@PersistenceContext(type = PersistenceContextType.EXTENDED)
protected EntityManager entityManagerFactory;
Session session;
Transaction tx;
public boolean createSession() {
try {
if (session == null) {
session = (Session) entityManagerFactory.getDelegate();
}
if (!session.isOpen()) {
session = session.getSessionFactory().openSession();
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public boolean createTransaction() {
try {
if (session == null || !session.isOpen()) {
session = (Session) entityManagerFactory.getDelegate();
}
if (tx == null || !tx.isActive()) {
tx = session.getTransaction();
tx.begin();
return true;
}
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public boolean closeSession() {
try {
if (session == null || !session.isOpen()) {
return false;
} else {
session.close();
return true;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public boolean commitTransaction() {
try {
if (tx != null || tx.isActive()) {
tx.commit();
return true;
}
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public boolean rollbackTransaction() {
try {
if (tx != null || tx.isActive()) {
tx.rollback();
return true;
}
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public Session getSession() {
return session;
}
public Transaction getTransaction() {
return tx;
}
}
edson, esse erro ocorre após algumas horas da aplicação rodando certo? tenta setar o idleConnectionTestPeriod do pool.
Fugindo um pouco do contexto, apenas algumas sugestões ok?
se vc usa spring seria mais interessante usar o controle transacional do proprio framework ao inves de controlar isso na mao.
Outra coisa que nao faz mto sentido é capturar uma Exception e depois relançar a mesma exception.
abrasssss
[quote=renanreismartins]edson, esse erro ocorre após algumas horas da aplicação rodando certo? tenta setar o idleConnectionTestPeriod do pool.
Fugindo um pouco do contexto, apenas algumas sugestões ok?
se vc usa spring seria mais interessante usar o controle transacional do proprio framework ao inves de controlar isso na mao.
Outra coisa que nao faz mto sentido é capturar uma Exception e depois relançar a mesma exception.
abrasssss[/quote]
Fala renanreismartins, obrigado pela resposta, eu utilizei o controle de transações a mão pois não sabia utilizar o gerenciador de transações do Spring, mas vou dar uma estudada para implementa-lo corretamente.
em relação a jogar as exceções, eu preciso sim, pois se eu simplesmente tratá-las fechando as transações, o problema vai morrer ali e meu web service não vai conseguir dar uma resposta de erro para o cliente…
Eu tinha a necessidade de retorno nulo, erro ou lista para os selects, então para deixar os daos da mesma forma resolvi jogar as exceções também para os add e delete ao invés de utilizar um retorno booleano.
Vou testar as propriedades do c3p0 depois respondo como resolvi.
[quote=renanreismartins]edson, esse erro ocorre após algumas horas da aplicação rodando certo? tenta setar o idleConnectionTestPeriod do pool.
Fugindo um pouco do contexto, apenas algumas sugestões ok?
se vc usa spring seria mais interessante usar o controle transacional do proprio framework ao inves de controlar isso na mao.
Outra coisa que nao faz mto sentido é capturar uma Exception e depois relançar a mesma exception.
abrasssss[/quote]
Não ajudou muito setar os valores do c3p0, utilizei vários valores para idleConnectionTestPeriod:
<!-- Connection Pool -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<!-- <property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" /> -->
<property name="properties">
<props>
<prop key="c3p0.idle_test_period">${jdbc.idleConnectionTestPeriod}</prop>
<prop key="c3p0.acquire_increment">${jdbc.acquireIncrement}</prop>
<prop key="c3p0.timeout">${jdbc.maxIdleTime}</prop>
<prop key="c3p0.max_size">${jdbc.maxPoolSize}</prop>
<prop key="c3p0.max_statements">${jdbc.maxStatements}</prop>
<prop key="c3p0.min_size">${jdbc.minPoolSize}</prop>
<prop key="user">${jdbc.username}</prop>
<prop key="password">${jdbc.password}</prop>
</props>
</property>
</bean>
jdbc.acquireIncrement=5
jdbc.maxIdleTime=30
jdbc.idleConnectionTestPeriod=?
jdbc.maxPoolSize=100
jdbc.maxStatements=0
jdbc.minPoolSize=1
porém descobri que quando baixo o serviço do MySQL e depois reinicio, o console para de dar o erro que coloquei abaixo e a app volta a funcionar normalmente.
2013-01-04 11:21:50,190 DEBUG [com.mchange.v2.resourcepool.BasicResourcePool] -
<An exception occurred while acquiring a resource.>
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not
create connection to database server. Attempted reconnect 3 times. Giving up.
at sun.reflect.GeneratedConstructorAccessor225.newInstance(Unknown Sourc
e)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingC
onstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1013)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
at com.mysql.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:
2291)
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2212)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:797)
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
at sun.reflect.GeneratedConstructorAccessor59.newInstance(Unknown Source
)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingC
onstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:389)
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java
:305)
at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManag
erDataSource.java:88)
at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnecti
on(WrapperConnectionPoolDataSource.java:109)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1.acquireResource(C
3P0PooledConnectionPool.java:89)
at com.mchange.v2.resourcepool.BasicResourcePool.acquireUntil(BasicResou
rcePool.java:665)
at com.mchange.v2.resourcepool.BasicResourcePool.access$500(BasicResourc
ePool.java:32)
at com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run(BasicRe
sourcePool.java:1206)
at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(Thre
adPoolAsynchronousRunner.java:368)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:
Too many connections
at sun.reflect.GeneratedConstructorAccessor225.newInstance(Unknown Sourc
e)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingC
onstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1013)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4098)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4030)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:951)
at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(My
sqlIO.java:1717)
at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1276)
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2389)
at com.mysql.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:
2230)
... 16 more
mto estranho sua app estar funcionando e depois do nada parar, só consigo pensar no erro que citei, o q vc colocou em idleConnectionTestPeriod?
abrasss
Agora estou utilizando com o valor 100 que vi em um dos foruns aqui do GUJ…
To tentando capturar o erro agora com o log4j, deve ser alguma configuração do MySQL para bloquear conexões com erros, alguém amais tem alguma ideia?
Sabem se isso pode ocorrer por algum erro na parte UI da aplicação?
Lembrando que estou trabalhando com um web service, mas tanto a parte de frontEND quanto de BackEND estão rodando no mesmo Tomcat
sera que suas sessions estao sendo fechadas realmente?
Opa, passei toda a gerência de transações para o Spring cuidar e mesmo assim deu erro, ou seja, não estão ficando sessions para trás…
Agora tenho a impressão que é algum tipo de configuração do MySQL…
Mais alguma possibilidade?
Consegui resolver o problema adicionando max_connections maior que o valor de maxPoolSize nas configuração do my.ini .
O numero de conexões configuradas em maxPoolSize do applicationContext.xml era maior que o número de conexões permitidas pelas configurações do MySQL, entâo quando o número de conexões aumentava NO POOL, tinha-se ESTOURO DE CONEXÕES.
excelente edson, parabens
abrasss