[jboss-as7-dev] JTA Synchronization.afterCompletion callback can occur in a background thread but JPA EntityManager must be accessed in single-threaded manner...

Scott Marlow smarlow at redhat.com
Thu Mar 7 12:00:23 EST 2013


CMP, EJB3, IronJacamar, Hibernate, Weld, Infinispan and the JPA 
subsystem use syncs.

The JTA 1.1 specification refers to the x/open "Distributed Transaction 
Processing: The TX (Transaction Demarcation) Specification" which includes:

"
2.2.5 Thread of Control
...
The RM receives the calls from the AP and TM in the same thread of control.
"

The JTA 1.1 specification also has its own:

"
3.4.3 Thread of Control
The X/Open XA interface specifies that the transaction association 
related xa calls must be invoked from the same thread context. This 
thread-of-control requirement is not applicable to the object-oriented 
component-based application run-time environment, in which application 
threads are dispatched dynamically at method invocation time. Different 
Java threads may be using the same connection resource to access the 
resource manager if the connection spans multiple method invocation. 
Depending on the implementation of the application server, different 
Java threads may be involved with the same XAResource object. The 
resource context and the transaction context may be operated independent 
of thread context. This means, for example, that it’s possible for 
different threads to be invoking the XAResource.start and XAResource.end 
methods.

If the application server allows multiple threads to use a single 
XAResource object and the associated connection to the resource manager, 
it is the responsibility of the application server to ensure that there 
is only one transaction context associated with the resource at any 
point of time.

Thus the XAResource interface specified in this document requires that 
the resource managers be able to support the two-phase commit protocol 
from any thread context.
"

I think that the x/open document is pretty clear about "thread of 
control", in that only the application thread should end the tx.  The 
JTA specification "thread of control" allows any thread to end the 
transaction.

Handling the JPA container level requirement (to close the EntityManager 
when the JTA transaction completes) is different than the Hibernate 
persistence provider requirement (to detach managed entities).  The 
synchronization.afterCompletion() is the last time that I get invoked 
for the EntityManager that we are supposed to close at that point. 
Maybe we could have a new "JPA transaction association interceptor" 
simply call EntityManager.close() as was suggested earlier.  I'm hoping 
to hear back on my question to the JPA EG [1] about whether we could 
standardize how vendors handle backgrounds threads rolling back the 
transaction.

Scott

[1] 
http://java.net/projects/jpa-spec/lists/jsr338-experts/archive/2013-03/message/0

On 02/22/2013 03:20 PM, Jason Greene wrote:
> The only other systems I know of that use syncs (off the top of my head - yes being lazy here) are clustering and EJB timers. Both of those control resources that are accessed from multiple threads.
>
> On Feb 22, 2013, at 2:11 PM, Steve Ebersole <steve at hibernate.org> wrote:
>
>> Thats sort of what we are planning on doing.  The rub is every library that interacts with JTA having to do this as well.  Thats more what I think Scott was getting at.
>>
>> For clarity your suggestion (method entry checks) is part of our solution.  We will also do method exit checks.  Ugh.  Lot of work to handle something the TM is doing
>>
>> On Feb 22, 2013 1:53 PM, "Jason Greene" <jason.greene at redhat.com> wrote:
>> I had a discussion with Steve about this. Not sure if you guys talked about my suggestion.
>>
>> My suggestion was to simply detect if afterCompletion is running on the thread that created it. If the threads match proceed normally. If, however, they do not match then DO NOTHING (well at first):)
>>
>> Then have the EntityManager, immediately before certain actions such as a flush, detect if the Transaction has been rolled back (using Transaction.getStatus()). If it has been rolled back then at that point of time trigger an exception to the calling application code, with a message that the "Transaction manager has decided to revert the transaction, either due to a timeout or a resource failure. Check your log for details".
>>
>> On Feb 22, 2013, at 8:45 AM, Scott Marlow <smarlow at redhat.com> wrote:
>>
>>> Related jira issues are HHH-7910 + AS7-6586.  HHH-7910 has been around a
>>> bit longer and contains comments about the current plan to address the
>>> issue in Hibernate.
>>>
>>> As mentioned in HHH-7910, the JTA specification allows
>>> Sychronization.afterCompletion callbacks to occur in a different thread
>>> than the application thread that is using the transaction (typically for
>>> transaction timeout or when a transaction is propagated to a remote thread).
>>>
>>> Since the JPA EntityManager is by design, not thread safe, invoking the
>>> EntityManager.clear() or EntityManager.close() methods from a background
>>> thread while the application thread may be in the middle of an
>>> EntityManager invocation is not the best situation (IMO).
>>>
>>> One improvement that we talked to the JBossTM/TS team about, is adding a
>>> TM policy that arranges for the Synchronization.afterCompletion to
>>> always run in the application thread (some of the IRC discussion is
>>> attached to HHH-7910).  The TM team doesn't think that they could do
>>> that for both the TX timeout and tx propagating to a remote thread
>>> (JBossTS) uses.
>>>
>>> One alternative solution, might be to create a top level container level
>>> queue that the background thread Synchronization.afterCompletion defers
>>> processing to.  As soon as the application thread returns control to the
>>> top level, the queue is processed in FIFO order.
>>>
>>> *Does AS have any other uses of Synchronization.afterCompletion or
>>> Synchronization.beforeCompletion that expect to run in the application
>>> thread*?
>>>
>>>  From the JPA specification about thread unsafety:
>>>
>>> "
>>> An entity manager must not be shared among multiple concurrently
>>> executing threads, as the entity manager and persistence context are not
>>> required to be threadsafe. Entity managers must only be accessed in a
>>> single-threaded manner.
>>> "
>>> _______________________________________________
>>> jboss-as7-dev mailing list
>>> jboss-as7-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/jboss-as7-dev
>>
>> --
>> Jason T. Greene
>> JBoss AS Lead / EAP Platform Architect
>> JBoss, a division of Red Hat
>>
>>
>> _______________________________________________
>> jboss-as7-dev mailing list
>> jboss-as7-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/jboss-as7-dev
>
> --
> Jason T. Greene
> JBoss AS Lead / EAP Platform Architect
> JBoss, a division of Red Hat
>



More information about the jboss-as7-dev mailing list