Using EntityManager as an autowired field in a Spring Repository - java

I'm working on a legacy codebase and saw something unsettling in our custom repositories. EntityManager is autowired into the repos directly. For example:
#Repository
public class OperationRepository {
// Yikes
private final EntityManager entityManager;
private QOperation operation = QOperation.operation;
#Autowired
public OperationRepositoryImpl(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Override
public Optional<Operation> findOneByIdAndType(Long operationId, OperationType type) {
JPAQuery<Operation> query = new JPAQuery<>(entityManager);
QOperation qOperation = QOperation.operation;
query.select(operation).from(operation)
.where(
operation.type.eq(type),
...
}
}
My understanding is that this is dangerous since EntityManager is not threadsafe and is being managed here as a field. I don't see an explicit definition in any of our configuration files to provide an EntityManager bean so am not sure what Spring does in this case.
I am going to start on the fix for using #PersistenceContext here instead but wanted to understand what the impact is on this being in production for so long and what consequences might have come from it.
Would we be limiting our connection pool size to the number of single entitymanagers in our repository beans? Are there any other dangers it could have caused? Or am I making too much of it?

It really depends on the configuration of your application context, which might get configured by Spring Boot if you are using that, but in general and with a typicals setup this is not a problem.
In such a setup the application context doesn't contain a single (or a limited set of) EntityManager instance but an EntityManagerFactory which can create EntityManager instances on demand.
And you don't get injected a normal EntityManager either, but a proxy which will point to different instances upon different calls, typically so that each thread has its own EntityManager and after a web request is completed the next request handled by the same thread gets a fresh instance.
If you are still concerned, I recommend to use a debugger to inspect the EntityManager and confirm that it is indeed a proxy and that it delegates to different actual instances for different threads.
You might also want to take a look at this question about Spring Scopes which is the underlying abstraction for this: Spring Bean Scopes

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.).

Getting a reference to EntityManager in Java EE applications using CDI

I'm using Java EE 7. I would like to know what is the proper way to inject a JPA EntityManager into an application scoped CDI bean. You can't just inject it using #PersistanceContext annotation, because EntityManager instances are not thread safe. Let's assume that we want our EntityManager to be created at the beginnig of every HTTP request processing and closed after the HTTP request is processed. Two options come into my mind:
1.
Create a request scoped CDI bean which has a reference to an EntityManager and then inject the bean into an application scoped CDI bean.
import javax.enterprise.context.RequestScoped;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#RequestScoped
public class RequestScopedBean {
#PersistenceContext
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
}
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
#ApplicationScoped
public class ApplicationScopedBean {
#Inject
private RequestScopedBean requestScopedBean;
public void persistEntity(Object entity) {
requestScopedBean.getEntityManager().persist(entity);
}
}
In this example an EntityManager will be created when the RequestScopedBean is created, and will be closed when the RequestScopedBean is destroyed. Now I could move the injection to some abstract class to remove it from the ApplicationScopedBean.
2.
Create a producer that produces instances of EntityManager, and then inject the EntityManager instance into an application scoped CDI bean.
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
public class EntityManagerProducer {
#PersistenceContext
#Produces
#RequestScoped
private EntityManager entityManager;
}
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;
#ApplicationScoped
public class ApplicationScopedBean {
#Inject
private EntityManager entityManager;
public void persistEntity(Object entity) {
entityManager.persist(entity);
}
}
In this example we will also have an EntityManager which is created every HTTP request, but what about closing the EntityManager? Will it also be closed after the HTTP request is processed? I know that the #PersistanceContext annotation injects container-managed EntityManager. This means that an EntityManager will be closed when a client bean is destroyed. What is a client bean in this situation? Is it the ApplicationScopedBean, which will never be destroyed until the application stops, or is it the EntityManagerProducer? Any advices?
I know I could use a stateless EJB instead of application scoped bean and then just inject EntityManager by #PersistanceContext annotation, but that's not the point :)
You're almost right on with your CDI producer. Only thing is that you should use a producer method instead of a producer field.
If you're using Weld as CDI container (GlassFish 4.1 and WildFly 8.2.0), then your example of combining #Produces, #PersistenceContext and #RequestScoped on a producer field should throw this exception during deployment:
org.jboss.weld.exceptions.DefinitionException: WELD-001502:
Resource producer field [Resource Producer Field [EntityManager] with
qualifiers [#Any #Default] declared as [[BackedAnnotatedField]
#Produces #RequestScoped #PersistenceContext
com.somepackage.EntityManagerProducer.entityManager]] must be
#Dependent scoped
Turns out that the container is not required to support any other scope than #Dependent when using a producer field to lookup Java EE resources.
CDI 1.2, section 3.7. Resources:
The container is not required to support resources with scope other
than #Dependent. Portable applications should not define resources
with any scope other than #Dependent.
This quote was all about producer fields. Using a producer method to lookup a resource is totally legit:
public class EntityManagerProducer {
#PersistenceContext
private EntityManager em;
#Produces
#RequestScoped
public EntityManager getEntityManager() {
return em;
}
}
First, the container will instantiate the producer and a container-managed entity manager reference will be injected into the em field. Then the container will call your producer method and wrap what he returns in a request scoped CDI proxy. This CDI proxy is what your client code get when using #Inject. Because the producer class is #Dependent (default), the underlying container-managed entity manager reference will not be shared by any other CDI proxies produced. Every time another request want the entity manager, a new instance of the producer class will be instantiated and a new entity manager reference will be injected into the producer which in turn is wrapped in a new CDI proxy.
To be technically correct, the underlying and unnamed container who do the resource injection into the field em is allowed to reuse old entity managers (see footnote in JPA 2.1 specification, section "7.9.1 Container Responsibilities", page 357). But so far, we honor the programming model required by JPA.
In the preceding example, it would not matter if you mark EntityManagerProducer #Dependent or #RequestScoped. Using #Dependent is semantically more correct. But if you put a wider scope than request scope on the producer class you risk exposing the underlying entity manager reference to many threads which we both know is not a good thing to do. The underlying entity manager implementation is probably a thread-local object, but portable applications cannot rely on implementation details.
CDI does not know how to close whatever stuff it is that you put into the request bound context. More so than anything else, a container-managed entity manager must not be closed by application code.
JPA 2.1, section "7.9.1 Container Responsibilities":
The container must throw the IllegalStateException if the application
calls EntityManager.close on a container-managed entity manager.
Unfortunately, many people do use a #Disposes method to close the container-managed entity manager. Who can blame them when the official Java EE 7 tutorial provided by Oracle as well as the CDI specification itself use a disposer to close a container-managed entity manager. This is simply wrong and the call to EntityManager.close() will throw a IllegalStateException no matter where you put that call, in a disposer method or somewhere else. The Oracle example is the biggest sinner of the two by declaring the producer class to be a #javax.inject.Singleton. As we learned, this risk exposing the underlying entity manager reference to many different threads.
It has been proven here that by using CDI producers and disposers wrongfully, 1) the not thread-safe entity manager may be leaked to many threads and 2) the disposer has no effect; leaving the entity manager open. What happened was the IllegalStateException which the container swallowed leaving no trace of it (a mysterious log entry is made which says there was an "error destroying an instance").
Generally, using CDI to lookup container-managed entity managers is not a good idea. The application is most likely better off just using #PersistenceContext and be happy with it. But there are always exceptions to the rule like in your example, and CDI can also be useful to abstract away the EntityManagerFactory when handling the life cycle of application-managed entity managers.
To get a complete picture on how to obtain a container-managed entity manager and how to use CDI to lookup entity managers, you might want to read this and this.
I understand your problem. but that is not a real one. Do not get messed up with the CDI declared scope of a containing class, that will propagate the scope of the attributes expect those that use #Inject'ion!
The #Inject'ed will compute their reference in depencency of the CDI-declaration of the implementation class. So you might have Applicationscoped class with a #Inject EntityManager em inside, but each controlflow will find its own em-transaction reference to a disjount em-object, because of the EntityManager CDI declaration of the implementation class behind.
The wrong thing of your code is, that you provide an inner getEntityManager() access method. Do not pass Injected object, if you need one, simply #Inject it .
You should use the #Dispose annotation to close the EntityManager, as in the example below:
#ApplicationScoped
public class Resources {
#PersistenceUnit
private EntityManagerFactory entityManagerFactory;
#Produces
#Default
#RequestScoped
public EntityManager create() {
return this.entityManagerFactory.createEntityManager();
}
public void dispose(#Disposes #Default EntityManager entityManager) {
if (entityManager.isOpen()) {
entityManager.close();
}
}
}
You may inject savely EntityManagerFactory, it is thread save
#PersistenceUnit(unitName = "myUnit")
private EntityManagerFactory entityManagerFactory;
then you can retrive EntityManager from entityManagerFactory.

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.

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.

