I am using Glassfish v3 server.
Usually the DB connection with EJB3 + JPA (Eclipselink) is done through injection, with @PersistenceUnit or @Persistencecontext.
However, there are 3 layers in my App :
Core (contains business logic, entities, exception handling etc)
an EJB on top of it, calling the right core objects and methods to do the job. This EJB is called by other internal modules of our ERP.
a REST layer on top of it for uses by frontend web sites.
I do not want to get the entityManager, nor the EMF (EM factory) in the EJB, because I want my middle layer to be unaware that there is a DB used under it. I could after all, later, decide to change my core implementation for a non-DB-using one.
I see only two bad solutions :
1) Add an EM parameter every time i call a method of the core layer that needs DB connection. Very ugly and goes againt what I said above.
2) In every method of core needing DB connection, I create a factory, an EM, use them, and then close them both.
I tried to cut things in the middle, having one factory per class of the Core level, and EMs are created and closed in every method. But I still have memory leaks like this :
javax.servlet.ServletException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Error in allocating a connection. Cause: In-use connections equal max-pool-size and expired max-wait-time. Cannot allocate more connections.
I guess it's because if one of my EJB methods uses 10 different objects, it creates 10 EM factories, and none of them is closed.
Example of typical use in a Core object:
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// do some stuff with em; for example persist, etc
em.flush();
em.close();
Should I go for solution 2? Is there a way to use a single EM factory at this core level ? I seems like the JPA spec assumes you're going to use the entities at the EJB level only, which is bad in a multi layers apps.
EDIT : here is the current status after trying @Inject :
Added an empty beans.xml file in the /META-INF directory on my CORE jar.
The parent DAO class is now like this :
public class ExampleBZL {
public EntityManagerFactory emf; @Inject public Emf emfobject; public ExampleBZL() { this.emf = emfobject.emf; }
The Emf class is very simple, and Stateless.
@Stateless public class Emf implements EmfAbstract {
@PersistenceUnit(unitName = Setup.persistenceUnitName) public EntityManagerFactory emf; public Emf() { }
}
I must be doing something wrong, but the injection doesn't work, altough in glassfish I see "[ejb, weld, web]" in the engines list, so the CDI is loaded.
Servlet.service() for servlet Jersey Web Application threw exception
java.lang.NullPointerException
at com.blablabla.core.bizlogic.ExampleBZL.<init>(ExampleBZL.java:40)
Am I missing other annotations ?? Is it really working to do an inection in a JAR with those two small annotations (Stateless on one side, Inject on the other) ?