JTA with PersistenceUnit - java

Can #PersistenceUnit be used with JTA in JPA? If so, how is it possible?
Per http://tomee.apache.org/jpa-concepts.html:
With <persistence-unit transaction-type="RESOURCE_LOCAL"> [...]
You must use the EntityManagerFactory to get an EntityManager
[...]
An EntityManagerFactory can be injected via the #PersistenceUnit annotation only (not #PersistenceContext)
With <persistence-unit transaction-type="JTA"> [...]
An EntityManager can be injected via the #PersistenceContext annotation only (not #PersistenceUnit)
I have a similar code which uses JTA and #PersistenceUnit at the same time. But sometimes I am having NullPointerException when accesing transaction (defined as #Resource).

Using JTA means that you delegate the work to the container. You can override it by using a UserTransaction. Your quotation contains all the answers you want to know. Using PersistenceUnit to get an EntityManager won't work.
If you are using RESOURCE_LOCAL you are responsible for the transaction itself, by using EntityManager.getTransaction(). An entity manager is created by an EntityManagerFactory. To obtain that factory, you can use PersistenceUnit.
So the simple answer is no, if you rely on container managed entity managers.
As example see http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html
Application Managed Entity Managers = RESOURCE_LOCAL can use UserTransaction (which are part of JTA).

What does entity manager means???
If i am a naive programmer i could simply interpret something which manages entity & Indeed it means the same.
An Entity Manager is been instantiated with the help of an Entity Manager Factory. A connection to a database is managed by the entity manager i.e. it provides functionality for performing operations on a database. Therefore we could say if an application needs multiple database connections, an EntityManagerFactory will be constructed for a specific database which provides an efficient way to construct multiple EntityManager instances(if required, even single instance of entity manager can the job depending upon the requirement you may opt for multiple instances) for that database required for every HTTP request. We shall understand this with the help of an example. Suppose we have a
Database : A , having a relational tables B and C.
So for A, an instance of entity manager factory will be instantiated. Now we if ever want to perform any update to table B & lets say delete operation for table C, either two different entity manager could be instantiated or same the entity manager instance can be utilized for both.
The instantiation of Entity Manager Factory itself is considered to be less efficient but since it's a one time activity therefore it's manageable task because Entity Manager Factory once instantiated, it will serve the entire application
The entity manager instantiated is associated with a persistence context.
#PersistenceUnit(unitName = "MyDatabase")
EntityManagerFactory emf;
EntityManager entityManager = emf.createEntityManager();
or
#PersistenceContext(unitName = "MyDatabase")
private EntityManager entityManager;
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.
EntityManagerFactory defines another method for instantiation of EntityManager that, like the factory, takes a map of properties as an argument. This form is useful when a user name and a password other than the EntityManagerFactory's default user name and password have to specified:
Map properties = new HashMap();
properties.put("javax.persistence.jdbc.user", "kashyap");
properties.put("javax.persistence.jdbc.password","kashyap");
EntityManager em = emf.createEntityManager(properties);
Within the persistence context, the entity instances and their lifecycle are managed. By Entity instance, we mean instance of an entity & each entity designates relational table in the database. Entity Manager is actually an interface which provides methods to create and remove persistent entity instances, to find entities by their primary key, and to query over entities so together these functionalities are grouped under operations we perform. Operations that modify the content of a database require active transactions. Transactions are managed by an Entity Transaction instance obtained from the EntityManager.
Precise Definition :-
An Entity Manager is defined by a persistence unit. A persistence unit defines the set of all classes that are related or grouped by the application, and which must be colocated in their mapping to a single database.
Below i'm writing a code snippet for better understanding :-
try {
em.getTransaction().begin();
// Operations that modify the database should come here.
em.getTransaction
/**
*getTransaction() EntityManager's method Return the resource-level EntityTransaction object. See JavaDoc Reference Page
*/
em.getTransaction().commit();
}
finally {
if (em.getTransaction().isActive())
em.getTransaction().rollback();
}
Lets proceed as per JPA Specification :-
1) Extended vs Transactional - Scoped :
By Default the Transactional Persistence Context is in used which means all changes are flushed and all managed entities become detahced when the current transaction commits.
The Extended scope is available only for Stateful EJBs & it even makes a perfect sense since stateful beans can save the state therefore one can say end of
one business method doesn't necessary means the end of the transaction.
With the Stateless beans, it has a different aspect - We have business method that must end when the business method finishes.
===> One Method = One Transaction;
Only Transactional-Scoped Entity Manager is allowed for Stateless Beans
You can control if the EntityManager is extended or transactional during the EntityManager Injection :-
#PersistenceContext (type = javax.persistence.PersistenceContextType.EXTENDED)
EntityManager emng;
By Default it's javax.persistence.PersistenceContextType.TRANSACTION
Extended and Transaction Scoped PersistenceContext are allowed only in case of container-managed EntityManagers.
Time to step up a bit with: Container-managed vs Application-managed
2) Container-managed vs Application-managed :
#PersistenceContext
EntityManager emng;
Above statement authorises Container to inject the entity manager for you, hence Container-Managed.
Alternatively, you can create an EntityManager by yourself using EntityManagerFactory But this time the injection will be bit different -
#PersistenceUnit
EntityManagerFactory emf;
Now to get the EntityManager you need to invoke
emf.createEntityManager();
And here it is - you're using the application managed Persistence Context. Now you're responsible for creation and removal of EntityManagers.
Focus before you read the next para because that's what the tangled context , i'm trying to resolve-
You might use createEntityManager if you want to have control over created EM - e.g. if you need to move the created EntityManager across multiple beans involved in the trasaction - the container won't do it for you and every time you invoke createEntityManager(), you're creating an EntityManager that is connected to the new PersistenceContext. You might use the CDI for EntityManager's sharing.
Stay tuned for Entity Transaction - JPA and Resource-local, will be posting a detailed discussion on it.
Hope it gives a brief idea about the context. & Feel free to post queries.
Read the second part from here

