I have the method below.
public Profile readUser(String email){
EntityManager em = EMF.get().createEntityManager();
return em.find(Profile.class, email);
}
Is the above usage of entity manager okay? Or It is necessary to close em?Any suggestions please.
I suppose the answer is: it depends.
Your entity manager is the key to gain access to the context where entities reside. If your application is a JSE application, you have to consider what is the life expectancy of your context.
Let's consider that you will create an entity manager per user's request. So, while you are attending a given request, you will keep your entity manager open, and when you finish with it, you close it.
In a JSE application, you may have considered that you would like to keep your entity manager open the entire life of the application (supposing you're not dealing with big amounts of data) then you close it when your application shuts down.
Bottom line, when you open it and when you close depends entirely on your strategy and your design. You close it when you no longer need the entities in its context.
In your example, that is not evident, but since you're creating the EM in the method, you should close it before returning, otherwise, you will no longer have access to it again (unless you're keeping it in some registry, which is not evident in the code).
If you don't close it your entities will be kept as attached, even after you're done using them. Your context will be kept alive even when you can no longer access your EM.
The JPA Specification contains more details. In section 7.7 Application-managed Persistence Contexts it says:
When an application-managed entity manager is used, the application
interacts directly with the persistence provider's entity manager
factory to manage the entity manager lifecycle and to obtain and
destroy persistence contexts.
All such application-managed persistence contexts are extended in
scope, and can span multiple transactions.
The EntityManagerFactory.createEntityManager method and the
EntityManager close and isOpen methods are used to manage the
lifecycle of an application-managed entity manager and its associated
persistence context.
The extended persistence context exists from the point at which the
entity manager has been created using
EntityManagerFactory.createEntityManager until the entity manager is
closed by means of EntityManager.close.
An extended persistence context obtained from the application-managed
entity manager is a stand-alone persistence context it is not
propagated with the transaction.
[...] The EntityManager.close method closes an entity manager to
release its persistence context and other resources. After calling
close, the application must not invoke any further methods on the
EntityManager instance except for getTransaction and isOpen, or
the IllegalStateException will be thrown. If the close method is
invoked when a transaction is active, the persistence context remains
managed until the transaction completes.
The EntityManager.isOpen method indicates whether the entity manager
is open. The isOpen method returns true until the entity manager has
been closed.
To actually understand how this works it is vital to understand the relationship between the entity manager and the context.
So, as you can see the entity manager is the public interface through which you access your entities, however, your entities reside in a context, attached to your entity manager. Understanding the life cycle of the different types of contexts will answer your question.
Persistence contexts can be of different types. In Java EE applications, you can either have a transaction-scoped persistence context or a extended-persistence context. In the JSE application, the nature of the context is controlled by the developer.
When you ask for an entity to your entity manager, it looks for the entity in its attached context, if it finds the entity there, then it returns it, otherwise, it retrieves the entity from the database. Subsequent calls for this entity in context will return the same entity.
Transaction-scoped
In a Java EE application using the transaction-scoped persistence context, when you first access your entity manager, it checks if the current JTA transaction has a context attached if no context is yet present, a new context is created and the entity manager is linked to this context. Then the entity is read from the database (o from the cache if present) and it is placed into the context. When your transaction ends (commit or rollback), the context becomes invalid and whatever entities in it become detached. This is the classical scenario for stateless sessions beans.
#PersistenceContext(unitName="EmplService")
EntityManager em;
This also means that depending on how you design your transactions, you may end up with more than one context.
Extended-Persistence Context
In a Java EE application with stateful session beans you might like the context to survive multiple bean invocations, since you don't like to commit until the bean has been marked for removal, right? In those cases, you need to use an extended persistence context. In this case, the persistence context is created when it is first needed, but it won't become invalid until your mark the stateful bean for removal.
#PersistenceContext(unitName="EmplService", type=PersistenceContextType.EXTENDED)
This means that, regardless of the instance of the entity manager that gets injected into this bean in subsequent calls of the stateful session beans methods, you can be sure you will always access the same context, and therefore, even subsequent calls will return the same instance, because it is the same context.
Also, your changes will not be flushed until the bean is marked for removal or you manually flush them.
Application-Managed
You can always instantiate manually your entity manager factory and your entity manager. This is what you would typically do in a JSE application, is that right?
For this kind of applications you typically do not have a container to deal with the JTA transactions, right? So you use resource-local transactions and you are responsible for manually committing or rolling back changes.
For this kind of application, when you instantiate your entity manager, a context is automatically attached to it.
Depending on your application, you can decide to create a global entity manager whose life cycle is attached to the life of the application itself. That is a single entity manager for the entire life of the application. In this cases, your context will be created and destroyed with your entity manager.
Or, you could create an entity manager per conversation (i.e. transaction) with your application user. The scope, in this case, is determined by you, but still, your context will be created and destroyed with your entity manager.
Related
I'm developing a system to process messages and update the database accordingly, but I need to keep some degree of isolation between layers. I have in mind something like the following.
MyDao.java: a #Stateless bean that provides database access. MyDao accesses the database using JPA, with an EntityManager injected by #PersistenceContext.
MyMdb.java: an MDB that listens on a queue. MyMdb uses MyDao by injection with #EJB.
One single execution of MyMdb.onMessage() needs to perform several accesses to the database, both read and write.
On the one hand, this makes me think that a #Stateless bean is not the right choice for MyDao: the EntityManager instance in MyDao could be randomly accessed by different executions of MyMdb.onMessage(), leading threads to interfere with each other.
On the other hand, JPA documentation says that the injected EntityManager is just a proxy: the actual persistence context on which it operates is the one bound to the JTA transaction. This way everything should be ok because, even though EntityManagers are "shared", each MDB will have a different transaction ongoing and thus work in safe isolation.
What is the right scenario? Am I missing something?
Entity managers injected in a stateless EJB in the way that you described are exactly what you should do.
This type of injection provides a 'Container-Managed Entity Manager' which is 'transaction scoped'.
So in the scenario that you describe.
the onMessage MDB call will create a transaction
the call to the stateless bean will happen to the same transaction context, creating an Entity Manager which will live until the transaction finishes usually when the MDB method returns.
The specific type of injected entity manager for the same EJB instance doesn't survive and is not re-used across different transactions.
We are working on a little web (will run on Tomcat) with the data layer done with JPA (Eclipselink).
I did similar thing some time ago. But i were always unsure when i need to begin and end transactions or do a flush.
At the moment i use transaction if i add (persist) and remove objects. If i call setters on an already persisted object i do not use transactions.
Is there a guide/ tutorial or a short answer when to use transactions or how to implement application managed JPA correctly.
I think one can summarize an answer to your question.
almost any JPA operation needs a transaction, except find/selects that do not lock entities (i.e any JPA operation that does not change the data).
(JTA transaction-scoped entity manager)
In the case of an JTA transaction-scoped entity manager it is better to quote from the spec (Chapter 3 Entity Operations):
The persist, merge, remove, and refresh methods must be invoked within
a transaction context when an entity manager with a
transaction-scoped persistence context is used.
If there is no transaction context, the javax.persistence.TransactionRequiredException is thrown.
Methods that specify a lock mode other than LockModeType.NONE must be invoked
within a transaction context.
If there is no transaction context, the javax.persistence.TransactionRequiredException is thrown.
The find method (provided it is invoked without a lock or invoked with
LockModeType.NONE) and the getReference method are not required to be
invoked within a transaction context. If an entity manager with
transaction-scoped persistence context is in use, the resulting
entities will be detached; if an entity manager with an extended
persistence context is used, they will be managed. See section 3.3 for
entity manager use outside a transaction.
(Application-managed/resource-local entity manager)
In the case of an Application-managed entity manager, the JPA spec is not clear about the behavior. In the case of Hibernate, it is pretty complicated what happens, when not inside a transaction (it could depend also on the JDBC driver and the autocommit mode of the DB connection). Check Hibernate's article on this theme. Basically you are strongly encouraged to always use transactions for the above mentioned operations.
To the second part of your question: if you called a setter of a managed entity, and without flushing you detached it (i.e before transaction commit), the behavior is unclear/undefined, i.e you should better correct the code.
Example of buggy code:
//begin Transaction
MyEntity entity = em.find(MyEntity.class, 1L);
entity.setField("New value");
em.detach();//it is not sure whether the "New value" will be persisted. To make sure it is persisted, ypu need to call em.flush() before detaching
//commit Transaction
Usually if the order of DB operations (not the same as the order of enity manager operations) is not important, you can leave the JPA implementation to decide when to flush (e.g on transaction commit).
I am injecting EntityManager objects in stateless EJB3 beans (which act as DAO objects and each provide access to a different database table). Deployment is in JBoss AS 7.
I then added code using System.identityHashCode in the EJB3 beans methods to see the various instances of the EntityManagers injecting (hoping to see the same instance in all DAOs). E.g. like:
#Stateless
public class AFacade {
#PersistenceContext(unitName="foo")
EntityManager em;
public List<A> findAll() {
l.info("entity manager is: "+System.identityHashCode(em)+" class is: "+em.getClass().getSimpleName());
...
}
However, what I noticed is that each DAO (e.g. AFacade, BFacade and so on) was injected with a different EntityManager (as reported by identityHashCode) although the PersistenceContext was the same. The implementing class was TransactionScopedEntityManager in all cases.
It is not clear to me why this different EntityManager objects are injected, whether this is something that should concern me or not. Also, I understand that the EJB3 container may actually inject proxies to the real EntityManager so these different instances may actually be proxies to a single EntityManager.
Yes, they are proxies (in fact, I think they are thread safe decorators, rather than proxies) on the real entity managers.
I'm not sure if you know that the EntityManager is a wrapper around a connection. If you wouldn't have this decorator (or proxy), all invocations to that stateless bean would share the same connection (and potentially transaction), which is not what you want.
The injected EntityManagers are proxy generated by the EJB Containers.
For Transaction scoped Entity Managers, each transaction uses a single separate instance of Provider's Entity Manager.
When a method call is made to this proxy , container checks javax.transaction.TransactionSynchronizationRegistry ( this is implemented by EJB Container) to see if there is a provider EntityManager already created for this transaction. If not, it will create the provider Entity Manager and register it in TransactionSynchronizationRegistry and then delegate the method call to it. If already present, it will simply retrieve the provider Entity Manager an delegate the method call to it.
Transaction scoped EntityManagers are stateless according to the book "Pro JPA2 Mastering the Java Persistence API" by Mike Keith and Merrick Schincariol (See Chapter 6).
The proxy objects inserted in each EJB instance object is different, though a single proxy object could have been used because of the stateless nature of Transaction scoped Entity Manager.
Also take a look at : http://piotrnowicki.com/2011/11/am-i-in-the-same-transaction-am-i-using-the-same-persistencecontext/
The EntityManger is injected with #PersistenceContext annotation. This is a method from my "DAO/Repository" class which is not annotated. This class is injected into the EJB's that needs to get data from/to the database.
Until now I thought that after the persist method below is finished the persistencecontext is flushed and the data is stored to the database but from what happening in my app I start to doubt that. I have made the datasource and connection pool in Glassfish so I am using container managed transactions as far I know, however I do not use any transaction annotations.
Could somebody throw some light over it for me?
public void persist(QuestionFeedback questionFeedback) {
questionFeedback.setCreated(new Date());
entityManager.persist(questionFeedback);
}
Using Glassfish 3, Java EE6 compatiblity
The persist method makes the entity persistent, but doesn't yet write the change to the database. This normally happens when the transaction commits (the provider is free to optimize this, it could happen earlier).
With flush you can force the write to happen earlier, but it will still be visible only to code that participates in the current transaction. To make the write permanent (visible to all external code), the transaction still needs to be committed.
Without any explicit annotations, your EJB bean will be transactional by default.
Because EntityManager is injected via #PersistenceContext annotation, you are for sure using container managed transactions.
Anyway, your assumption that persist causes transaction commit is wrong. Change performed via persist is made to the database in commit. Documentation of EntityManager says that "new instance becomes both managed and persistent by invoking persist". In this context "becomes persist" does not mean entity is persisted to the database on that moment. On the moment when persist is called, entity is persisted in the terms of PersistenceContext. It is then later on persisted to the database latest when transaction commits.
Because you are not using any #TransactionAttribute annotations for your methods, default will apply. Default is TransactionAttributeType.REQUIRED. This will cause container to create transaction when first business method is called and propagate this on to other methods. Your transaction will commit when the call to the first business method is completed. Then your changes are in database (if no rollback was performed).
If you don't use any transaction annotations the default will be transactions being required. Thus your DAO will run in a transaction and the persistence context will no later be flushed than when the transaction is committed.
From the JavaDoc on TransactionAttribute:
If the TransactionAttribute annotation is not specified, and the bean uses container managed transaction demarcation, the semantics of the REQUIRED transaction attribute are assumed.
From the JavaDoc on FlushModeType:
When queries are executed within a transaction, if FlushModeType.AUTO is set on the Query or TypedQuery object, or if the flush mode setting for the persistence context is AUTO (the default) and a flush mode setting has not been specified for the Query or TypedQuery object, the persistence provider is responsible for ensuring that all updates to the state of all entities in the persistence context which could potentially affect the result of the query are visible to the processing of the query.
This means that the persistence context might be flushed earlier, if you use a query whose result might be influenced by that flush.
Does it make sense to talk about the Open Session In View Pattern within JSF2 applications?
My app has JSF2 Managed Beans calling Business Service EJBs that do all the db-related stuff (there's a DAO layer but that doesn't matter right now).
Having OSIV pattern would mean that the Managed Bean would have to somehow make sure the underlying session was opened.
I am also using JPA.
Theoretically, the issue is exactly the same: entity will become detaches when they leave the EJB unless something keeps the scope of the EntityManager open. (Here is a great post about the topic in general: JPA implementation patterns: Lazy loading).
From a blog post I read:
8) No Open Entity Manager In View support.
[...] In EJB3, when your entity leaves bean
with transaction scoped EntityManager,
it is detached from persistence
context and you may no longer rely on
lazy loading (in fact, JPA
specification does not specify the
behavior in such situation, probably
some vendor dependent exception will
be thrown...) Of course, you may use
EntityManager with extended
persistence context, holding the
transaction and persistence context as
long as you want. But this feature is
only available for SFSB, while DAO
classes are typical examples of
stateless services, since they only
dispatch calls to the persistence
layer. Additionally, having dedicated
DAO bean instance for each client
seems to be a big overkill.
I'm however not sure it is really true. From my understanding you should be able to write a servlet filter which uses the UserTransaction to start and commit the transaction (like the regular filter in OSIV). EJB would then participate in the transaction started in the filter and the EntityManager would remain open. I haven't tested it though, but my suggestion would be to give it a try.