users@jpa-spec.java.net

[jpa-spec users] [jsr338-experts] Fwd: Re: 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: Sun, 07 Sep 2014 21:43:32 -0400

Please read response from Evan Ireland below.

-------- Original Message --------
Subject: [jsr338-experts] Re: Follow up discussion about transaction
time out, background transaction roll back and ordering issue with
detaching entities from persistence context...
Date: Sun, 7 Sep 2014 20:43:37 +0000
From: Ireland, Evan <evan.ireland_at_sap.com>
Reply-To: jsr338-experts_at_jpa-spec.java.net
To: jsr338-experts_at_jpa-spec.java.net <jsr338-experts_at_jpa-spec.java.net>

Scott,

Perhaps an approach that could be taken is for the transaction (which is
to be "rolled back" by a background thread, not the "owning" thread) to
be marked with status STATUS_MARKED_ROLLBACK or STATUS_ROLLING_BACK
(from the JTA status point of view), whereas the actual backend
transaction (at least in the case of STATUS_ROLLING_BACK) could be
already rolled back.

By playing with status codes and having a sort of limbo state, perhaps
we can avoid contract violation.

-----Original Message-----
From: Scott Marlow [mailto:smarlow_at_redhat.com]
Sent: Saturday, 6 September 2014 3:48 a.m.
To: jsr338-experts_at_jpa-spec.java.net
Subject: [jsr338-experts] Follow up discussion about transaction time
out, background transaction roll back and ordering issue with detaching
entities from persistence context...

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.