Hello, I'm using Tomcat + JPA + Vraptor 4 and I'm using cdi to inject EntityManager as follows.
EntityManagerFactoryCreator:
public class EntityManagerFactoryCreator {
@ApplicationScoped
@Produces
public EntityManagerFactory getEntityManagerFactory(){
return Persistence.createEntityManagerFactory("default");
}
public void destroy(@Disposes EntityManagerFactory factory){
if(factory.isOpen()){
factory.close();
}
}
}
EntityManagerCreator:
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();
}
}
}
GenericDAO:
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;
}
}'
When the ServerDAO class is instantiated on the Controller, the connection is opened and closed normally. However, if it is instantiated in a Quartz Job for example and try to make a list with the list () method, the following error occurs.
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)
If I remove the @RequestScoped property of EntityManagerCreator, the listing works, but the connection is kept open.
If I trigger an event from the cdi, and use the @Inject ServerDAO the connections remain open.
How can I close the connection, or use a better approach without the OpenSessionInView standard?