Very new to CMT here. Our application adds people information to a local database. Application has 3 statless EJB with BMP.
The first bean (person bean) validate the core perosn information then persists the core person data to the database. The 2nd Bean (address bean) validates the person's address information and persists the address data to the database and finally the third bean (telecom bean) validates the person's telecom information such as phone, cell phone, fax and so on and persists it to the database.
Note: We don't want nested transactions. Either all the transactions by all the 3 EJBs should persist or roll back the entire transactions.
If we were going to use CMT in junction with the BMP what would happen to the following scenario:
The first bean (person bean) validated and added the core person information to the database but the 2nd bean (address bean) throws an application specific exception during the address validation. Would the container roll back the data that was persisted by the person bean? How does container know an application exception has been thrown? (Note: We are not wrapping the exception in an EJBException).
The simplest way to make these operations transactional is write a 4th, Session EJB, that calls the operations in EJBs 1 to 3. EJB-to-EJB methods calls can easily be made transactional.
Roughly speaking, the transactional boundary for EJBs is the boundary between the client and the EJB-server. When the client invokes the first EJB, the transaction begins. EJB-to-EJB calls will be incorporated in the transaction. The transaction ends when all the EJB methods finish and control returns to the client.
The transaction can end in two ways:
1) All the operations succeed, and the transaction commits.
2) An exception is generated, and the transaction rolls back.
Some technical details you need to make things work.
1) You need to assign a transaction attribute such as "Required" to all the EJB methods.
2) For technical reasons too difficult to go into here, only Runtime exceptions automatically roll back the transaction. If you throw a non-Runtime (Checked) exception, you must explicitly mark the transaction for rollback, using the EJBContext.setRollbackOnly() method.
Thanks for your response. In our case we don't need the 4th EJB. In fact the first EJB calls the other 2 EJBs after it persist its own piece of data. I think what you are saying that in this case the CMt won't intercept to roll back the transaction if one of the beans throw an application exception during the data validation hence the application must make an explicit call to the EJBContext.setRollBack(). That's fine; I can live with that though I would much rather if the container would took care of the application exception :-)
The treatment of Application Exceptions is a bit controversial in the EJB standard. Personally, I agree with you. I would prefer it if the container automatically rolled back transactions for all exceptions.
There is a good justification for the way things work, though. By not automatically rolling back transactions for application exceptions, it allows the possibility of transaction recovery within EJB methods. Namely, a calling EJB method can catch the application exception, and rather than rolling back the transaction, perform some alternative operation and continue the transaction.
Anyway, that is the way the spec is written, and that is what we need to deal with :)
You 're right, the recovery certainly justifies the whole thing. I started reading up on CMT. They have actually have a term for transactions that are rolled back via a call to EJBContext.setRollBack(); it's called "Doomed transaction" :-)
Who's taking care of England?!?!