Well, with some help from my friends on here and after a lot of headaches, I have figured out how to make container-managed transactions (CMT) work on OC4J. Well, almost. When I intentionally throw bad data at my application, EJBException is thrown and all database changes are rolled back. That's the good news. That bad news is that when I try to throw good data at my application afterwards, I receive a DuplicateKeyException indicating that an entity with that primary key already exists.
Here is a simplified example of what I mean. A bad transaction is begun in a session bean method and propagates to an entity bean method that is supposed to insert a row in the database with primary key 4. The insert occurs, but later on in the transaction, EJBException is thrown. Thus the insert of record 4 is rolled back, and there is no longer a record 4 in the database. In the future, another transaction propagates to that entity bean to insert a record 4. This should be OK since there is such record in the database. However, the create method in the home interface throws the DuplicateKeyException as if there is some leftover EntityContext associated with an EJBObject from the first bad transaction.
I thought that the container, along with rolling back any database changes, destroys all bean instances associated with rolled back transactions. How can I ensure this happens? Thanks so much for your help.
First thing first did you set setRollbackOnly().
The other thing will be to have some logging in your ejbremove method. This will ensure that the remove method is being called.
If not may be it is a bug with the EJB implementation on your server.
I hope this is helpful.
Thanks for the advice, Sunil. I don't think it has anything to do with setRollbackOnly() since I am getting the message indicating that a rollback occurred and the database remains unchanged after the rolled back transaction. As for there being a bug in OC4J, while I would love to believe that a brilliant programmer like me never makes mistakes (ha!), I think that is unlikely. However, I will look into my ejbRemove() implementation and see if the answer is there. Still though, I would think that the method is being called correctly if the database records are deleted, but perhaps the EJB implementation on OC4J does things differently.
In any case, thanks again.
Let us know we will all be intrested. Looks like the EJB is still associated with some entity context....but with what...since you do not see any records. Was the data base server bounced.
As far as database servers are concerned you may see that there is no records inserted (because of isolation level) but the transaction may still be in Limbo and may not be rolled back. This happened to me once in Oracle and we noticed it because everytime we tried to start a new transaction it would say nested transaction not supported.
This may be totally different....but then suggestions is all that we can give.
As it turns out, I had forgotten to even implement ejbRemove in one of my entity beans (If you knew the application, you might understand why deletes in this particular table aren't a priority.). Yet even with this omission, the particular table to which the bean was related to was being rolled back as well after failed transactions. What this must mean is that OC4J doesn't use ejbRemove() to roll back database updates. Just for fun, I implemented ejbRemove() in that bean and added some logging to it, and it was as if nothing changed. This would appear to prove my hypothesis.
Of course, I am still at a loss. I still have leftover entity beans--associated with nonexistent database records--that cause a DuplicateKeyException to be raised when I try to insert records in subsequent transactions with the same key. I don't know how OC4J removes the database records themselves, and I certainly don't know how to "command" it to destroy any bean instances associated with nonexistent entities after a failed transaction.
Any further suggestions will be helpful. Thanks.