Related

Will an EntityManager with context type TRANSACTION in a Singleton join an external bean-managed transaction?

Suppose I have a Singleton bean with an EntityManager in it. The singleton also specifies (on method or class level) a transaction attribute REQUIRED. The entity manager is obtained via an #PersistenceContext injection which specifies persistence context type TRANSACTION. For all intents and purposes, if a method on this singleton is invoked with an existing transaction, the entity manager should join the transaction or possibly provide an already existing one linked to that transaction via proxy. If such a method is invoked outside of a transaction a new transaction will be started for the duration of the method invocation.
Now suppose we have a second bean which uses bean-managed transactions and injects the singleton. If it explicitly starts a user transaction and then invokes a method on the singleton, will the entity manager in that method join that user transaction? Will the jump from bean-managed to container-managed transaction context even work? I know the other way around doesn't and forms a barrier.
The singleton class:
#Singleton
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class PersistenceSingleton {
#PersistenceContext(unitName = "test", type = PersistenceContextType.TRANSACTION)
private EntityManager em;
public void doStuff() {
// perform actions with the entity manager that imply changes in the database
}
}
The bean with user transactions (might as well be stateless or stateful):
#Singleton
#TransactionManagement(TransactionManagementType.BEAN)
public class PersistenceFacade {
#EJB
private PeristenceSingleton ps;
#Resource
private UserTransaction userTx;
public void doStuff() {
userTx.begin();
ps.doStuff();
userTx.commit();
}
}
Does the transaction started in method doStuff() of the PersistenceFacade get taken into account when invoking doStuff() on the PersistenceSingleton? Does the entity manager automatically join the transaction and behave as expected from transaction isolation during concurrent access?
UserTransaction is used for changing the default transaction demarcation but we still control the JTA transactions.
https://www.javacodegeeks.com/2013/03/types-of-entity-managers-application-managed-entitymanager.html says:
If you have UserTransaction you can start demarcating what is to be executed within the transaction. Notice that you’re still controlling
the JTA transactions
so The persistence context propagation rule will be applied for UserTransaction demarcation.
pro JPA book says:
When a method is invoked on the transaction-scoped entity manager, it
must first see whether there is a propagated persistence context. If
one exists, the entity manager uses this persistence context to carry
out the operation. All subsequent transaction-scoped entity manager
operations, in this component or any other, will thereafter use this
newly created persistence context. This behavior works independently
of whether container-managed or bean-managed transaction demarcation
has been used.
the answer to your questions is yes(first question)
Does the entity manager automatically join the transaction and behave
as expected from transaction isolation during concurrent access?
entity manager checks the existence of a propagated persistence context and uses it.

