You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@synapse.apache.org by Rajith Attapattu <ra...@gmail.com> on 2008/01/01 19:34:13 UTC

Re: notes on adding JTA

Paul,

I appologize for the delay, here are my comments.

rajith.
On Nov 29, 2007 3:54 AM, Paul Fremantle <pz...@gmail.com> wrote:

>    1) If a user has a tx JMS queue and a tx connection to a database, then
> > > if there is a failure committing the transaction, both the queue and db
> > > updates should be rolled back
> >
> >
> > Paul when u said queue being rolled back, I assume you meant that the
> > enqueue and deqeue operations are transactional and not the queue creation
> > right?
> > That is if I, withing the scope of a transaction, send messages to a
> > qeueu and/or consume messages from a queue and if the transaction is rolled
> > back, then I will dequeue the messages I published and/or enqueue the
> > messages that I consumed.
> >
>
> I meant the messages not the creation or deletion of queues.Sorry I was
> unclear.
>
>   However if I create a queue within the scope of a transaction, do u
> > expect the queue to be deleted if the transaction is rolled back? In
> > AMQP/Qpid we don't do that and I think other JMS impls don't either (I stand
> > to be corrected).
> >
>
> No I don't believe other JMS providers do this either.
>
>   Finally, can I recommend we look at Atomikos
> > > http://www.atomikos.com/products.html#ate
> > >
> > > This seems a very effective, ASL licensed JTA implementation that
> > > supports transactions on incoming JMS work without requiring an EJB
> > > container or MDB. Which seems just what we need!
> >
> >
> > The XA implementation of any JMS provider should be able to support this
> > outside of an EJB container.
> >
>
> That is true - any XA enabled JMS provider can be used in this way, but
> that does NOT mean that any JTA implementation provides this *without* an
> EJB container.
> The tricky part - and talking to people like David Jencks makes me believe
> this is actually tricky - is making sure the transaction is in place before
> the JMS onMessage() gets called.
>

You mean that before my "onMessage()" method is called I need to ensure that
it is done within the scope of a transaction?


>  That is what the EJB container/MDB does for you. Now I asked David if the
> jencks project http://jencks.org/ could do this. He indicated it might,
> but he also thought we might need to re-use some of the OpenEJB container
> code. However, reading the Atomikos documentation it seems like this does it
> "out of the box".
>


>  I'm afraid I didn't really understand your options 1, 2a, 2b, so I'm
> going to try to clarify this.
>

Sorry about that, I presented the options in hope of understanding what you
said in your first email. Looks like I didn't do a good job.
Here is another attempt.

Option 1 - is where synapse is an XA resource, that will send a message
through if a transaction is comitted, else drop it.
Ex. Application A, within the scope of a transaction, makes a DB update and
send a message to synapse (using any transport) where synapse is supposed to
mediate it and send it out.
If the DB update fails then the TM will notify Synapse and it will just drop
the message. OR if the synapse mediation fails the TM will ask the DB to
rollback.
The advantage here is that synapse can participate in a transaction even
when using a non transactional transport like HTTP. However the outgoing
transport would need reliable semantics to garuntee the delivery of the
message.

The disadvantage is that this model is complicated.
The application needs to tell synapse about the transaction boundaries via a
TM and Synapse needs to implement the XA stuff.

Option 2a and 2b is a lot more simple.
2a - Synapse is not aware of transactions. The application that sends
messages to synapse can do so transactionally and synapse is not aware of
it. In the case where it sends transactionally, Synapse will only see the
message if it gets commited.

2b - Synapse sends messages transactionally leveraging the transactional
support of the transport. Ex, Synapse mediates a message, updates a DB and
sends the message within the scope of a transaction. I was wrong to say that
you don't need code changes, bcos here we need to maintain some notion of
transactions, like an xid so that the DB logging mediator and the transport
can use that.


>
>
> So firstly, lets be clear - the transaction is per *one-way* interaction.
> It's not a request/response full transaction that you would get with CORBA -
> its akin to the transactionality you get with MQSeries or another messaging
> engine. So in a request-response there will be two transactions - one for
> the request and one for the response.
>

Same page with you.

>
>
> The second thing is that Synapse is not participating in any end-to-end
> application transactions. In other words, I'm not expecting to take an
> existing fully distributed XA transaction (for example a CORBA transaction)
> and add Synapse in the middle without breaking the existing 2pc
> transactionality.
>
> Lets just be clear about distributed 2PC. There is the model where the
> complete activity end-to-end is fully 2PC. This is implemented by CORBA and
> WS-AT. Then there is the model like JMS or MQSeries where the work is broken
> into transactional hops. Here is a classic example of this Queued
> Transaction Processing (QTP) model:
>

