Problemas com o padrão OpenSessionInViewer + JPA + Tomcat

1 resposta Resolvido
tomcatjavamysqlhibernate
R

Olá, estou usando o Tomcat + JPA + Vraptor 4 e estou utilizando o cdi para injetar o EntityManager.

public class EntityManagerFactoryCreator {
    @ApplicationScoped
    @Produces
    public EntityManagerFactory getEntityManagerFactory(){
        return Persistence.createEntityManagerFactory("default");
    }

    public void destroy(@Disposes EntityManagerFactory factory){
        if(factory.isOpen()){
            factory.close();
	}
     }
}

public class EntityManagerCreator {
    private EntityManagerFactory factory;

    /**
    * @depreciated CDI eyes only
    */
    public EntityManagerCreator() {}

    @Inject
    public EntityManagerCreator(EntityManagerFactory factory) {
        this.factory = factory;
    }

    @Produces @RequestScoped
    public EntityManager getEntityManager(){
       return factory.createEntityManager();
    }

    public void destroy(@Disposes EntityManager entityManager){
	if(entityManager.isOpen()){
		entityManager.close();
	}
    }
}

DAO Genérico.

`

public abstract class DAO < T > {
    /**
    * EntityManager
    */
    @
    Inject private EntityManager em;
    
    /**
    * Faz referência aos DAOS
    */
    private Class < T > clazz;
    
    public DAO() {
            clazz = getClazz();
    }
    
    @
    Transactional
    public boolean create(T entity) {
            try {
                    em.getTransaction().begin();
                    em.persist(entity);
                    em.getTransaction().commit();
                    return true;
            } catch (Exception e) {
                    return false;
            }
    }
    
    @
    Transactional
    public boolean update(T entity) {
            try {
                    em.getTransaction().begin();
                    em.merge(entity);
                    em.getTransaction().commit();
                    return true;
            } catch (Exception e) {
                    return false;
            }
    }
    
    public T getById(Long id) {
            return em.find(clazz, id);
    }
    
    @
    Transactional
    public boolean remove(Long id) {
            try {
                    T entity = em.find(clazz, id);
                    em.getTransaction().begin();
                    em.remove(entity);
                    em.getTransaction().commit();
                    return true;
            } catch (Exception e) {
                    return false;
            }
    }
    
    public List < T > list() {
            try {
                    return em.createQuery("FROM " + clazz.getName(), clazz).getResultList();
            } catch (Exception e) {
                    return null;
            }
    }
    
    @
    SuppressWarnings("unchecked")
    private Class < T > getClazz() {
            
            Class <? > classeDAO = this.getClass();
            
            while (classeDAO.getSuperclass() != DAO.class) {
                    classeDAO = classeDAO.getSuperclass();
            }
            
            ParameterizedType tipo = (ParameterizedType) classeDAO.getGenericSuperclass();
            
            Class < T > clazz = null;
            
            try {
                    clazz = (Class < T > ) tipo.getActualTypeArguments()[0];
            } catch (ClassCastException exception) {
                    throw exception;
            }
            return clazz;
    }
}`

Quando a classe ServerDAO é instanciada no Controller, a conexão é aberta e fechada normalmente. Porém, se for instanciada em um Job do Quartz por exemplo e tentar fazer uma listagem com o método list(), ocorre o seguinte erro.

19:16:01,662 ERROR [TaskLogger          ] Task serverTask was failed

java.lang.NullPointerException

at br.com.serverus.tasks.ServerTask.execute(ServerTask.java:36)

at br.com.serverus.tasks.ServerTask$Proxy$_$$_WeldClientProxy.execute(Unknown Source)

at br.com.caelum.vraptor.tasks.jobs.simple.ConcurrentJobWrapper.execute(ConcurrentJobWrapper.java:20)

at org.quartz.core.JobRunShell.run(JobRunShell.java:202)

at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)

Se eu remover a propriedade @RequestScoped do EntityManagerCreator, a listagem funciona, mas a conexão é mantida aberta.

Se eu disparar um evento do cdi, e utilizar o @Inject ServerDAO as conexão continuam abertas.

Como posso fazer para fechar a conexão, ou usar uma abordagem melhor sem o padrão OpenSessionInView?

1 Resposta

javaflex
Solucao aceita

Use OpenSessionInView somente para sua aplicação web normal. No Quartz você cria uma conexão própria pro job, abrindo a session do hibernate no início do Job e fechando no final desse Job, sem mágicas.

Criado 28 de julho de 2016
Ultima resposta 28 de jul. de 2016
Respostas 1
Participantes 2