Will Session Bean transactions work if i use JDBC or FireStorm insterad of entity beans. How will RollBacks work with CMT?
Background: ----------- I am considering using EJB session beans to provide the business layer, but do not want to use Entity Beans (in order to minimise the learning curve on a new project where the team hasnt used J2EE before). So I am considering using straight JDBC (or perhaps a product like Firestorm) to provide my data access layer. My concern is that I will end up with nested transactions which won't all rollback with CMT.
Will all be fine if I just open a new Connection at the start of a Stateless Sesion bean method and close the Connection at the end of the method?
There is no need to do that. Any connection you obtain from a DataSource will be automatically enlisted in the CMT transaction. If the CMT transaction succeeds, they all commit. If it rolls back, they all roll back.
You can keep the scope of each connection limited to the particular method you're using that connection in.
Ummm....according to the EJB spec (and the implementation of every container I'm aware of) that's not what happens. The outer transaction is suspended while the inner transaction completes. It's not a nested transaction (because there's no way to roll back the inner one after it's completed when it commits). Once the inner transaction completes, the outer transaction resumes, and may either roll back or commit, depending upon the circumstances.
As far as I understand there is no way one can programmatically do nested transactions in the CMT bean.
The only way to end up with nested transactions is when using BMT beans (i.e. session beans as entity beans must not use BMT). Eg,
// Get ref to two user transactions UserTransaction ut1 = _context.getUserTransaction(); UserTransaction ut2 = _context.getUserTransaction(); // Begin first transaction ut1.begin(); // Begin second transaction - NESTED TRANSACTION!!! ut2.begin(); .....
The above piece of code demonstrates how nested transaction can occur. Nested transactions are prohibited in EJB and therefore, make sure that they are not occurring anywhere in your app.
Alex, this is not a nested transaction. It is merely two transaction operating in parallel. The outcome of transaction 2 will not have any effect on the outcome of transaction 1. JTA does not support nested transactions.
Let's say that a client CMT bean is running in a transaction, and let's say that we have another bean (BeanA) with these two methods.
m1() with transaction attribute of Required m2() with transaction attribute of RequiresNew
When m1() is called by the client, it runs in the client's transaction.
Should the client then call m2() in the same transaction, this is disallowed by the container. Why? Because BeanA is still in a transaction, and the container will not allow a new transaction to start within an already open transaction.
But if BeanA had not been in a transaction and m2() was called, then the container will suspend the client's transaction in order to run m2().
Chris, thanks a lot for pointing out that my "nested transactions" example is completely incorrect. I thought I could quote code from the "Head first EJB" book of the top of my head
That is what "Head first EJB" says about nested transactions (as found on page 481):
UserTransaction ut = context.getUserTransaction(); ut.begin(); doStuff(); ut.begin(); // NO, NO, NO! Can't start a transaction before completing the previous one! If you could do that it would mean you could have "nested transactions".
Kyle, it would be great if there is a Javaranch journal article on "nested transactions". Thanks a lot in advance.