users@jpa-spec.java.net

[jpa-spec users] [jsr338-experts] Re: 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: Mon, 08 Sep 2014 10:57:55 -0400

On 09/07/2014 09:43 PM, Scott Marlow wrote:
> 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.

I'm not following how the (background thread) transaction manager would
know to mark the transaction as STATUS_ROLLING_BACK (implies that
something knows to later mark the transaction as STATUS_ROLLEDBACK).
I'm also not sure of when the transaction is rolled back and
Synchronization.afterCompletion(int) called for this idea.

For the suggestion of STATUS_MARKED_ROLLBACK, I think that could help in
certain cases but not all (e.g. having the transaction rolled back
immediately to break deadlocks).

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

I'm not sure that changing the transaction status to any of the current
status codes available helps. In theory, the application (owning)
thread may check the transaction status and see STATUS_ACTIVE
(application still could add another entity to persistence context).
Also, the persistence providers really do not have control over the
determination of what the transaction status code is set to.

As mentioned below, one side effect of rolling the transaction back in a
background thread (which involves running the interposed/non-interposed
Synchronization.afterCompletion calls), is that an entity class could be
added after the persistence context detaches other entities from the
persistence context.

Before we get far into possible solutions, do we agree that this is a
situation that should be prevented? I think it should be prevented but
I really would like to hear what others think and why we should guard
against this potential issue.

For me, I would like to improve the robustness of EE application servers
environments to avoid invalid application state when JTA transactions
time out (for both BMT + CMT applications). I'm mentioning CMT even
though I couldn't actually reproduce a problem with my CMT test case).

>
> -----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.
>
>