[wildfly-dev] The EJB client and remote JTA transaction propagation
David M. Lloyd
david.lloyd at redhat.com
Tue Feb 9 12:25:15 EST 2016
Ah, interesting! I will think some more about this.
On 02/09/2016 11:07 AM, Tom Jenkinson wrote:
> I understood what you said but didn't communicate my suggestion clearly
> enough sorry.
>
> System1 creates a new transaction
> System1 registers a synchronization SYNC1 on transaction to record soon to
> be pending request for System2 *** NEW BIT
> System1 invokes EJB1 on System2 with XID1
> System2 examines EJB1's transaction mode
> System2 inflows XID1
> System2 executes EJB1
> System2 returns with "EnlistMe" flag
> System1 updates SYNC1 to say the call returned *** NEW BIT
> System1 enlists System2
> ...other work happens...
> System1 prepares XID1
> System2 prepares XID1 & returns XA_OK
> System1 commits
> System2 commits
>
> If the failure happens before EJB1 returns then SYNC1 throws an exception
> during beforeCompletion.
>
> On 9 February 2016 at 16:50, David M. Lloyd <david.lloyd at redhat.com> wrote:
>
>> I think you misunderstood what I"m getting at. Consider this normal
>> sequence of events under the proposed enlistment strategy:
>>
>> System1 creates a new transaction
>> System1 invokes EJB1 on System2 with XID1
>> System2 examines EJB1's transaction mode
>> System2 inflows XID1
>> System2 executes EJB1
>> System2 returns with "EnlistMe" flag
>> System1 enlists System2
>> ...other work happens...
>> System1 prepares XID1
>> System2 prepares XID1 & returns XA_OK
>> System1 commits
>> System2 commits
>>
>> Now what happens if the System1-System2 connection is broken before EJB1
>> returns? System2 is never enlisted, System1 may prepare & commit the XID1
>> transaction without ever knowing about System2, which now has an orphaned
>> transaction which has performed some unknown amount of work under the same
>> GTID as the now-committed transaction. System2's transaction times out,
>> the work is rolled back, and chaos ensues.
>>
>> So this means that I have to have System2 tell System1 to enlist *before*
>> "System2 executes EJB1" rather than after, right?
>>
>>
>> On 02/09/2016 10:41 AM, Tom Jenkinson wrote:
>>
>>> My understanding would be that the EJB transport would detect the
>>> transaction.commit call (although it should have an outstanding EJB call
>>> so
>>> I don't think that it would be possible for a client to call commit) and
>>> throw an exception. It could be that EJB transport would register a
>>> synchronization beforeCompletion to do this.
>>>
>>> On 9 February 2016 at 14:41, David M. Lloyd <david.lloyd at redhat.com>
>>> wrote:
>>>
>>> I have a follow-up question about delaying enlistment (I'm getting to this
>>>> point in the code).
>>>>
>>>> I'm worried about a scenario wherein the subordinate server begins the
>>>> transaction, does some work in the EJB, and then tries to return, but the
>>>> connection to the server has been partitioned indefinitely. The server
>>>> *may* opt to continue and commit the transaction despite the subordinate
>>>> failure, in which case the subordinate, not receiving any control
>>>> messages
>>>> from the root coordinator, would roll back the transaction at the
>>>> timeout,
>>>> while the server (not knowing about the subordinate server) would
>>>> continue
>>>> and commit the transaction, not knowing what work (if any) the
>>>> subordinate
>>>> server had performed.
>>>>
>>>> Is this a real problem? Perhaps I do need an "enlist me" callback to the
>>>> server after all, which executes before the EJB imports and resumes the
>>>> subordinate transaction?
>>>>
>>>>
>>>> On 02/02/2016 08:27 AM, Tom Jenkinson wrote:
>>>>
>>>> No problem :)
>>>>>
>>>>> On 2 February 2016 at 13:49, David M. Lloyd <david.lloyd at redhat.com>
>>>>> wrote:
>>>>>
>>>>> Ah okay, cool. This is an easy (and, in hindsight, rather obvious)
>>>>>
>>>>>> enhancement that I can build into the new protocol with a minimum of
>>>>>> effort.
>>>>>>
>>>>>> Thanks!
>>>>>>
>>>>>> On 02/02/2016 03:01 AM, Tom Jenkinson wrote:
>>>>>>
>>>>>> Hi David,
>>>>>>
>>>>>>>
>>>>>>> I was referring to case 1 when the transaction is inflowed into a
>>>>>>> second
>>>>>>> server. For JTS the type of transaction we create is a
>>>>>>> ServerTopLevelAction and this in its ctor calls back to the remote
>>>>>>> server:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> https://github.com/jbosstm/narayana/blob/master/ArjunaJTS/jts/classes/com/arjuna/ats/internal/jts/orbspecific/interposition/resources/arjuna/ServerTopLevelAction.java#L121
>>>>>>> If the transport can do that without the TMs assistance then that
>>>>>>> works
>>>>>>> for me :)
>>>>>>>
>>>>>>> I don't think we should optimize for case 2. The incidents where a
>>>>>>> transaction is created and not used should be really low.
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Tom
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 1 February 2016 at 15:43, David M. Lloyd <david.lloyd at redhat.com
>>>>>>> <mailto:david.lloyd at redhat.com>> wrote:
>>>>>>>
>>>>>>> I was thinking about this a bit. It seems to me that there are
>>>>>>> two
>>>>>>> "levels" of this that could be explored:
>>>>>>>
>>>>>>> 1. A transaction was made available to the server, but the EJB
>>>>>>> on
>>>>>>> the server does not use the caller's transaction context, so the
>>>>>>> EJB
>>>>>>> code never actually has to inflow the transaction. The EJB code
>>>>>>> would be able to make this determination without any help from
>>>>>>> the
>>>>>>> TM.
>>>>>>>
>>>>>>> 2. A transaction was made available, and the EJB resumed it,
>>>>>>> but no
>>>>>>> resources were actually enlisted, or perhaps resources were
>>>>>>> enlisted
>>>>>>> but not actually used, resulting in the same effect but relying
>>>>>>> on
>>>>>>> the TM to provide this information.
>>>>>>>
>>>>>>> I guess when you refer to a callback from Narayana, (2) is what
>>>>>>> you're referring to? When would this information be available?
>>>>>>> Maybe as some special result of suspending the transaction?
>>>>>>>
>>>>>>>
>>>>>>> On 01/29/2016 12:27 PM, David M. Lloyd wrote:
>>>>>>>
>>>>>>> That's an interesting idea. So in effect, the remote EJB
>>>>>>> would
>>>>>>> tell the
>>>>>>> caller "you sent me a transaction ID, but in the end, I
>>>>>>> didn't
>>>>>>> use it"?
>>>>>>> I would need to think about how this might work in the
>>>>>>> presence of
>>>>>>> multiple concurrent invocations on the same transaction.
>>>>>>>
>>>>>>> Either way though, I think it would still be beneficial for
>>>>>>> clients to
>>>>>>> be able to explicitly annotate a client method (or otherwise
>>>>>>> establish a
>>>>>>> policy) such that it causes transactions to be propagated
>>>>>>> (or
>>>>>>> not), or
>>>>>>> to enforce transaction-related preconditions. The
>>>>>>> interceptor
>>>>>>> that
>>>>>>> implements this feature doesn't actually have protocol
>>>>>>> awareness:
>>>>>>> it
>>>>>>> just examines the current environment, and decides whether
>>>>>>> to
>>>>>>> attach the
>>>>>>> transaction to the invocation context.
>>>>>>>
>>>>>>> On 1/29/16 10:42 AM, Tom Jenkinson wrote:
>>>>>>>
>>>>>>> One option that I would favour is to go down the JTS
>>>>>>> route
>>>>>>> where the
>>>>>>> subordinate calls back on the parent to tell it to
>>>>>>> register
>>>>>>> it in the
>>>>>>> transaction. This could be a new JBoss Remoting API
>>>>>>> that I
>>>>>>> can invoke
>>>>>>> from Narayana. The call would not necessarily be a
>>>>>>> remote
>>>>>>> call, it would
>>>>>>> invoke back into the JBR transport to tell it that when
>>>>>>> it
>>>>>>> returns to
>>>>>>> the parent it needs to enlist (or not).
>>>>>>>
>>>>>>> On 29 January 2016 at 15:47, David M. Lloyd
>>>>>>> <david.lloyd at redhat.com <mailto:david.lloyd at redhat.com>
>>>>>>> <mailto:david.lloyd at redhat.com
>>>>>>>
>>>>>>> <mailto:david.lloyd at redhat.com>>> wrote:
>>>>>>>
>>>>>>> As you may know, WildFly supports a feature
>>>>>>> wherein an
>>>>>>> EJB client
>>>>>>> which
>>>>>>> is invoking an EJB on a remote server has the
>>>>>>> option
>>>>>>> to
>>>>>>> propagate its
>>>>>>> local transaction to the remote server, treating
>>>>>>> the
>>>>>>> remote server
>>>>>>> as a
>>>>>>> subordinate and coordinating the transaction's
>>>>>>> two-phase commit among
>>>>>>> the resultant graph of servers. This feature has
>>>>>>> always been
>>>>>>> limited in
>>>>>>> that, when enabled, transactions are always
>>>>>>> propagated,
>>>>>>> regardless of
>>>>>>> the peer EJB's transaction policy, or of whether
>>>>>>> the
>>>>>>> peer even has a
>>>>>>> transaction manager.
>>>>>>>
>>>>>>> So, for the invocation rework which I anticipate
>>>>>>> will
>>>>>>> be included in
>>>>>>> WildFly 11, I've introduced a new client-side
>>>>>>> annotation intended
>>>>>>> to be
>>>>>>> associated with the EJB interface which informs the
>>>>>>> client library
>>>>>>> what
>>>>>>> to do for transaction propagation for that
>>>>>>> interface.
>>>>>>> In addition, I
>>>>>>> intend to configuration strategies which will allow
>>>>>>> the
>>>>>>> default
>>>>>>> mode to
>>>>>>> be specified in various ways (per-thread, globally,
>>>>>>> and
>>>>>>> by target
>>>>>>> interface/method all come to mind), for cases where
>>>>>>> the
>>>>>>> EJB's remote
>>>>>>> interface cannot be easily modified for some
>>>>>>> reason.
>>>>>>> I
>>>>>>> expect to
>>>>>>> also
>>>>>>> broaden these configuration strategies to apply to
>>>>>>> all
>>>>>>> client-side
>>>>>>> EJB
>>>>>>> interface/methods configuration items [3].
>>>>>>>
>>>>>>> The first part of this change is the addition of a
>>>>>>> new
>>>>>>> annotation
>>>>>>> called
>>>>>>> @ClientTransaction [1], which accepts as a value an
>>>>>>> enum called
>>>>>>> ClientTransactionPolicy [2]. The latter specifies
>>>>>>> whether a local
>>>>>>> transaction is required or forbidden for the
>>>>>>> method or
>>>>>>> interface, and
>>>>>>> also specifies whether the transaction is
>>>>>>> propagated
>>>>>>> or
>>>>>>> not
>>>>>>> propagated.
>>>>>>>
>>>>>>> I've added copious amounts of JavaDoc in order to
>>>>>>> establish
>>>>>>> exactly what
>>>>>>> the behavior of each mode is, as well as to specify
>>>>>>> how
>>>>>>> each mode
>>>>>>> interacts with the various modules that are
>>>>>>> configured
>>>>>>> via the
>>>>>>> standard
>>>>>>> javax.ejb.TransactionAttributeType enum.
>>>>>>>
>>>>>>> [1]
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> https://github.com/jbossas/jboss-ejb-client/blob/master/src/main/java/org/jboss/ejb/client/annotation/ClientTransaction.java
>>>>>>>
>>>>>>> [2]
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> https://github.com/jbossas/jboss-ejb-client/blob/master/src/main/java/org/jboss/ejb/client/annotation/ClientTransactionPolicy.java
>>>>>>>
>>>>>>> [2] (raw)
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> https://raw.githubusercontent.com/jbossas/jboss-ejb-client/master/src/main/java/org/jboss/ejb/client/annotation/ClientTransactionPolicy.java
>>>>>>>
>>>>>>> [3] for a list, see:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> https://github.com/jbossas/jboss-ejb-client/tree/master/src/main/java/org/jboss/ejb/client/annotation
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> - DML
>>>>>>> _______________________________________________
>>>>>>> wildfly-dev mailing list
>>>>>>> wildfly-dev at lists.jboss.org
>>>>>>> <mailto:wildfly-dev at lists.jboss.org>
>>>>>>> <mailto:wildfly-dev at lists.jboss.org
>>>>>>> <mailto:wildfly-dev at lists.jboss.org>>
>>>>>>> https://lists.jboss.org/mailman/listinfo/wildfly-dev
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> - DML
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>>
>>>>>> - DML
>>>>>>
>>>>>>
>>>>>>
>>>>> --
>>>> - DML
>>>>
>>>>
>>>
>> --
>> - DML
>>
>
--
- DML
More information about the wildfly-dev
mailing list