Solucionado (ver solução)
Solucionado
(ver solução)
12
respostas

Erro Filter Conexao JPA

Eu criei a abertura e fechando do EntityManager por requisição num Filter. Conforme segue abaixo.

@WebFilter(servletNames ={"Faces Servlet"})
public class JPAFilter implements Filter{

    private EntityManagerFactory factory;

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
        this.factory.close();
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub

        // CHEGADA
        EntityManager manager = this.factory.createEntityManager();
        request.setAttribute("EntityManager", manager);
        manager.getTransaction().begin();        

        // FACES SERVLET
        chain.doFilter(request,response);


        // SAÍDA
        try {

            manager.getTransaction().commit();

        }catch(Exception e) {

            manager.getTransaction().rollback();

        } finally {

            manager.close();

        }

    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub
        this.factory = Persistence.createEntityManagerFactory("portal");

    }

}

Mas quando o sistema fica um tempo ocioso sem utilizar ele começa a dar um erro - org.hibernate.exception.JDBCConnectionException: could not extract ResultSet

O eclipse mostra que o erro esta na linha do filter - manager.getTransaction().rollback();

Alguém poderia me ajudar e me dizer o que seria esse erro ou porque ele esta sendo causado?

12 respostas

Fala aí Diego tudo bem?

Pelo que eu entendi esse erro ocorre quando uma transação é fechada por que está muito longa.

O que está acontecendo é que alguém acessa uma página é aberto uma transação no banco de dados.

A pessoa fica com o sistema ocioso e essa transação continua aberta no banco. Então o banco ve que essa transação está aberta a muito tempo e derruba essa transação (faz rollback).

E como foi o banco que executou o rollback o hibernate lança a exception org.hibernate.exception.JDBCConnectionException: could not extract ResultSet.

Se útil marque como solução. ;)

A entendi agora..rs você poderia sugerir por favor, uma solução para isto? ou o que eu deveria fazer para tratar esse erro?

Claro,

Uma possível solução para isso seria você identificar qual URI deve ter transação, bem provável que nem todas as suas URI's devem ser transacionadas.

Poderia ser um parâmetro na request ou uma anotação que você consiga identificar via reflection no seu filtro.

Dessa forma você só abriria uma transação onde realmente fosse necessário, e não teria esse problema.

Em geral só abrimos uma transação no banco quando vamos efetuar alguma manipulação no banco de dados( executar uma DML: insert, delete ou update). Todo o restante não precisa de transação.

Se achou útil marque como solução. ;)

No meu projeto não estou utilizando Spring apenas o persistence.

Teria como no filter eu descobri pelo request se foi solicitado uma transação? Se sim, poderia me mostra um exemplo de codigo?

Grato!

Existem diversas formas de identificar uma delas seria pela URI e pelo verbo

Por exemplo, geralmente quando vamos executar uma DML fazemos uma requisição utilizando o verbo POST

Dentro do seu filtro você consegue acessar essas informações:

@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;


        String method = req.getMethod();

        String uri = req.getRequestURI();

        System.out.println("{ method: " + method + ", uri: " + uri);


    }

Dessa forma se você conseguir identificar as URI's que devem ser transacionadas vc pode fazer um IF. Se for alguma das URI's transacionadas e o método for POST.

Abre a transação do contrário só executa o chain.doFilter(request,response);

Fernando,

Fiz o teste que você falou, o problema que são muitos URI na aplicação. Teria algum outro método de identifica que o request necessita de conexao com o BD ou nao?

Eu tirei o javax.persistence.query.timeout do persisntece.. aparentemente tinha resolvido, mas quando upei no servidor, no dia seguinte da o erro HTTP Status 500 - org.hibernate.exception.JDBCConnectionException: could not extract ResultSet.

Alguem poderia me ajudar ainda?

Oi Diego,

vc está usando algum pool de conexão?

parece que o mysql fecha a conexão por desuso e e a sua aplicação não consegue abrir uma nova.

abs

acho q é isso mesmo.. mas nao to conseguindo solucionar isso, pois não estou sabendo como proceder.

Estou usando a seguinte configuração no meu persistence.xml

solução!

Oi Diego,

dá uma olhada nesse exercício:

https://cursos.alura.com.br/course/jpa-avancado/section/5/task/9

Lá está a configuração usando o pool C3P0, que é um dos mais utilizados no mercado.

abs

Nico muito obrigado!

Eu já tinha feito essas configurações e estava ainda dando erro, mas olhando o exemplo vi que precisava add algumas bibliotecas. Eu não uso maven e não sabia que pro c3p0 precisava de bibliotecas também. Depois que adicionei ate agora resolveu o problema. rs

Obrigado a tds pelo auxilio.