Thanks for the reply - I was only able to get my route working by using a
Spring Transaction Manager to open a new transaction (using
PROPOGATION_NOT_SUPPORTED) to do the actual publish request/reply part of
the route (just wrapped the producer template publish in this transaction). 
That worked.

However it opened up a few other issues that we were not comfortable
handling (such as stray database records if the persistence succeeded but
other parts of the processing failed).  Although this overall situation
could potentially be handled with a JTA product that would encompass the
processing in this route and also the DB persistance handled by the other
process on the other queue.

We changed our approach to remove the Request/Reply requirement from our
route.


My only remaining concern is just that the documentation for the Transaction
support and RequestReply functionality left me thinking this was a bug in my
code or a bug in the Camel code.  It seemed to me from reading the
documentation that sending a RequestReply message in a transaction would
work - but would just not be part of the transaction (meaning - if the
transaction rolled back, just accept the fact that whatever happened on that
other process will NOT roll back).

In reality - no matter what I did, I could not get the message to publish
and get a reply while operating in a transaction.  It was only after I
introduced a Spring transaction in my processor that I was able to force the
message to be published and get a reply.

Perhaps a new option to "force" a publish to occur even in a
transaction..with the clear understanding that doing so will mean that part
is NOT going to be part of the transaction.  Indeed the documentation only
states using TransactedInOut=true will cause it to not operate in a
transaction...where in reality it would not even send the request.

Specifically this part from: http://camel.apache.org/jms.html  - the bolded
part is what confused me as it seemed to contradict what was right above it
stating that you can't use transactions at all.  The solution here is
probably just making sure that the purpose for "transactedInOut=true" is
clearly explained.  As of right now I don't really understand what it is
for, where it can be used, and what it will accomplish.

Transaction and Request Reply over JMS

Note that when using Request Reply over JMS you cannot use a single
transaction; as JMS will not send any messages until a commit is performed,
the server side won't receive anything at all until the transaction commits.
So, with request/response you must commit a transaction after sending the
first request and then use a separate transaction for receiving the
response.

This is why the transacted property applies only to the InOnly message
Exchange Pattern (MEP). If you want to use transactions for the InOut MEP as
well, you must set transactedInOut=true.

To recap: if you have transacted=true, transactedInOut=false and are sending
an InOut, the Exchange will not use transactions.


In any event - thank you for your suggestion!


Fintan Bolton wrote:
> 
> Hi Johnathan,
> 
> To elaborate on Claus's reply. In general, you cannot really process InOut
> exchanges inside a transaction (yes, there is a 'transactedInOut' option,
> but it only applies to a very special use case and is not relevant to your
> example).
> 
> The best approach, as Claus suggested, is to split your route into two
> parts: one route to handle the 'request' leg of the processing and another
> route to handle the 'reply' leg of the processing. You need to break up
> the request/reply queue, 'queue:persistancequeue', into two separate
> queues that explicitly handle the request and reply legs, e.g.
> 'queue:requestqueue' and 'queue:replyqueue'.
> 
> You can then write your route in the form of two separate transactional
> routes:
> 
> from("queue:incomingqueue?transacted=true")
>         .process(getSomeTranslationProcessor())
>         .to("queue:requestqueue")
> 
> from("queue:replyqueue?transacted=true")
>         .process(getSomeOtherTransformerProcessor())
>         .to("queue:outgoingqueue");
> 
> The exchanges passing through these routes should be of InOnly type. I
> added the ?transacted=true option just to indicate that both routes are
> transactional. Of course, you have to do all the additional Spring
> configuration to make the 'queue' component transactional as well.
> 
> Regards,
> Fintan
> 
> 
> 
> Claus Ibsen-2 wrote:
>> 
>> Hi
>> 
>> Try using a 2nd JMS component for sending. Then its separated from the
>> 1st component.
>> 
>> 
>> On Sat, Oct 31, 2009 at 12:26 AM, jonathanq <[email protected]> wrote:
>>>
>>> I am having an issue with JMS queues and transactions.
>>>
>>> I have the following route:
>>>
>>> from("queue:incomingqueue")
>>>        .process(getSomeTranslationProcessor())
>>>        .process(getMyPersistanceProcessor())
>>>        .process(getSomeOtherTransformerProcessor())
>>>        .to("queue:outgoingqueue");
>>>
>>> The first and third processor just do some simple transformation on the
>>> exchange.  The middle processor (myPersistanceProcessor) is the key
>>> piece.
>>>
>>> It is a processor that sends part of the exchange to another queue and
>>> requests a reply back.  It uses a ProducerTemplate and looks like:
>>>
>>> Long recordDBId = (Long)producer.sendBody("queue:persistancequeue",
>>> ExchangePattern.InOut, objectToPersist);
>>>
>>> It is a synchronous process - so the myPersistanceProcessor will wait
>>> for a
>>> reply back before continuing.
>>>
>>> Now - the issue I have is this.  If that InOut part of the route fails
>>> for
>>> any reason (such as a time out, returns an error etc).  I want to
>>> essentially NOT acknowledge the message from the original incoming JMS
>>> queue
>>> (meaning it will go back on the front of the queue).
>>>
>>>
>>> I know that if you just do a "queue:incomingqueue?transacted=true" - it
>>> will
>>> put the message back on the queue if the exchange failed.  However If
>>> you
>>> add "transacted=true" to the incoming queue in my route - it will never
>>> send
>>> the message for the RequestReply part.
>>>
>>> Based on the documentation - that is because we must first commit the
>>> transaction and then start another.  However there is mention of the
>>> value
>>> "transactedInOut=true" which seems to imply it will create a transaction
>>> that wraps the WHOLE process (including the requestreply).
>>>
>>> In practice - using "transactedInOut=true" means that if the
>>> producer.sendBody() timesout, it sends an eviction notice for that
>>> message -
>>> but the original exchange does NOT get put back on the incoming queue.
>>>  In
>>> fact it disappears altogether.  The Camel JMX bean does not record it as
>>> a
>>> "Failed Exchange" - even through the log message says it was a failed
>>> exchange.  The exposed Camel JMX thinks it was a successful exchange.
>>>
>>> Is that how the "transactedInOut=true" is supposed to operate?  Is there
>>> any
>>> way to tell the incoming queue that we did NOT process the message and
>>> have
>>> it put back there if it failed?  Is there an error route that would put
>>> the
>>> original message back on the queue?  Or is that where using the:
>>>
>>> onException(Exception.class)
>>> .maximumRedeliveries(-1)
>>>
>>> comes into play - as that will cause it to just be re-tried constantly?
>>>
>>> Thanks for any help you can offer!
>>> --
>>> View this message in context:
>>> http://old.nabble.com/JMS-Transactions-and-RequestReply---transactedInOut%3Dtrue-not-working--tp26138285p26138285.html
>>> Sent from the Camel - Users mailing list archive at Nabble.com.
>>>
>>>
>> 
>> 
>> 
>> -- 
>> Claus Ibsen
>> Apache Camel Committer
>> 
>> Author of Camel in Action: http://www.manning.com/ibsen/
>> Open Source Integration: http://fusesource.com
>> Blog: http://davsclaus.blogspot.com/
>> Twitter: http://twitter.com/davsclaus
>> 
>> 
> 
> 

-- 
View this message in context: 
http://old.nabble.com/JMS-Transactions-and-RequestReply---transactedInOut%3Dtrue-not-working--tp26138285p26206104.html
Sent from the Camel - Users mailing list archive at Nabble.com.

Reply via email to