users@jpa-spec.java.net

[jpa-spec users] [jsr338-experts] Re: transaction-scoped persistence context being closed at JTA transaction completion time from non-application thread ...

From: Scott Marlow <smarlow_at_redhat.com>
Date: Mon, 11 Mar 2013 12:32:02 -0400

On 03/08/2013 08:31 PM, Linda DeMichiel wrote:
>
>
> On 3/7/2013 4:48 PM, Scott Marlow wrote:
>> On 03/07/2013 05:41 PM, Linda DeMichiel wrote:
>>>
>>>
>>> On 3/6/2013 2:16 PM, Scott Marlow wrote:
>>>> [1] requires that at Transaction completion, the container closes (or
>>>> returns to cache), the transaction-scoped
>>>> persistence context. What is supposed to happen when the JTA
>>>> transaction completes in a different thread than the
>>>> application thread? For example, if a background thread calls the
>>>> Synchronization.afterCompletion() because the tx
>>>> timeout period has been exceeded (as some Transaction Managers may
>>>> do), its not exactly thread-safe to call
>>>> EntityManager.close() (see [2]). Specifically, the application could
>>>> be in the middle of a persist or some other
>>>> EntityManager method, when EntityManager.close() is called.
>>>>
>>>
>>> The team here tells me that this should not be happening, and that the
>>> transaction managers they are
>>> familiar with will just mark the transaction for rollback rather than
>>> rolling it back at the point
>>> of timeout.
>>
>> Currently, we roll the transaction back from the background timer
>> thread. The JTA spec [4] does allow different threads
>> to start/end the transaction.
>>
>
> Yes, I realize this is permitted.
>
>>>
>>> Nevertheless, if the container were working with a TM where a timeout
>>> did result in immediate
>>> rollback and invocation of afterCompletion, the container should note
>>> this, and at the point at
>>> which the transaction would normally be completed then do the actual
>>> close as it normally would.
>>
>> Should we include a form of the above text in the JPA 2.1 spec
>> (section 7.9.1 [1])?
>>
>
> Unfortunately, I don't think this may always work, because the
> container may be relying on synchronization notifications at the
> normally expected tx end to know when it should be calling close
> (i.e., it may not know when the tx was started). If EJB CMT were
> used, the container would know when a tx was started and could use a
> business method boundary as the interpositioning point. If a
> container wrapped UserTransaction, I suppose it could use that point
> as well, but it is not obvious to me how this would be handled
> otherwise.

Yes, it would be easier if containers could queue (or hand-off) the
action (closing EntityManager or returning it to a EM pool) to happen at
the tx boundary as you suggest (if known).

One concern that I have is if we were to hand-off the closing of the
EntityManager to the top level component, that would probably be too
late (e.g. we could exhaust memory/resources before that is reached).
I'm not saying that we would, just pointing out that the action needs to
be taken as close as possible to the transaction ending.

How deeply do we want to go up the EE stack to deal with this? Is there
a non-JPA mechanism that we need to help with the container and provider
side?

At a minimum, I think that we should add a requirement for all providers
to deal with this situation. And, text about how containers should also
deal with this if needed.

>
> How does your implementation handle this?

On the container side we close the EntityManager in the background
thread and the application thread cleans up when the container level
deals with the transaction getting cancelled. Depending on where this
discussion goes, we will follow the recommendations made here.

>
> I'd also like to hear from the other implementations here as to
> what they do and how their transaction manager implementations
> handle timeout.
>
>
>> How would we word what the provider side has to do when detaching
>> entities after rollback [3]? I'm not sure that the
>> persistence provider will have the same chance to make a note for the
>> container side to take action on (if there is an
>> EE container involved). There is also the expectation that any JPA
>> provider will work, with any EE container to consider.
>>
>>>
>>> What do your transaction manager and container do?
>>>
>>>> Related to the above, if a JTA transaction rollback occurs in a
>>>> background thread [3], how are the managed entities
>>>> expected to be detached without violating the EntityManager
>>>> thread-safety [2]?
>>>>
>>>> There may be vendor specific solutions but shouldn't we (JPA spec eg)
>>>> account for the interaction of thread-unsafe
>>>> persistence contexts and the JTA Synchronization.afterCompletion that
>>>> may be invoked in non-application (background)
>>>> threads?
>>>>
>>>> Scott
>>>>
>>>> [1] 7.9.1 Container Responsibilities - After the JTA transaction has
>>>> completed (either by transaction commit or
>>>> rollback), the container closes the entity manager calling
>>>> EntityManager.close.
>>>>
>>>> [2] 7.2 Obtaining an EntityManager - 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.
>>>>
>>>> [3] 7.9.2 Provider Responsibilities - When the JTA transaction rolls
>>>> back, the provider must detach all managed entities
>>>> if the persistence context is of type SynchronizationType.SYNCHRONIZED
>>>> or has otherwise been joined to the transaction.
>>
>> [4] JTA 1.1 spec 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.
>> "
>>
>> Scott