jsr338-experts@jpa-spec.java.net

[jsr338-experts] Follow up discussion about transaction time out, background transaction roll back and ordering issue with detaching entities from persistence context...

From: Scott Marlow <smarlow_at_redhat.com>
Date: Fri, 05 Sep 2014 11:48:03 -0400

Hi,

I created a few test cases that try to simulate what could happen, when
JTA transaction time-out leads to a background thread rolling the
transaction back. I was able to recreate the situation, where the
application thread is able to (I believe) violate "7.9.2 Provider
Responsibilities" for when background thread rolls back by simulating an
edge case where the application thread adds an entity after the
roll-back occurs.

Here is my example servlet service method that starts a user
transaction, times out and simulates how application thread could add
entities after roll back (based on [1]):

@Resource
private UserTransaction userTransaction;

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

doGet(...) {
   userTransaction.setTransactionTimeout(5); // 5 second timeout
   userTransaction.begin();
   EntityManager entityManager = entityManagerFactory.createEntityManager();
   entityManager.joinTransaction(); // already joined but...

   boolean notRolledBackException = false;
   while (!notRolledBackException) {
     Thread.sleep(10 * 1000);
     int transactionStatus = userTransaction.getStatus();
     if ( transactionStatus == Status.STATUS_ROLLEDBACK) {
         // simulate race condition by adding entity after rollback
         Employee emp = new Employee();
         emp.setId(id);
         emp.setAddress(address);
         emp.setName(name);
         entityManager.persist(emp);
     }
     // application has invalid state as the persistence context
     // has an Employee entity that was not detached.
}

The above illustrates my concern of a deeper issue that we should
address in EE 8. I don't think we have control of when the entities are
cleared from the persistence context after a background thread rolls the
transaction back, as the application/background threads are not
controlled by any ordering requirements. In other words, I think that
the background thread may clear the persistence context of entities
before the application thread is about to add another entity to the
persistence context.

 From a standards point of view, I also found that there is no way to
know whether the thread that is rolling back the transaction, is a
communications thread (on behalf of remote JVM participating in same TX)
or a local "timer" thread. Or if the thread rolling back the
transaction is the application thread. I have some ideas of how this
could be addressed but would like to first confirm with others on this
list that we should address this situation for JPA.next/EE 8.

I also tried to recreate the above situation with stateful session beans
+ a CMT but was unable to due to various transaction status checks
already in our EJB container. In theory, we might also see see the same
problem with EJB CMT but I was unable to recreate it.

Thanks,
Scott

[1]
https://github.com/scottmarlow/wildfly/tree/transactiontimeout_clientut_noejb
creates a UT from a servlet with a 5 second TX time out and the
application thread adds entities to the persistence context after the
transaction has been rolled back.