When using a new JTA Transaction, what happens to PersistenceContexts in other transactions?

I'm using CMT with a stateless EJB. Suppose I have two methods, one of which is a timeout for an EJB timer and one which modifies existing entities:
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
#Timeout
public void cullOldEntities() {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaDelete<T> cd = cb.createCriteriaDelete(clazz);
Root<T> root = cd.from(clazz);
Path<Date> dateCreatedPath = root.get("lastUpdated");
cd.where(cb.lessThan(dateCreatedPath, dateOfExpiry()));
em.createQuery(cd).executeUpdate();
}
public void modifyEntities(...)
As cullOldEntities requires a new transaction, a new persistence context is created and then it is committed when the method ends. The issue is what happens to a preexisting persistence context of another transaction.
If modifyEntities and then cullOldEntities are called so they run concurrently what happens to modifyEntities persistence context if cullOldEntities finishes first and has it's persistence context committed?
Does the modifyEntities's persistence context get synchronized with the changes made?
If not what will happen when an entity is modified?
How can I do a bulk delete that is safe with concurrent modification?
EntityManager not thread safe. So, without Locking last commit will override changes which was made in another transaction.
The behaviour (and subsequent effect on design of transaction propagation) depends upon the type of scope being used for persistence context. The two kinds are Transaction scoped and Extended Persistence context (which can span multiple transactions). For Transaction scoped persistence context - before the cullOldEntities() method call starts,
the container will suspend the transaction inherited if any and will start a new
transaction (because of attribute TransactionAttributeType.REQUIRES_NEW). When the entity manager method requiring a transaction is invoked on the entity manager, it will check the current transaction for an active persistence context and none will be found. A new
persistence context will be created starting with that call, and this persistence context will be the
active persistence till the method contextcullOldEntities() ends. Because the transaction
started in cullOldEntities() is different from the earlier one ( if there was one) , the entities managed by the previous persistence context
will not be visible to this new one.
An extended persistence context however is typically scoped to the stateful session bean to which it is bound.
the extended entity manager of a stateful session bean always uses the same persistence
context. The stateful session bean is associated with a single extended persistence context that is
created when the bean instance is created and closed when the bean instance is removed.

How to persist entities, how to create table from entities without "main class"?

I'm developing an application, and I started with creating my JPA entities (annotation + persistence.xml). Then in my persistence.xml file, I created a connection for a MySql data base (the connection is fine).
The problem is that I just don't know how to persist my entities without creating a "main class".
Do I have to run my main class for every single entity that I'm going to create?
To persist an entity, you need an instance of entityManager. Since you have a Java EE container you can get an instance of entityManager using the annotation #PersistenceContext in some bean
What I mean by some bean ? It's a bean managed by the Java EE container. So, for instance you have to define a bean like this :
#Stateless
public class MyController{
#PersistenceContext
private EntityManager em;
public void persistIt(Object anEntity){
em.persist(anEntity);
}
}
The annotation #Stateless indicate to the container that it must manage this class and take care of providing an instance of the entityManager when needed.
So to answer precisely to your question: it is not mandatory to have another class to persist an entity, as soon as you find a way to get access to an entityManager instance.
But:
it is definitively NOT a best practice.
to take advantages of entityManager injection: you must use another managed bean so that entityManager can be injected by the container.
Additionally, the controller is where you can handle your transactions properly.

Handle JPA cache

