What is best practice for using Database Transactions with Seam when not using EJBs - ie. when deploying Seam as a WAR?
By default Seam JavaBeans support Transactions. I can annotate a method with @Transactional and that will ensure that a transaction is required. Or I can use @Transactional(NEVER) or @Transactional(MANDATORY). What I can't find out how to do is to create my own Transaction, set a timeout, begin and then commit/rollback.
I have tried using:
UserTransaction utx = Transaction.instance();
utx.setTransactionTimeout(2000);
utx.begin();
But it is either ignored if a Transaction is already in progress or returns a javax.transaction.NotSupportedException if I annotate the method with @Transactional(NEVER)
Any help appreciated. Thanks.
As you know, Transaction Management is a cross-cutting concern. So it is not a good idea your code scattered about in modules where those concerns are not their primary concern.
If you are using a JTA UserTransaction in a non-EJB environment, so JTA is avaliable (Apache Tomcat does not support JTA).
1° rule
Seam transaction management is enabled by default for all JSF requests (Seam 2.0+).
I think Seam transaction management sounds better as Transactions managed by Seam. It means Seam takes cares, behind the scenes, of calling begin and commit. Seam plays the role of Transaction manager by using a Seam Transaction Manager
1° scenario: POJO + JTA avaliable (Apache Tomcat does not support JTA)
Transaction Manager used by Seam: org.jboss.seam.transaction.UTtransaction
Enabled by default in non-EJB environment (war) when JTA available (JBoss support JTA)
If you are using JPA EntityManager or Hibernate Session, you need to register them to allows Seam manage transaction boundaries
See 9.3. Seam-managed persistence contexts how to set up a Seam managed persistence context (Injected by using @In)
Then inject a EntityManager (EntityManager) or Session (Hibernate) by using @In (scoped to ScopeType.CONVERSATION)
@Name("businessService")
public class BusinessServiceImpl implementes BusinessService {
@In
private EntityManager entityManager;
public void doSomething() {
// You do not need to call entityManager().getTransaction().begin();
// because Seam Transaction Manager takes care of it
// By using proxies
// Therefore, if you call entityManager().getTransaction().begin()
// You will get IllegalStateException
// Some EntityManager operations persist, find etc
// You do not need to call entityManager().getTransaction().commit();
// because Seam Transaction Manager takes care of it
// By using proxies
}
}
Behind the scenes, Seam Transaction Manager enlist the EntityManager (JPA) or Session (Hibernate) in the active JTA UserTransaction, by calling joinTransaction method
2° scenario: POJO + RESOURCE_LOCAL (Either Hibernate or JPA) Transaction
Transaction Manager used by Seam (JPA): org.jboss.seam.transaction.EntityTransaction
Transaction Manager used by Seam (Hibernate): org.jboss.seam.transaction.HibernateTransaction
See 9.3. Seam-managed persistence contexts how to set up a Seam managed persistence context (Injected by using @In)
Behind the scenes, Seam Transaction Manager takes care of calling begin and commit in the underlying technology by using proxies
3° scenario: EJB
Transaction Manager used by Seam : org.jboss.seam.transaction.CMTTransaction
Enabled by default in EJB environment. Take care, in that case, Seam does not control container-managed transaction.
regards,