Seam-managed transactions how-to - java

Seam advises using an Extended persistent context in a Stateful Session Bean, in order to have Seam-managed persistence.
I am not clear on whether the above advice casts any implications on the way we want to have Seam-managed transactions. This is because our architecture is different. We have the following persistence context in a Stateless EJB:
#Stateless
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class CrudServiceBean implements CrudService {
#PersistenceContext(type = PersistenceContextType.TRANSACTION)
private EntityManager em;
...
}
Our DAOs invoke the above CrudServiceBean are Stateless EJBs (some of them are also Seam components) with #TransactionAttribute(TransactionAttributeType.REQUIRED). So, our transactions are handled by the container (WebLogic) and not Seam.
However, we now need to satisfy the following scenario: We need to have a front-end Seam component (non-EJB) invoke multiple DAO (EJB) methods and wrap all of them in a single transaction. If I understand correctly, we need to have Seam-managed transactions.
Can we have Seam-managed transactions as in the scenario I described, without having a Seam-managed persistence context? Or are the two irrelevant?

As said
We need to have a front-end Seam component (non-EJB) invoke multiple DAO (EJB) methods and wrap all of them in a single transaction
But
Our transactions are handled by the container - Also called Container Managed Transaction (The container Takes care of calling begin and commit method used by each underlying resource-manager Transaction)
The first issue is that you have a scenario where a non-EJB invokes multiple DAOs, each one an EJB. You could think of
#Name("nonEjbComponent")
public class NonEjbComponent {
private #In DaoEjbComponent daoEjbComponent;
private #In OtherDaoEjbComponent otherDaoEjbComponent;
private #In AnotherDaoEjbComponent anotherDaoEjbComponent;
private #In UserTransaction userTransation;
public void wrapperAllOfThem() {
userTransation.begin();
daoEjbComponent.save(someEntity);
otherDaoEjbComponent.update(otherEntity);
anotherDaoEjbComponent.delete(anotherEntity);
userTransation.commit();
}
}
But the Java EE specification 3.0 states
The enterprise bean with Either bean-managed or container-managed transaction demarcation must be a session bean or a message-driven bean.
So you can not use the scenario above. And because all of your DAOs are using container-managed transactions, the Java EE specification does not allow you to use container-managed and bean-managed Transaction at the same time
So the solution is
Wrap all of the DAOs in an EJB Stateless session bean whose transaction is container-managed. It will behave like a delegate component
#Stateless
#TransactionAttribute(TransactionAttributeType.REQUIRED)
#Name("wrapperStateless")
public class WrapperStatelessImpl implements WrapperStateless {
private #In DaoEjbComponent daoEjbComponent;
private #In OtherDaoEjbComponent otherDaoEjbComponent;
private #In AnotherDaoEjbComponent anotherDaoEjbComponent;
public void wrapperAllOfThem() {
daoEjbComponent.save(someEntity);
otherDaoEjbComponent.update(otherEntity);
anotherDaoEjbComponent.delete(anotherEntity);
}
}
And inside your non-EJB component, use
#Name("nonEjbComponent")
public class NonEjbComponent {
private #In WrapperStateless wrapperStateless;
public void wrapperAllOfThem() {
wrapperStateless.wrapperAllOfThem();
}
}

Related

Transaction management in EJB 3.0 and hibernate

I am trying to understand the transactions management and try to use its power in my already existing application developed in Struts 2, EJB 3 and hibernate 5.2.
Now I have ejb in my business layer like below
#Stateless
#TransactionManagement(TransactionManagementType.CONTAINER)
public class MyEJb implements ejbxyz {
#Override
public void method(){
Dao dao=new Dao() //Dao class is simple java class
dao.fooMethod(); //this method updates some record
dao.barMethod(); // this method updates some other record
}
}
public class Dao{
fooMethid(){
Session session=sessFactory.openSession();
session.beginTransaction();
session.update(x);
}
barMethod(){
try{
Session session=sessFactory.getCurrentSession();
session.getNamedQuery("xyz").executeUpdate();
}catch(HibernateException ex){
session.getTransaction.rollback();
}
}
}
I understand that Transaction management should be done at service layer(at ejb in my case). But how can I achieve this over there. ?
Now the dependency is if barMethod() fails to update the record then I need to rollback the changes made in fooMethod. So basically I need both the methods to be done in one transaction.
When I execute the application it throws the below exception
Exception while barMethod getNamedQuery is not valid without active transaction
Its because I am not beginning any transaction in barMethod. But then I really dont want to start a new transaction and want to continue with the older transaction started in fooMethod.
Container managed transactions are indeed suported out of the box for EJB beans. However, your Dao class is not a managed bean - it is a regular pojo that you instantiate manualy - therefore it does not participate in any transaction started by your other ejb.
So move your Dao to separate file, annotate it with #Stateless and then inject it into your service using #EJB private Dao dao;
There is more to transactions in Ejb container though. You can control the transaction support on method level via #TransactionAttribute annotation, that specifies how should the container invoke your method with regard to transaction. That way you can control, whether your method requires its own transaction, or if it shall participate in a transaction initiated by the caller(e.g. when invoked from ejb bean). For more info have a look at official Java EE tutorial

