Use of joinTransaction in JPA - java

The following code is from JPA specs. I could not understand why em.joinTransaction() is required in createLineItem(int quantity).
Can anyone provide an apt explanation?
#Stateful
public class ShoppingCartImpl implements ShoppingCart {
#PersistenceUnit
private EntityManagerFactory emf;
private EntityManager em;
private Order order;
private Product product;
#PostConstruct
public void init() {
em = emf.createEntityManager();
}
public void initOrder(Long id) {
order = em.find(Order.class, id);
}
public void initProduct(String name) {
product = (Product) em
.createQuery("select p from Product p where p.name = :name")
.setParameter("name", name).getSingleResult();
}
public LineItem createLineItem(int quantity) {
em.joinTransaction();
LineItem li = new LineItem(order, product, quantity);
order.getLineItems().add(li);
em.persist(li);
return li;
}
#Remove
public void destroy() {
em.close();
}
}

First, a few words of theory...
An application-managed entity manager participates in a JTA transaction in one of two ways.
If the persistence context is created inside the transaction, the persistence provider will automatically synchronize the persistence context with the transaction.
If the persistence context was created earlier (outside of a transaction or in a transaction that has since ended), the persistence context can be manually synchronized with the transaction by calling joinTransaction() on the EntityManager interface. Once synchronized, the persistence context will automatically be flushed when the transaction commits.
After reading the above definition a few questions may arise:
how do we know that ShoppingCartImpl participates in JTA transaction ?Because the class has been annotated with #Stateful (or #Stateless) annotation so the intention is to execute the class within Java EE environment which by default uses JTA transactions. A class doesn't need such annotation, if it will be executed in Java SE environment.
how do we know application-managed entity manager is used in this particular case?Because we are using #PersistenceUnit annotation to inject EntityManagerFactory and then manually creating and destroying EntityManager. By doing this we are telling Java EE container that we don't want our transaction to be automatically managed (like in case of transaction-scoped entity manager or extended entity manager types).
why em.joinTransaction() is required in createLineItem method?By calling em.joinTransaction() we notify the application-managed persistence context that it should synchronize itself with the current JTA transaction. Without such call the changes to Order would not be flushed to the underlying database when the transaction commits (at the end of createLineItem method). NOTE: since EntityManagerFactory instances are thread-safe and EntityManager instances are not, an application must not call em.joinTransaction() on the same entity manager in multiple concurrent transactions.

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.

Spring transactions, EntityManager lifecycle

