jsr338-experts@jpa-spec.java.net

[jsr338-experts] Re: unsynchronized persistence contexts

From: Linda DeMichiel <linda.demichiel_at_oracle.com>
Date: Fri, 09 Sep 2011 11:31:34 -0700

On 9/9/2011 11:01 AM, Gordon Yorke wrote:
>> the resulting behavior is as if the PC is propagated.
> It is a "hole" that EPCs can not be accessed from within a SLSBs outside of a transaction and it is a limitation that
> should be resolved. The reality is a PC is never really propagated to the SLSB anyway but is assigned to the transaction
> and resolved by the container. With an EPC the container will still resolve the reference but the EPC will be propagated
> along the call stack. Perhaps we just need to use different language to make it less confusing. Perhaps describing the
> curent inheritance as propagation via call stack or thread would help to align the behaviours.
>

I definitely agree with you about the hole. My question was more as to the resulting complexity /
confusion vs added functionality tradeoff, since the matrix of combinations is already fairly complex.

I can be convinced either way on this point, but in any case, I would like to hear from more members
of the group on this issue !!

-Linda



> --Gordon
>
>
>
> On 9/9/2011 2:12 PM, Linda DeMichiel wrote:
>>
>>
>> On 9/8/2011 12:27 PM, Gordon Yorke wrote:
>>> Inline:
>>>
>>> On 9/8/2011 3:43 PM, Linda DeMichiel wrote:
>>>> At this point, I think the safest course of action here is the conservative
>>>> one, and not to proceed with changes to the inheritance rules, at least
>>>> until we get further feedback in this regard.
>>> Except the change that allows an EPC to be inherited by a Stateless Session Bean?
>>
>> Yes, this is the case I'm struggling with. At this point, I'm
>> questioning whether we should do that (at least now), or whether it
>> would just be confusing, given that the "inheritance" would be for the
>> duration only a a method call. The main advantage I see for it over the
>> current spec + the proposal for propagation is that in the absence of
>> a tx, the resulting behavior is as if the PC is propagated.
>>
>>
>> And we need additional restrictions to
>>> prevent inheritance of PC with different transaction participation requirements.
>>
>> Yes.
>>
>>>>
>>>> If you feel strongly about this issue, please let me know.
>>>>
>>>> I have also been thinking about singletons, which were left as an open
>>>> issue in the proposal I circulated.
>>>>
>>>> Inheritance of PCs by singleton's is also problematic, independent of
>>>> whether they are synchronized or not.
>>>> The EJB spec states that singleton's are created by the container,
>>>> not directly by the application. This creation may be at startup
>>>> (and is required to be if the @Startup annotation has been applied),
>>>> or it may be deferred, as late as the first method invocation upon
>>>> the singleton. The time of the creation of a singleton is also
>>>> influenced by whether any other singleton has a @Depends relationship
>>>> upon it.
>>>>
>>>> We thus cannot assume that a singleton that is not marked @Startup
>>>> should inherit a PC (as the rules below proposed for method invocation
>>>> time inheritance for SLSBs), as that singleton may have been created
>>>> at startup time as well. So, my conclusion is that a singleton should
>>>> not inherit a PC.
>>> Agreed.
>>>>
>>>> That leaves the issue of whether EPCs should be bound to singletons,
>>>> and, if so, whether such EPCs should be inherited by beans which
>>>> the singleton instantiates.
>>>>
>>>> I think that binding EPCs to singletons is potentially useful; inheritance
>>>> not so much.
>>> Inheritance here is important for the same reasons it is include for Statefull Session Beans; users want the PC to be
>>> consistent across the call stack.
>>> We may want to add to section 7.2 to note special care should be taken when using EPCs in Stateless Session Beans and
>>> Singleton Session Beans.
>>>>
>>>> Should we extend the notion of *binding* an EPC to a singleton??
>>> We should treat it as a Statefull Session Bean with the exception that a EPC is assigned when it is created.
>>>>
>>>> -Linda
>>>>
>>>>
>>>> On 9/2/2011 7:05 AM, Gordon Yorke wrote:
>>>>>> Subject to the above requirements, a synchronized persistence context
>>>>>> or an unsynchronized persistence context may be propagated into a
>>>>>> component that specifies an unsynchronized persistence context. An
>>>>>> unsynchronized persistence context may only be propagated into a
>>>>>> component that specifies an unsynchronized persistence context. The
>>>>>> attempt to propagate an unsynchronized persistence context into a
>>>>>> component that specifies a synchronized persistence context causes the
>>>>>> EJBException to be thrown. [OPEN ISSUE: Is this the right exception?
>>>>>> Should we relax this if the PC has been joined to the transaction?]
>>>>> Hello All,
>>>>> I have been thinking about this issue for a while and believe it is unsafe to allow a *joined* EXTENDED UNSYNC'd PC
>>>>> to be *inherited* by a component using a SYNC'd PC. The UNSYNC'd PC would become bound to that component and that
>>>>> would
>>>>> be technically incorrect. We could allow the propagation of *joined* TRANSACTION UNSYNC'd PCs to SYNC'd PCs but that
>>>>> may be too confusing for users.
>>>>>
>>>>> On 8/26/2011 4:00 PM, Linda DeMichiel wrote:
>>>>>>
>>>>>> When we solicited feedback on features for this release, one of the
>>>>>> discussions on the jsr-317 feedback list concerned the ability to
>>>>>> specify a persistence context that was not "synchronized" with regard
>>>>>> to transactions -- i.e., which did not respond to transaction
>>>>>> synchronization notifications. This would offer a cleaner alternative
>>>>>> to the manual flushmode which was decisively rejected by the JPA 1.0
>>>>>> expert group.
>>>>>>
>>>>>> JPA already has the notion of a persistence context that is
>>>>>> unsynchronized. This occurs when an application-managed persistence
>>>>>> context is created outside the scope of a JTA transaction, and the
>>>>>> application must notify the entity manager that the persistence
>>>>>> context is to be joined to a subsequently-started transaction by means
>>>>>> of the joinTransaction() method.
>>>>>>
>>>>>> The proposal below is a strawman proposal for unsynchronized
>>>>>> container-managed persistence contexts that Mike, Gordon,
>>>>>> and I have collaborated on.
>>>>>>
>>>>>> This proposal attempts to define synchronization as orthogonal to the
>>>>>> existing persistence context types and propagation rules. It loosens
>>>>>> some of the restrictions imposed by those types however.
>>>>>> In particular:
>>>>>> -- Entity managers for unsynchronized transaction-scoped persistence
>>>>>> contexts can be used to invoke the persist, remove, refresh, and
>>>>>> merge operations regardless of the presence of an existing transaction.
>>>>>> -- The notion of extended persistence context is loosened to include
>>>>>> the use of extended persistence contexts being "bound" to stateless
>>>>>> session beans in order to capture the ability to propagate extended
>>>>>> persistence contexts from stateful session beans to stateless
>>>>>> session beans outside of a transaction.
>>>>>>
>>>>>> Please post your feedback to the group, including on the open issues.
>>>>>>
>>>>>> thanks,
>>>>>>
>>>>>> -Linda
>>>>>>
>>>>>> -----------------------------------
>>>>>>
>>>>>> Proposal:
>>>>>>
>>>>>> A container-managed persistence context can be designated at its point
>>>>>> of creation to be unsynchronized by means of the synchronization
>>>>>> element of the PersistenceContext annotation. Both transaction-scoped
>>>>>> and extended persistence contexts may be designated as unsynchronized.
>>>>>>
>>>>>> @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
>>>>>> public @interface PersistenceContext {
>>>>>> String name() default "";
>>>>>> String unitName() default "";
>>>>>> PersistenceContextType type default TRANSACTION;
>>>>>> SynchronizationType synchronization default SYNCHRONIZED;
>>>>>> PersistenceProperty[] properties() default {};
>>>>>> }
>>>>>>
>>>>>> public enum SynchronizationType {
>>>>>> SYNCHRONIZED,
>>>>>> UNSYNCHRONIZED
>>>>>> }
>>>>>>
>>>>>> A persistence context of type UNSYNCHRONIZED is not enlisted in any
>>>>>> JTA transaction unless explicitly joined to that transaction by the
>>>>>> application.
>>>>>>
>>>>>> An unsynchronized persistence context is enlisted in a JTA transaction
>>>>>> and registered for subsequent transaction notifications against that
>>>>>> transaction by invoking the EntityManager joinTransaction() method.
>>>>>> The persistence context remains joined to (synchronized with) the
>>>>>> transaction until the transaction commits or rolls back. After the
>>>>>> transaction commits or rolls back, the persistence context will not be
>>>>>> synchronized with any subsequent transaction unless the joinTransaction
>>>>>> method is invoked in the scope of that subsequent transaction.
>>>>>>
>>>>>> A persistence context of type SynchronizationType.UNSYNCHRONIZED must
>>>>>> not be flushed to the database unless it is joined to a transaction.
>>>>>> Both the persistence provider and the application are prohibited from
>>>>>> flushing to the database until the point that a transaction has been
>>>>>> joined. The application's use of queries with pessimistic locks, bulk
>>>>>> updates/delete queries, etc. result in the provider throwing the
>>>>>> TBDException. (If the application has specified FlushMode.AUTO, it
>>>>>> must be ignored by the provider when executing queries.) [Open Issue:
>>>>>> should this be IllegalStateException or a new JPA exception?] After
>>>>>> the persistence context has been enlisted in the JTA transaction,
>>>>>> these operations are again allowed.
>>>>>>
>>>>>> The application is permitted to invoke the persist, merge, remove, and
>>>>>> refresh entity lifecycle operations on an entity manager corresponding
>>>>>> to a unsynchronized transaction-scoped persistence context as well as
>>>>>> one corresponding to an unsynchronized extended persistence context
>>>>>> independent of whether a transaction is active.
>>>>>> Such changes in the persistence context can be flushed to the database
>>>>>> either explicitly by the application or by the provider after the
>>>>>> persistence context has been joined to a transaction. If flush() is
>>>>>> not explicitly invoked, flushing may be deferred until commit time
>>>>>> depending on the operations invoked (and the setting of
>>>>>> FlushModeType.)
>>>>>>
>>>>>> If an unsynchronized persistence context has not been joined to the
>>>>>> current JTA transaction, rollback of the JTA transaction will have no
>>>>>> effect upon the persistence context. It is recommended that the
>>>>>> persistence provider use a non-JTA datasource for an unsynchronized
>>>>>> persistence context that has not been joined to a JTA transaction to
>>>>>> alleviate the risk of integrating uncommitted changes into the
>>>>>> persistence context in the event that the transaction is later rolled
>>>>>> back.
>>>>>>
>>>>>> If an unsynchronized persistence context has been joined to the JTA
>>>>>> transaction, transaction rollback will cause the persistence context
>>>>>> to be cleared and all pre-existing managed and removed instances to
>>>>>> become detached. (See spec section 3.3.2.)
>>>>>>
>>>>>> When a JTA transaction exists, an unsynchronized persistence context
>>>>>> is propagated with that transaction according to the rules below (in
>>>>>> the section Requirements for Persistence Context Propagation)
>>>>>> regardless of whether the persistence context has been joined to that
>>>>>> transaction.
>>>>>>
>>>>>>
>>>>>> Container-managed Extended Persistence Contexts (See spec section
>>>>>> 7.6.2)
>>>>>>
>>>>>> The rules pertaining to extended persistence contexts are relaxed as
>>>>>> follows: Any EJB component may specify the use of an extended
>>>>>> persistence context. If the persistence context bound to a stateful
>>>>>> session bean is not inherited by any other component, it is the
>>>>>> responsibility of the container to close the persistence context when
>>>>>> the @Remove method of the stateful session bean completes (or the
>>>>>> stateful session bean instance is otherwise destroyed) or when the
>>>>>> method invocation completes (if the component is a stateless session
>>>>>> bean or message-driven bean). [OPEN ISSUE: still need to handle the
>>>>>> singleton session bean case.]
>>>>>>
>>>>>>
>>>>>> Inheritance of Extended Persistence Contexts (See spec section
>>>>>> 7.6.2.1.)
>>>>>>
>>>>>> If a component to which an extended persistence context is bound
>>>>>> instantiates a stateful session bean component (executing in the same
>>>>>> EJB container instance), which also specifies an extended persistence
>>>>>> context, the extended persistence context of the first component is
>>>>>> inherited by the second component and bound to it, and this rule
>>>>>> recursively applies--independent of whether transactions are active or
>>>>>> not at the point of the creation. If the second component is a
>>>>>> stateless session bean component that is invoked by a component to
>>>>>> which an extended persistence context is bound, the persistence
>>>>>> context is propagated into the that stateless session bean and bound
>>>>>> to it for the duration of the method invocation.
>>>>>>
>>>>>> If the persistence context has been initiated or inherited by any
>>>>>> stateful session bean, the container does not close the persistence
>>>>>> context until all such stateful session beans have been removed or
>>>>>> otherwise destroyed.
>>>>>>
>>>>>>
>>>>>> Requirements for Persistence Context Propagation
>>>>>> (See section 7.6.3.1)
>>>>>> All the requirements of section 7.6.3.1 still apply. (The word
>>>>>> "existing" in the second sub-bullet should be removed.)
>>>>>> In addition, the following is added to the last bullet point:
>>>>>>
>>>>>> Subject to the above requirements, a synchronized persistence context
>>>>>> or an unsynchronized persistence context may be propagated into a
>>>>>> component that specifies an unsynchronized persistence context. An
>>>>>> unsynchronized persistence context may only be propagated into a
>>>>>> component that specifies an unsynchronized persistence context. The
>>>>>> attempt to propagate an unsynchronized persistence context into a
>>>>>> component that specifies a synchronized persistence context causes the
>>>>>> EJBException to be thrown. [OPEN ISSUE: Is this the right exception?
>>>>>> Should we relax this if the PC has been joined to the transaction?]
>>>>>>
>>>>>>
>>>>>>