How to design for JPA in a non-Java EE web server (e.g. Tomcat)

Considering there is no #PersistenceContext available to inject the EntityManager, plus you need to manually manage Transactions, what is the best way to design such an application?
For the EntityManagerFactory/EntityManager, as far as I can see, you must have each DAO accepting an EntityManager in the costructor e.g.
public class DAOImpl implements DAO
{
private EntityManager em;
DAOImpl(EntityManager em){
this.em = em;
}
//all CRUD operations follow
}
The first question that rises is when do you call EntityManager#close()?
Point A: The way I see it, you are better off doing this in a Filter at the end of the request cycle, which implies that you associate the EntityManager with the current thread (using ThreadLocal?)
Second question is, how and when do you inject the EntityManager?
Considering there is a ServletContextListener where we create and close the EntityManagerFactory, we could have a static method as follows
public static EntityManager createEntityManager(){
return entityManagerFactory.createEntityManager(PERSISTENT_NAME);
}
but since we want to encapsulate creating the DAO, we could use a factory e.g.
public class DAOFactory
{
public static DAO dao(){
//return a new DAO
}
}
As per Point A we should use a ThreadLocal to create the DAO using the EntityManager for the current Thread.
For managing Transactions.
The best way I can think of (which mimics the JPA spec) is to create your own Transaction annotation and use reflection to inject the begin/commit/rollback operations.
You should then return a Proxy from the DAOFactory which handles the transactions
I wouldn't do all that. Why try to recreate the whole JPA spec yourself? You just need to be able to use JPA without a container.
Spring can help you with this. Try it.

Categories