Here is a question given in enthuware . (I hope posting is not a violation of license)
Bean A with transaction attributes of "RequiresNew" for all its methods.
Bean B with transaction attributes of "Supports" for all its methods.
A client having a transaction context calls a method mA() on bean A, which in turns calls a method mB() on Bean B.
Assuming all invocations are local, which of the following statements is correct if mB() encounters a system exception?
Select 3 options
1. The client's transaction will be marked for roll back. 2. The client will get a javax.ejb.EJBException but it can continue with the same transaction. 3. The client will get a javax.ejb.EJBTransactionRolledbackException 4. The bean B instance will be discarded. 5. The bean A instance will NOT be discarded. 6. Changes made to the database by mA(), will be commited.
Correct answers are and enthu's explanations
2 : Since mA() encounters a system exception (thrown by mB()), it will translate to EJBException for the client. However, the client's transaction will not be rolled back because of the above mentioned reason. 4 : Because it encounters a system exception. 5 : Since mB() executes within mA()'s transaction context, the container will mark it for rollback and throw javax.ejb.EJBTransactionRolledbackException to mA() when mB() encounters a system exception.
I totally agree with the answers and explanations,
But here is how I tested above scenario and below what I got,
SlsbOne : Represent above Class B
SlsbTwo : Represent Class A
SlsbThree : Represent Client
If im not mistaken, all "before call", "after call", "after commit" could be seen in logs,
But I can only see only "before call" from SlsbThree and after that javax.ejb.EJBException: Stateless SessionBean method returned without completing transaction
I see you're making us guys fit in transactions/exceptions. That's good.
I think the following happens to your beans:
1. SlsbOne throws a system exception.
2. Container logs the exception, marks the tx for rollback, discards SlsbOne and throws an EJBTransactionRolledbackException to the client, that is to SlsbTwo (compare core spec 14.3.1, table 14, second row).
3. SlsbTwo (re-)throws the EJBTransactionRolledbackException (= system exception).
4. Container logs the exception, rolls back the tx, discards SlsbTwo and throws an EJBException to the client, that is SlsbThree (compare core spec 14.3.1, table 14, fourth row).
5. In the catch-block of SlsbThree the EJBException is catched and the buisness method three() returns.
6. Since returning the business method of a stateless Session Bean with BMT without completing the transaction isn't allowed (see core spec 13.3.3), the container throws an EJBException, complaining "Stateless SessionBean method returned without completing transaction".
I disagree with enthuware about
5. The bean A instance will NOT be discarded.
being correct. I think both, bean A instance and bean B instance will be discarded [due to core spec 14.3.1, table 14, fourth row resp. second row] - at least, if the system exception isn't catched in bean A. But if it is catched in bean A then the client won't get a javax.ejb.EJBException, so option "2" would be wrong.
I tried your sample with stateful beans with the following modifications in SlsbThree: The output in (*) is "javax.ejb.NoSuchEJBException" indicating that the SlsbTwo instance was discarded, too.
I have missed 5th Option. So correct answers of enthu's are 2,4 and 5 from below list
1. The client's transaction will be marked for roll back. 2. The client will get a javax.ejb.EJBException but it can continue with the same transaction. 3. The client will get a javax.ejb.EJBTransactionRolledbackException 4. The bean B instance will be discarded. 5. mA() will get a javax.ejb.EJBTransactionRolledbackException 6. The bean A instance will NOT be discarded. 7. Changes made to the database by mA(), will be commited.
But what Im arguing is Client gets javax.ejb.EJBException (System Exception),
1. So client will be discarded, Therefore client can't continue same transaction. 2. Also its transaction will be marked for rolled back (because it get a system exception).
Hence I think correct answers should be 1, 4 and 5
Either client catch exception, transaction already marked for rolledback
no, that's wrong. You have to differentiate:
There are two transactions: The one, in those context the client is runing (-> this tx isn't marked for rollback, if the client catches the exception) and the second, started by bean A (-> this tx is marked for rollback).
You can easily check this by using CMT in SlsbThree and printing sc.getRollbackOnly().
Since the client's transaction was suspended, it is not marked for rollback automatically if the other transaction fails. The client will get EJBException and it then has an option to either catch it or floor it. In the later case, the client transaction will be rolled back, not because the other transaction failed but because an excecption was thrown out of the client code.