[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