[cdi-dev] Transaction Scope for CDI
struberg at yahoo.de
Sun May 27 07:13:35 EDT 2012
Hi Reza, all!
Sorry for the delay (pretty busy times right now). Response inline.
----- Original Message -----
> From: Reza Rahman <reza_rahman at lycos.com>
> To: cdi-dev at lists.jboss.org
> Sent: Wednesday, May 23, 2012 8:18 PM
> Subject: Re: [cdi-dev] Transaction Scope for CDI
> Responses in-line...
>> -----Original Message-----
>> From: cdi-dev-bounces at lists.jboss.org
> [mailto:cdi-dev-bounces at lists.jboss.org]
>> On Behalf Of Mark Struberg
>> Sent: Wednesday, May 23, 2012 5:15 AM
>> To: cdi-dev at lists.jboss.org
>> Subject: Re: [cdi-dev] Transaction Scope for CDI
>> It's really hard to follow (and subsequently check the necessity)
>> didn't gave _reasons_ for all the behaviour.
> [Reza Rahman] That's fair and something I anticipated. The problem is that
> it would be a bit odd to discuss all the supporting use-cases in the spec
> itself since the others do not. We can certainly do that here (to a great
> degree Nigel, I and Pete already have) and maybe add to the spec if we deem
> it necessary.
>> > If a contextual object is placed into the transaction context while
>> >a transaction is active, the object will remain available until the
>> >transaction is committed or rolled-back.
>> What about nested transactions? That would then Clash with the
> [Reza Rahman] Can you kindly elaborate? As such, JTA does not allow nested
> transactions. What it does allow is one or more suspended transactions in
> the same call-stack. In case of CMT, this would be a non-issue since the
> contextual objects would not be propagated beyond method invocation
> boundaries. In case of BMT, you really can't suspend the transaction, so
> this would work there as well?
EJB supports REQUIRES_NEW. Now for the wording it's something different saying
"If a contextual object is placed into the transaction context while a transaction is active"
"A contextual instance is active AS LONG as the transaction is active"
But then again, you will just repeat the basic definition of a Context. It would be much easier to just define the lifecycle boundaries of the TransactionContext. See the wording of the CDI spec 6.7. "Context management for built-in scopes"
>> Imo the wording is way too abstract. I know this is really hard stuff to
> get right
>> and I'd like to thank you for picking this up.
> [Reza Rahman] Could you be more specific? That would be helpful in making
> this more concrete.
>> But I share Lincolns sentiments that
>> CDI is NOT the right place to define this.
> [Reza Rahman] If a significant portion of this EG feels this way, we can
> certainly get this clarified by Bill, Linda, et al. My suspicion is that
> although this might not be the ideal place, it is likely the most pragmatic
> place. Either way, it would be good to vet out the technical aspects of the
> proposal with CDI centric folks.
To me it seems that the proposed wording solely targets JTA use cases. And this is imo way too narrow.
Imo we should start with summing up the supported use cases and the parts we need for it:
* @Transactional annotation
* TransactionInterceptor implementation
Supported use cases:
* 1.) JTA Extended EM with UserTransaction
* 2.) JTA Container Managed EM in @Stateless EJBs
* 3.) JTA Container Managed EM in Message Driven Beans (do we need to distinguish between 2. and 3. ?)
* 4.) CDI produced 'native'/'unmanaged' EntityManager
* 5.) Container managed EM injected in CDI beans
* 6.) Container managed EM injected in JSF managed beans
* various mixed scenarios of 2.) .. 4.)
Once we agree on those lists, THEN we can discuss about the implementation details!
Sidenote: in CODI (and DeltaSpike) we implemented this via 1 single Interceptor implementation which injects a @Dependent PersistenceStrategy which the user can switch via <alternatives>. Not sure though if we could specify it exactly that way.
>> You can definitely spare the whole paragraph above (not only the quoted
>> but the whole one), because this is automatically defined if you describe
>> lifecycle of the @TransactionScoped beans. Ie WHEN does the context start,
>> WHEN does the context end and WHEN is the context active/inactive
> [Reza Rahman] Hmm - not sure what you mean? Could you kindly propose
> alternate text? If anything I felt I was writing too little...
see my comment above regarding the wording in CDI spec 6.7. "Context management for built-in scopes"
>> Also your wording doesn't cover what happens if there is a method
>> with TransactionAttributeType.REQUIRES_NEW ?
>> In this case the original @TransactionScoped should become isActive()
>> and a new one should be opened, isn't?.
> [Reza Rahman] I avoided calling out specific CMT cases to keep this compact.
> The use-case is handled though if you trace it through. In the REQUIRES_NEW
> case, if there is an existing transaction, it would be suspended and hence
> any contextual instances that belong to it would not be propagated past the
> new method invocation. If there wasn't an existing transaction, the case
> would be relatively straight-forward -- the instance would be created and
> placed into the transactional cache. In addition, it will propagated to the
> end of the method call to handle the BMT/short-transaction use-case.
See my note above 'set as active' vs 'active if'
>> Also it's way too much fixated to JTA. There is a world outside of JTA
>> most apps do NOT use JTA at all...
> [Reza Rahman] It is true that this is deliberately focused on JTA. The basic
> reason for this is ease of standardization since the JTA semantics are
> known. If the JTA case can be standardized, I imagine one could tackle the
> case of other transaction management APIs down the line if theirs APIs are
> also adequately standardized as far as CDI/Java EE is concerned. Also,
> personally I am a supporter of JTA and see few technical reasons to avoid
> it's use. Nevertheless, I deliberately tried to keep that possibility open
> (not the parenthetical remark about CMT/BMT==JTA).
To be honest, JTA semantics are blurry to most users and often completely container depending (when it comes to the gory details you need in big apps). JTA is also really imposing heavy limitations to users, e.g. that you cannot serialize open JTA transactions and there is also no portable way to propagate JPA entity state across clusters when serialisation kicks in. Due to this restriction a LOT projects either use DAOs in their JSF backing beans or do NOT use JTA at all...
>> Also please s/contextual object/Contextual Instance/ as this is a well
>> terminus tecnicus in the spec.
> [Reza Rahman] Again, could you kindly propose specific alternate text? That
> would be greatly helpful.
It's really just s/contextual object/Contextual Instance/
See 6.5, especially 6.5.2. "Contextual instance of a bean"
"Contextual Instance" is a well defined technical term in the CDI spec.
>> > Transactional contexts that come into effect in
>> > complete absence of a transaction
>> > are shared between all contextual objects in a single
>> > managed bean method call
>> a.) you have a chicken egg problem if you e.g. try to @Produces
>> @TransactionScoped EntityManager and you do not yet have an open
> [Reza Rahman] Not sure I follow? The way it is specified, the object would
> be created and propagated across the method call. Any transactions that
> become active after the object is created can still be utilized by the
We must take care to not implicitely introduce a cyclic reference which creates a chicken-egg problem. E.g. a @TransactionScoped bean cannot open/control a UserTransaction.
>> b.) imo if there is no open Transaction HANDLER then the
>> shall return false, and accessing a Contextual Reference for a
>> @TransactionScoped bean will lead to a ContextNotActiveException.
> [Reza Rahman] Right. This was the initial implementation/concept in Resin.
> The trouble is that it is severely limiting for BMT and cases where there is
> no active transaction. For example, the JPA entity manager can be used
> outside of an active transaction as long as you stick to "read-only"
> methods: . The case in the JMS context is even broader since you can use the
> JMS APIs without a transaction (even within Java EE).
I see. This is targeted for 'auto transactions' which get created if a user is executing a query _without_ calling em.getTransaction().begin()/commit(). Please note that there is still a transaction in place - it's just not controlled by the user. But the wording only fits the @Stateless EJB use case. All other use cases outlined above would imo be broken with the very wording.
"Similarly, contextual objects can outlive method invocation boundaries if a transaction spans multiple method calls." is especially very dangerous imo. How would you implement this? I fear this behaviour would be nice for some use cases and completely fuck up other ones.
>> > Note that each managed bean method call begins and ends its own
>> > separate local context.
>> certainly not true for nested bean method calls...
> [Reza Rahman] Not sure what you mean? Limiting propagation to method
> boundaries was specifically designed to avoid sticky situations where
> transactions may be suspended/activated on the same thread multiple times.
But that doesn't work in practice. Usually only the outermost @Transactional (implicite or explicite) method call will 'open' the transaction context. It might get suspended when you call a method with TransactionAttributeType.REQUIRES_NEW, but usually it just remains open.
>> > Note also that most Container-Managed Transactions
>> > (CMT) span one or more manage bean method calls.
>> I don't get that. Once your EJB method invocation returns, the built in
>> transaction-handler will commit that stuff and even close the involved
>> EntityManager (I'm talking about the REAL native EM and NOT the
>> EntityManager facade you might see as user).
> [Reza Rahman] Right, but the point is that CMT transactions can and do
> indeed span multiple method calls (e.g. is transaction propagation is set to
> REQUIRED or SUPPORTS). In such a case, the context would ensure that all
> methods in a the call-stack participating in the transaction are referring
> to the same instance.
>> Au contraire with an Extended EM, you might open the UserTransaction in a
>> backing bean and keep it open during multiple @Stateless service
>> finally closing the UserTransaction before the JSF action returns.
> [Reza Rahman] Yes, propagating instances across the transaction would handle
> this the way it is described now. BTW, for JPA in particular, you are
> actually not allowed to propagate EMS from stateful to stateless contexts:
> ture.html (not a reasonable restriction IMO).
I've not written anything about @Stateful. The JSF managed bean spec defines that @PersistenceContext might get injected. It doesn't say anything about those restrictions.
PS: This is only true for container managed EntityManagers anyway...
PPS: The doc you mentioned only covers container managed EMs, thus leaving out a wide share of productive projects which create and manage the EM themselfs. E.g. almost all Spring based apps, and lots of others. I prefer to reference the JSR specs instead (despite they are much harder to read than the really good JBoss documents).
>> Of course those are only first 'feelings' and I certainly need more
> to get
>> warm with the wording.
> [Reza Rahman] Right -- I fully expect that and is the reason I will likely
> need to tend to this discussion for a duration (which is fine). The issues
> you raised are good conversation starters. Alternatively, we could start
> with a bunch of use-cases and see how the proposal fits? Luckily, we do
> already have those for the proposed JMS 2 context (maybe Nigel can oblige
> here?). Also, I could pose some pseudo-code for the proposal (tends to be
> easier to follow since it provides conditional structures which natural
> language does not).
+1 for use cases. In CODI, TomEE, Seam-Persistence we already have a few @Transactional implementations.
Please note that there are quite a few patterns out there which are _not_ working on clusters! This is also because JPA has a few fundamental flaws which I like to get fixed as well (see JPA_SPEC-21).
I'm not sure if we can deliver a 1-fits-it-all logic. This might depend heavily on how the user works within his application.
More information about the cdi-dev