I have many persistence units in my persistence.xml, one by postgreSQL schema.
I instantiate my EntityManager whenever I need by creating EntityManagerFactory dynamically :
EntityManagerFactory emf = Persistence.createEntityManagerFactory(schemaToChoose);
EntityManager em = emf.createEntityManager();
and it works fine. But thus, I don't use container injection.
Now, I wonder if it doesn't cost too much resources by this way ?
I don't probably understand well JPA cache but I believe that entities are stored inside em cache and inside emf cache, there are 2 levels. So when I instantiate em and emf each time I probably loose JPA cache and thus, I recreate it each time too.
I have 2 questions : could instantiate each time emf and em impact perfomances ? Should I inject as many em that I have schemas instead to keep cache ?
Thank you
An EntityManagerFactory is a heavyweight, long-to-create object. It should be created only once, and then reused. Indeed, every time it's created, it parses the persistence.xml file, computes the mapping metadata of every entity, etc.
If you're running inside a Java EE container, then you should definitely let the container instantiate it for you, and inject the entity managers inside your EJBs.
I find it strange that a single application uses several database shemas. Why is it so?
Regarding the caches: there is a first-level cache associated with the entity manager (which is a short-lived cache, typically having the same life-time as a transaction. It's also possible to have a second-level cache, associated with the entity manager factory, but this is off by default, and, if enabled, must only be used for some entities and configured with care.
You basically have a multi-tenant pattern. EJB injection doesn't handle this very well.
An EntityManagerFactory is not something you want to create more than once, and does contain the shared cache. (the share cache default is not specified by JPA, it is on by default in EclipseLink, but configurable through JPA cache-mode and #Cacheable and #Cache).
I would recommend some sort of registry for your factories. Perhaps this would even be an application object, such as your Universe.
public class Universe {
static Map<String, Universe> universes;
EntityManagerFactory emf;
public static Universe getUniverse(String schema) {
... hopefully you get the idea ...
}
public EntityManagerFactory getEntityManagerFactory() {
return emf;
}
}
Also, I would recommend you look into EclipseLink's multi-tenant support,
http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_multitenant.htm#BABEGBIJ

JPA's EntityManager should be RequestScoped?

I am developing a JavaEE6 based web application using JBoss7.
In my application I am injecting the EntityManager in my EJBs as:
class ForumServiceEJB
{
#PersistenceContext(type=EXTENDED)
private EntityManager em;
}
class TopicServiceEJB
{
#PersistenceContext(type=EXTENDED)
private EntityManager em;
}
The problem when I update some data using ForumServiceEJB's EntityManager then the changes are made into DB but TopicServiceEJB's EntityManager is not able to see those changes and the results are always fetched from Cache.
I am using ExtendedPerssisteenceContext as My Entities contain child Entity Collections of Lazy Loading type.
How can I use/Inject EntityManager of type ExtendedPersistenceContext and make different EntityManager in one EJB can still see the changes done by other different EJB EntityManagers?
Somewhere I read EntityManagers should be RequestScoped objects.
public class MyEntityManagerProducers {
#Produces #RequestScoped
public EntityManager createDbEm() {
return Persistence.createEntityManagerFactory("forumDb").
createEntityManager();
}
public void disposeUdEm(#Disposes EntityManager em) {
em.close();
}
Is it the way to go?
I am using ExtendedPerssisteenceContext as My Entities contain child
Entity Collections of Lazy Loading type.
This is not a good reason to use EXTENDED. I would suggest you to make it default, which is TRANSACTION. And it's good to make your EntityManager request-scoped, or method-scoped, in non-enterprise environment or when using application-managed persistence, as this is not a very heavy object to create. Moreover, neither using application-scoped EntityManager is a good idea, as it is not threadsafe.
Having said that, as you are using JBoss, you should let the container handle the lifecycle of EntityManager, in case you are using JTA. Hence, just inject that with everything default
Note:
Only stateful session beans can have a container-managed, extended entity manager.
Links:
http://javanotepad.blogspot.com/2007/08/managing-jpa-entitymanager-lifecycle.html
https://blogs.oracle.com/enterprisetechtips/entry/extended_persistence_context_in_stateful
Suggestions:
Your business method should know whether to load the children or not. But that's the ideal case. A number of times we can't say that and completely depends on the user input -- we can't predict that well. Therefore, there are two solutions available,
make a separate AJAX call to load children
Use the filter called open-session-in-view. I would prefer the former.
Links:
https://community.jboss.org/wiki/OpenSessionInView
http://static.springsource.org/spring/docs/1.2.9/api/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.html
Why is Hibernate Open Session in View considered a bad practice?

Categories

Resources