I have an enterprise application containing a large number of BMP entity beans that are created, findByPrimaryKey:ed, and removed by a number of separate clients. I have a problem that occurs rarely, but sometimes:
Let us say that we have two EJB transactions A and B. They both try to access the same entity C. A, which enters first and locks the bean C to the transaction, want to call remove() on the bean. B calls a little bit later on findByPrimaryKey() for C or some random business method on C.
When C.remove() has executed by A, C is immediately removed from the EJB container's bean cache. But the DB transaction which executed the remove may still not be committed when transaction B enters the stage. Since A's transaction is not yet committed, B will not see the modifications it has done in DB, and since C is now removed from bean cache, B will cause ejbActivate() and ejbLoad() to be called on a new C instance, which then is added to the beancache (if commit options permits and transaction B is not rollbacked). Meanwhile, transaction A is committed, and C is permanently removed from persistent storage. But the ghost instance of C added in bean cache as a sideeffect of B will live on until next ejbLoad() when a NoSuchEntityException hopefully is thrown and C is really permanently removed from bean cache. But if using commit option A, that may take a while, especially when cache timeouts are set to get high performance.
But is this really a problem? Yes it is for us. A removed bean may act as if it still exists for some time after removal. And also, if any business methods are invoked on the ghost instance, inconsistent data may be stored in the DB.
But does this really happen, the window for this problem must be so small? Not often, I admit. But sometimes it does, and that is trouble for us. Espescially, JMS events may cause multiple clients to take action on the same bean simultaneously.
So, what is the solution for this? I can't be the only one who has seen this behavior? Is there a standard pattern to avoid this without loosing performance? Or is this just a bug in JBoss that needs to be fixed? Or am I just using the wrong transaction isolation level on my data source?