Again same page with you.

>
> transaction 1:
> System updates DB to say order sent, message queued. Both either happen or
> don't.
>
> transaction 2:
> Message dequeued and order logged in second database: both either happen
> or don't.
>
> The interesting case is the failure of the second transaction. In this
> case, the message dequeue (onMessage) will be tried again. Supposing it
> fails n times in a row, the usual behaviour is to put the failing message
> into an error queue and notify someone. In this case the originator needs to
> be notified by some process that their order was never accepted.
>
> Now in the case of Synapse, if we are dequeueing the message then its our
> responsibility to maintain the QTP transaction semantics. So now lets add
> synapse in the middle.
>
> trans 1 (as before)
>
> transaction 1a (synapse)
> Synapse dequeues the message, modifies it, updates a log database, and
> requeues it in a new queue (Q2). Either everything happens or not.
>

Paul, In this case the dequeue from Q1, the DB update and the enqueue to Q2
should all happen within the same transaction.
However both the incomming transport and the outgoing transport has to
support transactions.
The tricky part is for us to ensure the dequeue is transactional. - is this
what you were refering to as tricky above?


>
> If this all works, then transaction 2 can proceed as before (assuming that
> the tran2 JMS code has been pointed to the new queue (Q2))
>
> If this fails, just as before, we now have to put this message into a dead
> message queue and notify the initial sender (out-of-band) that the message
> has not been accepted.
>

Yes we can DLQ the message if the other application fails to process it.
Synapse can also listen to the specific DLQ and then send a message to the
original sender.


>
> Now in the more traditional 2PC model, there would only be one transaction
> - not two or three. However the problem with that is the distributed
> locking.
>

One solution maybe to do option 1, but it's complicated.


>
>
> Now Rajith you asked how we implement this. You are *almost* right in
> saying its the transports that need to implement this. So suppose we just
> discuss the JMS-->DBlogging->JMS mediation scenario. As long as we have a
> JTA transaction monitor in place, AND we have defined transactional queues
> and an XA database connection, AND we solve the issue of making sure the
> onMessage() happens within a new transaction, then we shouldn't have to
> write any extra code - the JTA transaction monitor will do everything else.
> However, there is still a lot of work making this happen.
>

Agreed, see my comments above on that. " I was wrong to say that you don't
need code changes, bcos here we need to maintain some notion of
transactions, like an xid so that the DB logging mediator and the transport
can use that."

Also making sure the onMessage() happens within a new transaction is very
very tricky. Since this a push, we have no control over it.
(AMQP has a nice solution to this using credits but we need a more general
solution here).
If we use a pull, ex receive() or receive(timeout) then it is easy as we can
ensure we call that inside a transaction.

One crude (and expensive) solution is to create a new subscription inside
the transaction and then delete it after we complete it. If not we need some
sort of flow control like we have in AMQP.


>
>
> Also, we need to work through the scenarios when one side is not a
> transactional transport (e.g. HTTP) and follow those up.
>

Yes, one solution is option 1. But to be frank I still haven't thought about
all the use cases for transactions, especially the corner cases.
Paul, I think it's a good idea to first come up with a bunch of
transactional use cases that we want to support using Synapse. We can then
start thinking about possible solutions. Maybe create a wiki page with these
use cases?


>
>
> Paul
>
> No!
>
>
> > >
> > > Paul
> > >
> > >
> > >
> > > --
> > > Paul Fremantle
> > > Co-Founder and VP of Technical Sales, WSO2
> > > OASIS WS-RX TC Co-chair
> > >
> > > blog: http://pzf.fremantle.org
> > > paul@wso2.com
> > >
> > > "Oxygenating the Web Service Platform", www.wso2.com
> >
> >
> >
> >
> > --
> > Regards,
> >
> > Rajith Attapattu
> > Red Hat
> > blog: http://rajith.2rlabs.com/
>
>
>
>
> --
> Paul Fremantle
> Co-Founder and VP of Technical Sales, WSO2
> OASIS WS-RX TC Co-chair
>
> blog: http://pzf.fremantle.org
> paul@wso2.com
>
> "Oxygenating the Web Service Platform", www.wso2.com
>



-- 
Regards,

Rajith Attapattu
Red Hat
blog: http://rajith.2rlabs.com/