I am developing a project with spring framework.
I have following architecture: all database code is in dao classes, all application logic is in service classes, http requests are processed using spring mvc rest controllers.
#Repository
public class UserDao {
#PersistenceContext
private EntityManager em;
public void editUser(User user) {
...
}
}
#Service
public class UserService {
#Autowired
private UserDao userDao;
#Transactional
public void editUser(User user) {
...
}
}
#RestController
#RequestMapping(value = "/UserCtrl", produces = "application/json;charset=UTF-8")
public class UserCtrl {
private static final Logger logger = LogManager.getLogger(AppConfig.LOGGER_NAME);
#Autowired
private ApplicationContext appContext;
#RequestMapping(value = "/editUser")
public ActionResult editUser(#ModelAttribute User user) {
ActionResult rslt = new ActionResult();
try {
UserService userService = appContext.getBean(UserService.class);
userService.editUser(user);
rslt.setSuccess(true);
} catch (Exception ex) {
logger.error("editUser", ex);
rslt.setSuccess(false);
}
return rslt;
}
}
This code works correctly.
One thing I cannot understand is how aop proxy of UserService bean starts transaction, when EntityManager is injected only in UserDao class. Can somebody explain me how this works and how EntityManager lifecycle is managed by spring framework ?
Any help appreciated.
The TransactionManager is responsible for managing the transaction boundaries
in Spring Framework.
When you annotate the business method with #Transactional you are instrumenting the method with an aspect.
Before executing the method, this aspect interact with TransactionManager which decides if it is necessary to create a new Transaction or use a preexisting one. In the case of create a new Transaction, a new Entity Manager is created from EntityManagerFactory and is associated to the current thread alonside with the Transaction.
The EntityManager is responsible to iterate with the database. When you inject it with #PersistenceContext, Spring injects an proxy to the EntityManager.
Whenever an operation is executed in the EntityManager proxy it looks the EntityManager associated with the thread.
Based on the snippet of code you provide you are using spring with some implementation of JPA you are using J2EE container for your web application and bases on my guess I think this is good article about how things works.
Basic concepts :
EntityManager - A class that manages the persistent state(or lifecycle) of an entity.
Persistence Unit - is a named configuration of entity classes.
Persistence Context - is a managed set of entity instances. The entities classes are part of the Persistence Unit configurations.
Managed Entities - an entity instance is managed if it is part of a persistence context and that Entity Manager can act upon it.
Based on this article you use Container Managed EntityManager by using #PersistenceContext
When a container of the application(be it a Java EE container or any other custom container like Spring) manages the lifecycle of the Entity Manager, the Entity Manager is said to be Container Managed. The most common way of acquiring a Container Managed EntityManager is to use #PersistenceContext annotation on an EntityManager attribute.
And the injection is like this :
A Transaction Scoped Entity Manager is returned whenever a reference created by #PersistenceContext is resolved.
and
Every time an operation is invoked on an Entity Manager, the container proxy(the container creates a proxy around the entity manager while instantiating it ) checks for any existing Persistence Context on the JTA Transaction. If it finds one, the Entity Manager will use this Persistence Context. If it doesnt find one, then it will create a new Persistence Context and associates it with the transaction.
So the lifecycle of of entity manager is managed by your container and
we work with an instance of EntityManager, the only role of EntityManager is to determine the lifetime of the Persistence Context. It plays no role in dictating how a Persistence Context should behave. To reiterate, Persistence Context is a managed set of Entity instances. Whenever a transaction begins, a Persistence Context instance gets associated with it. And when a Transaction ends(commits for example), the Persistence Context is flushed and get disassociated with the transaction.
In the nutshell container instantiate your EntityManager by the EntityManagerFactory you provide and manage it's lifecycle but inject the proxy of EntityManager for you. The TransactionManager is responsible for creating, commiting and ... tranactions based on annotations you provide ,whenever it begins the transaction the PersistancecContext associated with it and when the tranasction ends it commites the state of PersistenceContext. The EntityManager works with PersistenceContext and if it's not provided the EntityManager creates one. The EntityManager is threadsafe as long as it holds no state and the state (PersistenceContext) is attached to current tranasction.
Hope this helps.

JTA EntityManager without manual commits

I'm trying to move out my project from Seam 3.
Now I'm stuck on JTA transactions after switching off Seam Faces module. There was integrated transaction management. Transactions were begun and commit automatically - without manual commit.
Now when I try to execute EntityManager.persist() or EntityManager.merge(Object entity), I've got error:
JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context)
Is there any way to force JTA to start transaction and commit it transparently?
Ps. Funny thing - some time ago I was looking for solution how to force manual commit/rollback in Seam3.
OK, if I put bean into #Stateless state - then it behaves as I expected.
But...
Isn't it - that if I put application managed EntityManager - then I should manage transaction on my own (method testApplicationJTA() in example below), but if I use container managed EntityManager - then it should work without transaction managing (method testContainterJTA() ) ?
My example:
#Named
#SessionScoped
public class Test implements Serializable {
private static final long serialVersionUID = 1L;
#PersistenceContext
private EntityManager em;
#PersistenceUnit
private EntityManagerFactory emf;
#Resource
private UserTransaction utx;
public void testContainerJTA() {
TestEntity entity = em.find(TestEntity.class, 1L);
entity.setName("dddddd");
em.merge(entity);
}
public void testApplicationJTA() {
EntityManager mgr = emf.createEntityManager();
TestEntity entity = em.find(TestEntity.class, 1L);
entity.setName("fffff");
try {
utx.begin();
mgr.joinTransaction();
mgr.merge(dict);
utx.commit();
} catch (Exception e) {
utx.rollback();
}
mgr.close();
}
}
In my example above method testContainerJTA() doesn't work. Why?
If I'll remove #SessionScoped and put #Stateless then method testApplicationJTA() doesn't work, but testContainerJTA() works. Why?
Should't they work both always - as application managed and container managed?
OK, so it is possible to make CDI bean tansactional - with interceptors :-)
Finally I managed to solve my problem reading this article:
http://smokeandice.blogspot.com/2009/12/cdi-and-declarative-transactions.html
Edit:
From JEE7 there is new #Transactional annotation which takes all JPA actions in CDI bean or method into transaction.