Transaction Propagation in EJBs methods

I want to make sure to understand corrsctly transaction propagation,please help.
Let's suppose we have a stateless EJB_A wich exposes the services of the application tier.
it uses local stateless EJB_B , EJB_C ,
both of them use a container managed EntityManager.
EJB_B and EJB_C use eachother methods.
If I understand things correctly each EJB gets it own intsance of an EntityManager to the manage same persistence unit.
Let's suppose EJB_A, on a client request, uses methods of bot EJB_B and EJB_C to create a transaction for example:
#Stateless(name = "myejb")
public class EJB_A implements Interface_EJB_A
{
#EJB
private EJB_B ejb_b;
#EJB
private EJB_C ejb_c;
public String method()
{
ejb_b.call();
ejb_c.call();
}
...
}
How does entity manager injected in EJB_C knows there's is a transaction ongoing
if it knows nothing about the exsistence of the EntityManager injected in EJB_B ?
It's this king of container added magic I'm having hard time to grasp...
The container internally uses a ThreadLocal variable to store the transaction. And the persistence context used by the entity managers is synchronized to this transaction. So the work done by EJBs A, B and C are both linked to the same persistence context, and done in the same transaction.
The specifications say:
By default, a container-managed persistence context is of SynchronizationType.SYNCHRONIZED and is automatically joined to the current transaction.
[...]
The application can obtain a container-managed entity manager with transaction-scoped persistence context by injection or direct lookup in the JNDI namespace. The persistence context type for the entity manager is defaulted or defined as PersistenceContextType.TRANSACTION.
A new persistence context begins when the container-managed entity manager is invoked[82] 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.
[...]
As described in section 7.1, a single persistence context may correspond to one or more JTA entity manager instances (all associated with the same entity manager factory[84]).
The persistence context is propagated across the entity manager instances as the JTA transaction is propagated.

CDI bean producer inside EJB stateless session bean

Let's suppose I have a simple lib named db-utils, which has a CrudService CDI bean (requestScoped) that's used by my web applications to perform CRUD operations.
I also have an EJB project named grad-db, which has the entities mapped from database. Grad-db also has the producer used to set the entityManager in db-utils' CrudService.
I already tried it and apparently it works fine. My question is: is that a bad practice? Is there any consequence of producing a CDI bean inside a stateless session bean and passing the EJB stateless bean as a parameter to the CrudService?
My code:
EJB Bean (grad-db):
#Stateless
public class CrudServiceCae extends AbstractCrud implements Serializable {
private static final long serialVersionUID = 1L;
#PersistenceContext(unitName = "cae-pu")
EntityManager em;
#Override
public EntityManager getEntityManager() {
return em;
}
#Produces
#Database(Schema.CAE)
public CrudService createCrudServiceCou() {
return new CrudService(this);
}
}
CrudService (db-utils):
#Named("crudService")
public class CrudService implements Serializable {
private static final long serialVersionUID = -2607003150201349553L;
private AbstractCrud crud;
public CrudService(AbstractCrud abstractCrud) {
this.crud = abstractCrud;
}
...
}
Edit:
Actually it worked only for queries. When I tried to insert data I got javax.persistence.TransactionRequiredException. Apparently I'm going to have to use inheritance instead of CDI in this case.
The EJBs are responsable for business processes/logic (i.e: methods), and are able to orchestrating others CDI controllers, is not so common let the EJB create objects, for that you would prefer a CDI POJO Producer.
In your case is leaner to use a CDI object and produce the object that you need from there, looks like a DAO and could be used (i mean, injected) into the EJB.
Think of EJBs on terms of a Boundary Pattern, using specialized controllers.
Notes:
#Stateless is not required to implements Serializable, these are pooled, and its lifecycle does not allow serialization.
In general you dont want to use a getter to the entity manager of an EJB, you should prefer write a method and use the em internally.
The persistence context is easier to manipulate if uses JTA
Your #Stateless should begins the transactions and let them propagated along the controllers
The em with package visibility is a good idea, lets you mock your facade / boundary easily

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.

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