The 'correct' way to instantiate JPA manager bean? - java

I'm using IBM RAD to develop some JPA entities, and from those, corresponding JPA Manager Beans. Manager beans (which are generated by RAD) have the following member:
#PersistenceUnit
private EntityManagerFactory emf;
I'm not sure how to correclty instantiate (or get a reference to) this manager bean from a stateless EJB (3.0), so I've added a constructor to manager bean where I can pass EntityManagerFactory instance to it. I get a reference to EntityManagerFactory in an EJB by using `#PersistenceUnit' annotation like so:
#PersistenceUnit
private EntityManagerFactory _entityManagerFactory;
This seems rather unnecessary and I believe there must be a way to tell the container (Websphere 7.0 in my case) to 'bootstrap' this for me somehow, so that I get a reference to JPA manager bean right away. Is it?
Update:
It seems I haven't bean elaborate enough. Sorry for that.
There are three objects involved: JPA Entity, JPA Entity Manager and a Stateless EJB.
JPA Entity Manager class (not an EJB) is created by RAD and has convinience methods (named queries) on it. It also has defined member #PersistenceUnit private EntityManagerFactory emf. I know I can use EntityManager directly, but I'd like to use MyEntityManager for it's convinience methods.
I can get a reference to EntityManager or EntityManagerFactory in a stateless EJB by using annotations described above (and also like Bozho suggests)
I would like to get a reference to JPA Entity Manager in a stateless EJB. If I 'new' it up (new MyEntityManager()), the emf field is null. The workaround is to declare #PersistenceUnit field in an EJB and then pass it to JPA Entity Manager and use that.
Come to think of it, maybe I could declare JPA Entity Manager as an EJB and be done with it... (although this again seems unnecessary). I thought there is a method along the lines PersistenceContext.getJpaManager(MyEntityManager.class) which I am perhaps missing.

#PersistenceContext
private EntityManager em;
It seems you have your custom bean that you want to inject in other beans (it needs a local interface at least):
#EJB
private MyEntityManager em;

Related

PersistenceUnit vs PersistenceContext

In few project I have been successfully using
#PersistenceUnit(unitName = "MiddlewareJPA")
EntityManagerFactory emf;
...
EntityManager entityManager = emf.createEntityManager();
to obtain EntityManager for Database connection, but some days ago I was trying to move my project to Jboss EAP 6.2 and it couldn't create EntityManager. I was googling it and I found that I should try change #PersistenceUnit to
#PersistenceContext(unitName = "MiddlewareJPA")
private EntityManager entityManager;
to obtain EntityManager. It worked but I don't know why. What is the difference bettween PersistenceUnit and PersistenceContext? What are pros and cons of each one? Where should we be using one of them?
PersistenceUnit injects an EntityManagerFactory, and PersistenceContext injects an EntityManager. It's generally better to use PersistenceContext unless you really need to manage the EntityManager lifecycle manually.
I don't know how it works exactly in the Java EE, but in Spring, when you specify #PersistenceContext annotation, it injects EntityManager. Where does it get EntityManager? It is wrong to create one EntityManager for the whole application lifetime by calling EntityManagerFactory.createEntityManager(). So instead a special implementation of EntityManager interface is used and instantiated directly. It has an internal mutable thread-local reference to a real EntityManager. Implementations of methods just redirect calls to this real EntityManager. And there is a servlet listener, that before each request obtain EM by calling EMF.createEntityManager() and assign it to that inner reference of special EM. Also this listener manages transactions by calling getTransaction().begin(), .commit() and .rollback() on the real EM. It is very simplified description of performed work. And I believe, that JEE container does the same thing, as Spring does.
In general case it is better to inject EntityManager, because with EntityManagerFactory and #PersistenceUnit you should create/destroy EntityManager every time by hands and manage transactions too.
EntityManager obtained via #PersistenceContext is called Container Managed EntityManager as container will be responsible for managing "EntityManager". EntityManager obtained via #PersistenceUnit / entityManagerFactory.createEntityManager() is managed in the application by the developer. (for e.g. managing lifecycle of EntityManager, releasing the resources acquired by EntityManager, etc.).

Java CDI #PersistenceContext and thread safety

Is an EntityManager #Inject[ed] as follows in muliple classes threadsafe?
#PersistenceContext(unitName="blah")
private EntityManager em;
This question and this one seem to be Spring specific. I am using Jave EE CDI services
To my great surprise (after years of using jpa in spring) EntityManager is not thread safe. This is actually understandable if you think about it deeper: EntityManager is just a wrapper around native JPA implementation, e.g. session in Hibernate, which in turns is a wrapper around jdbc connection. That being said EntityManager can't be thread safe as it represents one database connection/transaction.
So why does it work in Spring? Because it wraps target EntityManager in a proxy, in principle using ThreadLocal to keep local reference per each thread. This is required as Spring applications are built on top of singletons while EJB uses object pool.
And how can you deal with that in your case? I don't know cdi but in EJB each stateless and stateful session bean is pooled, which means you cannot really call method of the same EJB from multiple threads in the same time. Thus EntityManager is never used concurrently. That being said, injecting EntityManager is safe, at least into stateless and stateful session beans.
However injecting EntityManagerto servlets and singleton beans is not safe as possibly several threads can access them at the same time, messing up with the same JDBC connection.
See also
Mind thread-safety when injecting EntityManager
The EntityManager is not thread-safe
Although EntityManager implementations itself are not thread safe the Java EE container injects a proxy which delegates all methods invocations to a transaction bound EntityManager. Therefore each transaction works with it's own EntityManager instance. This is true for at least transaction-scoped persistence context (which is default).
If container would inject a new instance of EntityManager in each bean the below wouldn't work:
#Stateless
public class Repository1 {
#EJB
private Repository2 rep2;
#PersistenceContext(unitName="blah", type = PersistenceContextType.TRANSACTION)
private EntityManager em;
#TransactionAttribute
public void doSomething() {
// Do something with em
rep2.doSomethingAgainInTheSameTransaction();
}
}
#Stateless
public class Repository2 {
#PersistenceContext(unitName="blah", type = PersistenceContextType.TRANSACTION)
private EntityManager em;
#TransactionAttribute
public void doSomethingAgainInTheSameTransaction() {
// Do something with em
}
}
doSomething->doSomethingAgainInTheSameTransaction call happens in a single transaction and therefore the beans must share the same EntityManager. Actually they share the same proxy EntityManager which delegates calls to the same persistence context.
So you are legal use EntityManager in singleton beans like below:
#Singleton
#ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class Repository {
#PersistenceContext(unitName="blah", type = PersistenceContextType.TRANSACTION)
private EntityManager em;
}
Another proof is that there is no any mention of thread safety in EntityManager javadoc. So while you stay inside Java EE container you shouldn't care about concurrency access to EntityManager.
I feel I need to go deeper into this because my first answer was not absolutely true.
I will refer to JSR-220 (EJB 3.0). In section 5.2 Obtaining an EntityManager you may find:
An entity manager may not be shared among multiple concurrently
executing threads. Entity managers may only be accessed in a
single-threaded manner.
Well that's it. You may stop reading here and never use EntityManager in singleton beans unless properly synchronized.
But I believe there is a confusion in the spec. There are actually two different EntityManager implementations. The first is one is provider implementation (saying Hibernate) which is not obliged to be threadsafe.
On the other hand there is a container implementation of EntityManager. Which is also not supposed to be threadsafe according to the above. But container's implementation acts as a proxy and delegates all calls to the real provider's EntityManager.
So further in the spec in 5.9 Runtime Contracts between the Container and Persistence
Provider:
For the management of a transaction-scoped persistence context, if
there is no EntityManager already associated with the JTA transaction:
The container creates a new entity manager by calling
EntityManagerFactory.createEntityManager when the first invocation of
an entity manager with Persistence- ContextType.TRANSACTION occurs
within the scope of a business method executing in the JTA
transaction.
This means in turn that there will be a different EntityManager instance for each transaction started. The code that creates an EntityManager is safe according to 5.3:
Methods of the EntityManagerFactory interface are threadsafe.
But what if there is an EntityManager associated with JTA transaction? The code that binds an EntityManager associated with current JTA transaction may be not threadsafe according to the spec.
But I can't really think of an application server implementation that works correctly with EntityManager injected into stateless beans and not correctly within singletons.
So my conclusions are:
If you want to follow the JSR-220 strictly then never use EntityManager in singletons until synchronizing the access to it.
I personally will continue to use EntityManager in singleton because my application server implementation works perfectly with it. You may want to check your implementation before doing so.

EJBException when calling entityManager.getTransaction()

This is probably something trivial, but I'd love some help.
I get:
javax.ejb.EJBException: java.lang.IllegalStateException: Illegal to call this method from injected, managed EntityManager
11:54:37,105 ERROR [STDERR] at org.jboss.ejb3.tx.Ejb3TxPolicy.handleExceptionInOurTx(Ejb3TxPolicy.java:77)
11:54:37,105 ERROR [STDERR] at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:83)
11:54:37,105 ERROR [STDERR] at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:190)
when doing:
#PersistenceContext(unitName = "someName")
private EntityManager em;
...
final EntityManager entityManager = getEntityManager();
final EntityTransaction tx = entityManager.getTransaction(); // here
Can anyone tell me what the cause might be ?
It is illegal to obtain a reference to the EntityTransaction instance associated with the EntityManager in a Java EE managed context. From the Java EE API documentation of EntityManager.getTransaction():
Return the resource-level EntityTransaction object. The
EntityTransaction instance may be used
serially to begin and commit multiple
transactions.
Returns:
EntityTransaction instance
Throws:
IllegalStateException - if invoked on a JTA entity manager
The last line is pertinent in this context.
When you inject the EntityManager in an EJB deployed on an application server using the #PersistenceContext or #Inject annotations, the EntityManager will be managed by the container and not by the application. A container managed entity manager must be a JTA Entity Manager; application-managed entity managers can be resource-local entity managers. This is dictated by the JPA specification:
An entity manager whose underlying
transactions are controlled through
JTA is termed a JTA entity manager.
An entity manager whose underlying
transactions are controlled by the
application through the
EntityTransaction API is termed a
resource-local entity manager.
A container-managed entity manager
must be a JTA entity manager. JTA
entity managers are only specified for
use in Java EE containers.
Inferring from the first point (regarding the IllegalStateException), you must not obtain the EntityTransaction reference for container injected EntityManagers. You may however do so, if the container injected only the EntityManagerFactory, and your application obtained the EntityManager reference by invoking EntityManagerFactory.getEntityManager.
Additionally, it should be noted that invoking EntityManager.getTransaction() is meaningless for JTA entity managers. This is indicated by the JPA specification, in the definition of the EntityTransaction interface:
The EntityTransaction interface is used to control resource transactions on resource-local entity managers.
On the topic of managing the JTA transaction itself, if you need to manage the transaction boundaries yourself (i.e. use bean-managed transactions), inject the UserTransaction instance. Or if you wish to have the container manage the transaction, then simply annotate the method or the bean, with the appropriate TransactionalAttribute value.
It is usually not a good idea to use resource-local entity managers (and data sources) with bean managed or container managed transactions in an application server, but it can be done.
You will find a suitable example demonstrating the use of BMTs with injection of the EntityManager in the Hibernate EntityManager documentation. CMTs are even more trivial if you've already annotated your bean classes or methods; you merely have to avoid invoking the the getEntityTransaction() method for CMTs to work.
If you wish to understand further, I would recommend reading Chapter 7 of the JPA 2.0 specification, titled "Entity Managers and Persistence Contexts". The examples provided in the chapter demonstrate:
how JTA entity managers ought to be used in an application server (which is typically the place where they are used).
how resource-local entity managers may be used in an application server.
how resource-local entity managers can be used in a Java SE application.
You don't need to instantiate the EntityManager by hand, your container does that for you because of the
#PersistenceContext annotation. Also, you don't need to begin the transaction manually, it's also provided by your containter. Just use your em field and forget about the other ones.

Is it okay to pass injected EntityManagers to EJB bean's helper classes and use it?

We have some JavaEE5 stateless EJB bean that passes the injected EntityManager to its helpers.
Is this safe? It has worked well until now, but I found out some Oracle document that states its implementation of EntityManager is thread-safe. Now I wonder whether the reason we did not have issues until now, was only because the implementation we were using happened to be thread-safe (we use Oracle).
#Stateless
class SomeBean {
#PersistenceContext
private EntityManager em;
private SomeHelper helper;
#PostConstruct
public void init(){
helper = new SomeHelper(em);
}
#Override
public void business(){
helper.doSomethingWithEm();
}
}
Actually it makes sense.. If EntityManager is thread-unsafe, a container would have to do
inercept business()
this.em = newEntityManager();
business();
which will not propagate to its helper classes.
If so, what is the best practice in this kind of a situation? Passing EntityManagerFactory instead of EntityManager?
EDIT: This question is very interesting so if you are interested in this question, you probably want to check out this one, too:
EDIT: More info.
ejb3.0 spec
4.7.11 Non-reentrant Instances
The container must ensure that only one
thread can be executing an instance at
any time. If a client request arrives
for an instance while the instance is
executing another request, the
container may throw the
javax.ejb.ConcurrentAccessException to
the second client[24]. If the EJB 2.1
client view is used, the container may
throw the java.rmi.RemoteException to
the second request if the client is a
remote client, or the
javax.ejb.EJBException if the client
is a local client.[25] Note that a
session object is intended to support
only a single client. Therefore, it
would be an application error if two
clients attempted to invoke the same
session object. One implication of
this rule is that an application
cannot make loopback calls to a
session bean instance.
And,
4.3.2 Dependency Injection
A session bean may use dependency injection
mechanisms to acquire references to
resources or other objects in its
environment (see Chapter 16,
“Enterprise Bean Environment”). If a
session bean makes use of dependency
injection, the container injects these
references after the bean instance is
created, and before any business
methods are invoked on the bean
instance. If a dependency on the
SessionContext is declared, or if the
bean class implements the optional
SessionBean interface (see Section
4.3.5), the SessionContext is also injected at this time. If dependency
injection fails, the bean instance is
discarded. Under the EJB 3.0 API, the
bean class may acquire the
SessionContext interface through
dependency injection without having to
implement the SessionBean interface.
In this case, the Resource annotation
(or resource-env-ref deployment
descriptor element) is used to denote
the bean’s dependency on the
SessionContext. See Chapter 16,
“Enterprise Bean Environment”.
I used a similar pattern, but the helper was created in #PostConstruct and the injected entity manager was passed in the constructor as parameter. Each EJB instance had its own helper and thread-safety was guaranteed then.
I also had a variant were the entity manager was not injected (because the EJB wasn't using it altogether), so the helper has to look it up with InitialContext. In this case, the Persistence context must still be "imported" in the parent EJB with #PersistenceContext:
#Stateless
#PersistenceContext(name="OrderEM")
public class MySessionBean implements MyInterface {
#Resource SessionContext ctx;
public void doSomething() {
EntityManager em = (EntityManager)ctx.lookup("OrderEM");
...
}
}
But it's actually easier to inject it (even if the EJB doesn't use it) than to look it up, especially for testability.
But to come back to your main question, I think that the entity manager that is injected or looked up is a wrapper that forwards to the underlying active entity manager that is bound to the transaction.
Hope it helps.
EDIT
The section § 3.3 and § 5.6 in the spec cover a bit the topic.
I've been using helper methods and passed the EntityManager there, and it is perfectly OK.
So I'd recommend either passing it to methods whenever needed, or make the helper a bean itself, inject it (using #EJB) and inject the EntityManager there as well.
Well, personally, I wouldn't like to have to pass the Entity Manager to all my POJOs in my constructors or methods. Especially for non-trivial programs where the number of POJOs is large.
I would try to create POJOs/HelperClasses that deal with the Entities returned by the EntityManager, instead of using the entitymanager directly.
If not possible, I guess I'd create a New EJB Bean.

In Seam what's the difference between injected EntityManager and getEntityManager from EntityHome

I am testing a Seam application using the needle test API. In my code I am using the getEntityManager() method from EntityHome. When I run the unit tests against an in memory database I get the following exception:
java.lang.IllegalStateException: No application context active
at org.jboss.seam.Component.forName(Component.java:1945)
at org.jboss.seam.Component.getInstance(Component.java:2005)
at org.jboss.seam.Component.getInstance(Component.java:1983)
at org.jboss.seam.Component.getInstance(Component.java:1977)
at org.jboss.seam.Component.getInstance(Component.java:1972)
at org.jboss.seam.framework.Controller.getComponentInstance(Controller.java:272)
at org.jboss.seam.framework.PersistenceController.getPersistenceContext(PersistenceController.java:20)
at org.jboss.seam.framework.EntityHome.getEntityManager(EntityHome.java:177)
etc ..
I can resolve some of these errors by injecting the EntityManager with
#In
EntityManager entityManager;
Unfortunately the persist method of EntityHome also calls the getEntityManager. This means a lot of mocks or rewriting the code somehow. Is there any workaround and why is this exception thrown anyway? I am using Seam 2.2.0 GA by the way.
There is nothing special about the components. They are generated by seam-gen. The test is performed with in memory database - I followed the examples in http://jbosscc-needle.sourceforge.net/jbosscc-needle/1.0/db-util.html.
In Seam what is the difference between injected EntityManager and getEntityManager from EntityHome ?
No one.
When using getEntityManager from EntityHome, Seam will lookup a Seam-managed persistence context named entityManager. If you set up your Seam-managed persistence context with other name than entityManager, your EntityHome will throw an Excedption.
Here is the default implementation of getEntityMananger in EntityHome
public EntityManager getEntityManager() {
return (EntityMananger) Component.getInstance("entityManager");
}
And when using a #In-jected EntityManager, Seam will do as shown above. Both are the same Seam managed persistence context.
Remember Seam performs lookup through #In-jected Component field name. For instance:
#In
EntityManager entityManager;
Because EntityManager field name is entityManager, Seam will perform a hierarchical search by using this name;
Here and here you can see how to set up a Seam Managed Persistence context.
regards,

Categories