how inject entityManager to EJB from other EJBModule

I have 2 ejb-module in my project, ejb-module1 and ejb-module2. ejb-module1 contain entity clases and persistence unit, there is a ejb with a Entity Manager like this:
#Stateful
public class ErpTools implements ErpToolsLocal {
#PersistenceContext(unitName = "erp-ejbPU")
private EntityManager em;
public EntityManager getEm() {
return em;
}
public void setEm(EntityManager em) {
this.em = em;
}
in ejb-module2 i have other ejb that need use entity manager from ejb-module1,
i try with this,
String ejbql = "SELECT e from CtEmpresaCliente e ORDER BY e.idCliente ASC";
Query query = this.erpTools.getEm().createQuery(ejbql);
empresaClientes = query.getResultList();
but send this exception:
"Unable to retrieve EntityManagerFactory for unitName erp-ejbPU"
debuging in this point Query query = this.erpTools.getEm().createQuery(ejbql);
this.erpTools.getEm() is not null.
note: Using Netbeans, JPA, JEE6, EJB 3.1
Calls to EJBs that are in different modules are similar to remote invocations in the sense that they use pass by value semantics and undergo serialization / de-serialization. In this case the network is not used, but all other aspects of the remote invocations are still happening.
What this means for you is that even though you get a non null EntityManager from another EJB module, it is serialized / de-serialized and by the time it makes it to the other EJB module it no longer refers to a valid persistence context (since it does not exist in the calling EJB module).

Why different persistence units with separated data sources query the same data source?

I'm developing a webapp which needs access to two different database servers (H2 and Oracle).
The container is an Apache Tomee 1.5.1 and I'm using the Java EE stack with libraries provided in it (JSF, JPA, CDI, EJB, etc.).
I'm trying to use two entity managers inside an XA transaction to extract data from the Oracle database and persist it in the H2 after transforming it, BUT all the queries are executed against the H2 database no matter the entity manager I use. Any help?
EDIT: I found that if I try to access the entity managers in inverse order, they behavior is the same but accessing to Oracle. I.e.: the entity managers stay with the first database accessed.
The EJB where this happens (calling service.getFoo() from JSF):
#Named
#Stateless
public class Service {
#Inject
#OracleDatabase
private EntityManager emOracle;
#Inject
#H2Database
private EntityManager emH2;
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public List<Foo> getFoo() {
TypedQuery<Foo> q = emH2.createQuery(
"SELECT x FROM Foo f", Foo.class);
List<Foo> l = q.getResultList();
if (l == null || l.isEmpty()) {
update();
}
return q.getResultList();
}
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public void update() {
// FAIL: This query executes against H2 with Oracle entity manager!
List<Object[]> l = emOracle.createNativeQuery("SELECT * FROM bar ").getResultList();
//more stuff...
}
}
The resource producer (CDI) for the entity managers (where #H2Database and #OracleDatabase are qualifiers):
public class Resources {
#Produces
#PersistenceContext(unitName = "OraclePU")
#OracleDatabase
private EntityManager emOracle;
#Produces
#PersistenceContext(unitName = "H2PU")
#H2Database
private EntityManager emH2;
}
My peristence.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="H2PU"
transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>H2DS</jta-data-source>
<class>my.app.h2.Foo</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
<persistence-unit name="OraclePU" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>OracleDS</jta-data-source>
<class>my.app.oracle.Bar</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
</persistence>
And finally, the data sources inside tomee.xml (there aren't any other data sources configured inside this file):
<Resource id="OracleDS" type="javax.sql.DataSource">
jdbcDriver = oracle.jdbc.xa.client.OracleXADataSource
jdbcUrl = jdbc:oracle:thin:#server:port:instance
jtaManaged = true
password = abcde
userName = user
</Resource>
<Resource id="H2DS" type="javax.sql.DataSource">
jdbcDriver=org.h2.jdbcx.JdbcDataSource
jdbcUrl=jdbc:h2:h2/db;AUTO_SERVER=TRUE
jtaManaged = true
password = edcba
userName = user
</Resource>
Container Managed Persistence Contexts
When using container-managed persistence contexts (as you are via #PersistenceContext annotations), the JPA spec specifies that only ONE persistence context may be associated with a JTA transaction.
The persistence context is created by the Java EE container. Despite appearances of the code (#PersistenceContext annotations seem to suggest that PC is injected directly into your EntityManager instance variables), the persistence context is actually stored as a reference WITHIN THE JTA TRANSACTION. Each time an EntityManager operation occurs it does not refer to it's own internal persistence context. Instead it does a special operation because it is container managed - it always looks up the persistence context within the JTA Transaction and uses that. This is called JTA persistence context propagation.
Some Quotes from the JPA spec:
When a container-managed entity manager is used, the lifecycle of the
persistence context is always managed automatically, transparently to
the application, and the persistence context is propagated with the
JTA transaction.
Container-managed Transaction-scoped Persistence Context
...
A new persistence context begins when the container-managed entity manager
is invoked[76] in the scope of an active JTA transaction, and there is
no current persistence context already associated with the JTA
transaction. The persistence context is created and then associated
with the JTA transaction.
Container-managed Extended Persistence Context
...
A container-managed extended persistence context can only be initiated within the scope
of a stateful session bean. It exists from the point at which the stateful session bean
that declares a dependency on an entity manager of type PersistenceContextType.EXTENDED
is created, and is said to be bound to the stateful session bean. The dependency on the
extended persistence context is declared by means of the PersistenceContext annotation or persistence-context-ref deployment descriptor element.
The persistence context is closed by the container when the #Remove method of the stateful session bean completes (or the stateful session bean instance is otherwise destroyed).
Requirements for Persistence Context Propagation
... If a component is called and there is no JTA transaction ..., the persistence context is not propagated.
• Invocation of an entity manager defined with PersistenceContext-
Type.TRANSACTION will result in use of a new persistence context.
• Invocation of an entity manager defined with PersistenceContext-
Type.EXTENDED will result in the use of the existing extended persistence context
bound to that component.
... If a component is called and the JTA transaction is propagated into that component:
• If the component is a stateful session bean to which an extended persistence context has been bound and there is a different persistence context bound to the JTA transaction, an EJBException is thrown by the container.
• Otherwise, if there is a persistence context bound to the JTA transaction, that persistence context is propagated and used.
So that's your problem.
The obvious $64 question: WHY does the spec ask for this???
Well, it's because it's a deliberate trade-off that brings powerful EntityManager magic to EJBs.
Using JTA transactions to propagate a single persistence context has a limitation: transactions cannot straddle multiple persistence contexts, so can't straddle multiple databases.
However, it also has a tremendous advantage: any entityManager declared in EJBs can automatically share the same persistence context and hence can operate on the same set of JPA entities and partake in the same transaction. You can have a chain of EJBs calling other EJBs of any complexity and they all behave sensibly and consistently against the JPA entity data. And they also do not need the complexity of consistently intializing/sharing entity manager references across method invocations - the EntityManagers can be declared privately in each method. The implementation logic can be very simple.
The Answer To Your Problem: Use Application-Managed Persistence Contexts (via application-managed EntityManagers)
Declare your entityManager via one of these approaches:
// "Java EE style" declaration of EM
#PersistenceUnit(unitName="H2PU")
EntityManagerFactory emfH2;
EntityManager emH2 = emfH2.createEntityManager();
OR
// "JSE style" declaration of EM
EntityManagerFactory emfH2 = javax.persistence.Persistence.createEntityManagerFactory("H2PU");
EntityManager emH2 = emfH2.createEntityManager();
and the same for emfOracle & emOracle.
You must call em.close() when you are finished with each EM - prefereably via a final { } clause or via a Java 7 try-with-resources statement.
Application-managed EMs still partake in (i.e. synchronise with) JTA transactions. Any number of application-managed EMs can partake in a single JTA transaction - but none of these will ever have their persistence context associated with or propagated to any container managed EM.
If the EntityManager is created outside the context of a JTA transaction (before the transaction commenced), then you must ask it explicity to join the JTA transaction:
// must be run from within Java EE code scope that already has a JTA
// transaction active:
em.joinTransaction();
Or even simpler, if the EntityManager is created inside the context of a JTA transaction, then the application-managed EntityManager automatically joins the JTA transaction implicity - no joinTransaction() needed.
So Application-managed EMs can have a JTA transaction that straddles multiple databases. Of course, you can alway run a local resource JDBC transaction independent of JTA:
EntityTransaction tx = em.getTransaction();
tx.begin();
// ....
tx.commit();
EDIT: EXTRA DETAILS for Transaction Management with Application-Managed Entity Managers
WARNING: the code samples below are for educational use - I've typed them off the top of my head to help explain my points & haven't had time to compile/debug/test.
The default #TransactionManagement parameter for EJBs is TransactionManagement.CONTAINER and the default #TransactionAttribute parameter for EJB methods is TransactionAttribute.REQUIRED.
There are four permutations for transaction management:
A) EJB with CONTAINER managed JTA transactions
This is the preferred Java EE approach.
EJB class #TransactionManagement annotation:
must set to TransactionManagement.CONTAINER explicitly or omit it to implicitly use the default value.
EJB method #TransactionAttribute annotation:
must set to TransactionAttribute.REQUIRED explicitly or omit it to implicity use the default value. (Note: if you had a different business scenario, you could use TransactionAttribute.MANDATORY or TransactionAttribute.REQUIRES_NEW if their semantics matched your needs.)
Application-managed entity managers:
they must be created via Persistence.createEntityManagerFactory("unitName") and emf.createEntityManager(), as described above.
Join the EntityManagers with the JTA transaction:
Create the EntityManagers WITHIN a transactional EJB method and they will automatically join the JTA transaction. OR if EntityManagers are created beforehand, call em.joinTransaction() within a transaction EJB method.
Call EntityManager.close() when you are finished using them.
That should be all that's required.
Basic Examples - just use more EntityManagers for transaction across multiple DBs:
#Stateless
public class EmployeeServiceBean implements EmployeeService {
// Transactional method
public void createEmployee() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("EmployeeService");
EntityManager em = emf.createEntityManager();
Employee emp = ...; // set some data
// No need for manual join - em created in active tx context, automatic join:
// em.joinTransaction();
em.persist(emp);
// other data & em operations ...
// call other EJBs to partake in same transaction ...
em.close(); // Note: em can be closed before JTA tx committed.
// Persistence Context will still exist & be propagated
// within JTA tx. Another EM instance could be declared and it
// would propagate & associate the persistence context to it.
// Some time later when tx is committed [at end of this
// method], Data will still be flushed and committed and
// Persistence Context removed .
emf.close();
}
}
#Stateful
public class EmployeeServiceBean implements EmployeeService {
// Because bean is stateful, can store as instance vars and use in multiple methods
private EntityManagerFactory emf;
private EntityManager em;
#PostConstruct // automatically called when EJB constructed and session starts
public void init() {
emf = Persistence.createEntityManagerFactory("EmployeeService");
em = emf.createEntityManager();
}
// Transactional method
public void createEmployee() {
Employee emp = ...; // set some data
em.joinTransaction(); // em created before JTA tx - manual join
em.persist(emp);
}
// Transactional method
public void updateEmployee() {
Employee emp = em.find(...); // load the employee
// don't do join if both methods called in same session - can only call once:
// em.joinTransaction(); // em created before JTA tx - manual join
emp.set(...); // change some data
// no persist call - automatically flushed with commit
}
#Remove // automatically called when EJB session ends
public void cleanup() {
em.close();
emf.close();
}
// ...
}
B) EJB with BEAN managed JTA transactions
Use #TransactionManagement.BEAN.
Inject the JTA UserTransaction interface, so the bean can directly mark JTA transactions.
Manually mark/synchronize the transaction via UserTransaction.begin()/commit()/rollback().
Ensure the EntityManager joins the JTA transaction - either create the EM in an active JTA transaction context OR call em.joinTransaction().
Examples:
#TransactionManagement(TransactionManagement.BEAN)
#Stateless
public class EmployeeServiceBean implements EmployeeService {
// inject the JTA transaction interface
#Resource UserTransaction jtaTx;
public void createEmployee() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("EmployeeService");
EntityManager em = emf.createEntityManager();
try {
jtaTx.begin();
try {
em.joinTransaction();
Employee emp = ...; // set some data
em.persist(emp);
// other data & em operations ...
// call other EJBs to partake in same transaction ...
} finally {
jtaTx.commit();
}
} catch (Exception e) {
// handle exceptions from UserTransaction methods
// ...
}
Employee emp = ...; // set some data
// No need for manual join - em created in active tx context, automatic join:
// em.joinTransaction();
em.persist(emp);
em.close(); // Note: em can be closed before JTA tx committed.
// Persistence Context will still exist inside JTA tx.
// Data will still be flushed and committed and Persistence
// Context removed some time later when tx is committed.
emf.close();
}
}
C) POJO/Non-EJB with hand-coded (bean managed) resource local transactions (not JTA)
Simply use the JPA EntityTransaction interface for tx demarcation (obtained via em.getTransaction()).
Example:
public class ProjectServlet extends HttpServlet {
#EJB ProjectService bean;
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// ...
try {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPU");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
bean.assignEmployeeToProject(projectId, empId);
bean.updateProjectStatistics();
} finally {
tx.commit();
}
} catch (Exception e) {
// handle exceptions from EntityTransaction methods
// ...
}
// ...
}
}
D) POJO/Non-EJB with hand-coded (POJO-managed) JTA transactions
This assumes the POJO/component is running in some container that has JTA support.
If in a Java EE container, can use Java EE resource injection of JTA UserTransaction interface.
(Alternatively, can explicitly lookup a handle to the JTA interface and do demarcation on it, then call em.getTransaction().joinTransaction() - see JTA spec.)
Example:
public class ProjectServlet extends HttpServlet {
#Resource UserTransaction tx;
#EJB ProjectService bean;
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// ...
try {
tx.begin();
try {
bean.assignEmployeeToProject(projectId, empId);
bean.updateProjectStatistics();
EntityManagerFactory emf = Persistence.createEntityManagerFactory("myPU");
EntityManager em = emf.createEntityManager();
// Should be able to avoid explicit call to join transaction.
// Should automatically join because EM created in active tx context.
// em.joinTransaction();
// em operations on data here
em.close();
emf.close();
} finally {
tx.commit();
}
} catch (Exception e) {
// handle exceptions from UserTransaction methods
// ...
}
// ...
}
}
Try to create a Query not a native query first, returning a list of Bars.
Also try to comment the H2 injection in your EJB. If it works, then you know that is a CDI conflict problem.

Categories

Resources