You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by dcheckoway <dc...@gmail.com> on 2009/06/04 18:43:50 UTC

How to control transactions when already in a transaction

Camel 1.6.1, ActiveMQ 5.2.0, Spring 2.5.6

I have a POJO consumer that gets invoked by Camel for messages on an
ActiveMQ JMS queue.  It's set up as transacted (JMS transaction manager). 
While my POJO is consuming a message, it needs to send a subsequent message
(or several messages) to a different JMS queue.  I use
ProducerTemplate.sendBody to accomplish this...it works fine...except...

My "complaint" is that the messages my consumer ends up sending don't
actually "appear" (in their respective JMS queue) until my consumer returns
(commits?).

Based on what I've read here (
http://activemq.apache.org/how-do-transactions-work.html ActiveMQ: How do
transactions work ) I'm convinced that ActiveMQ is buffering up the sent
messages until the consumer commits its transaction.  Something like that --
I'm definitely not an expert on transactions...and that's why I'm posting
this.

Is there any way to force an already-in-transaction consumer to use a
*separate* transaction when calling ProducerTemplate.sendBody?

Is there another trick?

My goal is to avoid the whole buffer-til-commit thing if possible, and just
have those sent messages queued "immediately."

Thanks in advance...
-- 
View this message in context: http://www.nabble.com/How-to-control-transactions-when-already-in-a-transaction-tp23873683p23873683.html
Sent from the Camel - Users mailing list archive at Nabble.com.


Re: How to control transactions when already in a transaction

Posted by dcheckoway <dc...@gmail.com>.
Thanks for the quick reply...my route looks like this (and this is the setup
I used when testing against Camel 2.0, with its <transacted/> element):

  <camelContext id="camelContext"
                xmlns="http://camel.apache.org/schema/spring">
    <template id="producerTemplate"/>
    <endpoint id="testQueueA" uri="activemq:queue:test.queueA"/>
    <endpoint id="testQueueB" uri="activemq:queue:test.queueB"/>
    <route>
      <from uri="activemq:queue:test.queueA?concurrentConsumers=3"/>
      <transacted/>
      <bean ref="consumerThatAlsoProduces" method="onTestMessage"/>
    </route>
  </camelContext>

...and here's the code for my POJO consumer-that-also-produces:

public class ConsumerThatAlsoProduces {
    @Autowired
    ProducerTemplate producerTemplate;
    @Autowired
    @Qualifier("testQueueB")
    Endpoint testQueueB;
    
    public void onTestMessage(TestMessage msg) {
        producerTemplate.sendBody(testQueueB, ...a new message...);
    }
}


I see your point about having the outbound endpoint non-transacted, but I'd
prefer to have it send in a transaction.  Is there a way to tell Camel to
use a new transaction when using producerTemplate inside the existing
transaction?



Claus Ibsen-2 wrote:
> 
> Hi
> 
> What does your route look like?
> 
> Just a quick idea. Maybe in the producer template sendBody you could
> use a JMS endpoint where you set transacted=false.
> 
> 
> On Thu, Jun 4, 2009 at 6:43 PM, dcheckoway <dc...@gmail.com> wrote:
>>
>> Camel 1.6.1, ActiveMQ 5.2.0, Spring 2.5.6
>>
>> I have a POJO consumer that gets invoked by Camel for messages on an
>> ActiveMQ JMS queue.  It's set up as transacted (JMS transaction manager).
>> While my POJO is consuming a message, it needs to send a subsequent
>> message
>> (or several messages) to a different JMS queue.  I use
>> ProducerTemplate.sendBody to accomplish this...it works fine...except...
>>
>> My "complaint" is that the messages my consumer ends up sending don't
>> actually "appear" (in their respective JMS queue) until my consumer
>> returns
>> (commits?).
>>
>> Based on what I've read here (
>> http://activemq.apache.org/how-do-transactions-work.html ActiveMQ: How do
>> transactions work ) I'm convinced that ActiveMQ is buffering up the sent
>> messages until the consumer commits its transaction.  Something like that
>> --
>> I'm definitely not an expert on transactions...and that's why I'm posting
>> this.
>>
>> Is there any way to force an already-in-transaction consumer to use a
>> *separate* transaction when calling ProducerTemplate.sendBody?
>>
>> Is there another trick?
>>
>> My goal is to avoid the whole buffer-til-commit thing if possible, and
>> just
>> have those sent messages queued "immediately."
>>
>> Thanks in advance...
>> --
>> View this message in context:
>> http://www.nabble.com/How-to-control-transactions-when-already-in-a-transaction-tp23873683p23873683.html
>> Sent from the Camel - Users mailing list archive at Nabble.com.
>>
>>
> 
> 
> 
> -- 
> Claus Ibsen
> Apache Camel Committer
> 
> Open Source Integration: http://fusesource.com
> Blog: http://davsclaus.blogspot.com/
> Twitter: http://twitter.com/davsclaus
> 
> 

-- 
View this message in context: http://www.nabble.com/How-to-control-transactions-when-already-in-a-transaction-tp23873683p23874232.html
Sent from the Camel - Users mailing list archive at Nabble.com.


Re: How to control transactions when already in a transaction

Posted by Claus Ibsen <cl...@gmail.com>.
On Thu, Jun 4, 2009 at 11:09 PM, dcheckoway<dc...@gmail.com> wrote:
>
> I finally got it t work as expected, but here was the deal...
>
>  <bean id="jmsTransactionManager"
>        class="org.springframework.jms.connection.JmsTransactionManager">
>    <property name="connectionFactory" ref="jmsConnectionFactory" />
>  </bean>
>
>  <bean id="jmsConfig"
>        class="org.apache.camel.component.jms.JmsConfiguration">
>    <property name="connectionFactory" ref="jmsConnectionFactory"/>
>    <property name="transactionManager" ref="jmsTransactionManager"/>
>    <property name="transacted" value="true"/>
>  </bean>
>
>  <bean id="activemq"
>        class="org.apache.activemq.camel.component.ActiveMQComponent">
>    <property name="configuration" ref="jmsConfig"/>
>  </bean>
>
> If I removed the "transacted=true" from the activemq component's jmsConfig
> (or set it to false), then it works as expected.  Messages are queued as
> they are "sent".
>
> But maybe somebody can help explain to me what the difference is.  Does that
> mean all of my sends are no longer transactional?  Are transactional sends
> even important?  I'm struggling to wrap my head around why I would or
> wouldn't want sends to be transactional.
It all depends on your use case.

I was thinking on the line maybe you could use spring transaction
demarcation using REQUIRES_NEW
when sending the messages using the producer template.

You can just create a new route that does this

from direct:foo
   policy (requires new)
   to (jms queue foo)

And maybe the original route can be transacted as well.

Or the 2nd route can use NO TX at all

from direct:foo
   policy (none)
   to (jms queue foo)

Or you can configure a 2nd AMQ client in the Spring XML file that has
transacted=false and use it for sending.

But ask at the AMQ forum as they get this kind of questions more often.



> --
> View this message in context: http://www.nabble.com/How-to-control-transactions-when-already-in-a-transaction-tp23873683p23877773.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>
>



-- 
Claus Ibsen
Apache Camel Committer

Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus

Re: How to control transactions when already in a transaction

Posted by dcheckoway <dc...@gmail.com>.
I finally got it t work as expected, but here was the deal...

  <bean id="jmsTransactionManager"
        class="org.springframework.jms.connection.JmsTransactionManager">
    <property name="connectionFactory" ref="jmsConnectionFactory" />
  </bean>

  <bean id="jmsConfig"
        class="org.apache.camel.component.jms.JmsConfiguration">
    <property name="connectionFactory" ref="jmsConnectionFactory"/>
    <property name="transactionManager" ref="jmsTransactionManager"/>
    <property name="transacted" value="true"/>
  </bean>

  <bean id="activemq"
        class="org.apache.activemq.camel.component.ActiveMQComponent">
    <property name="configuration" ref="jmsConfig"/>
  </bean>

If I removed the "transacted=true" from the activemq component's jmsConfig
(or set it to false), then it works as expected.  Messages are queued as
they are "sent".

But maybe somebody can help explain to me what the difference is.  Does that
mean all of my sends are no longer transactional?  Are transactional sends
even important?  I'm struggling to wrap my head around why I would or
wouldn't want sends to be transactional.
-- 
View this message in context: http://www.nabble.com/How-to-control-transactions-when-already-in-a-transaction-tp23873683p23877773.html
Sent from the Camel - Users mailing list archive at Nabble.com.


Re: How to control transactions when already in a transaction

Posted by dcheckoway <dc...@gmail.com>.
FYI, I tried setting transacted=false in the URI for the endpoint where the
transacted consumer ends up sending subsequent messages.  No change in
behavior...it still waits for the consumer to return before anything
actually shows up in the queue.

Any suggestions on how to force a new/separate transaction, or at least some
sort of immediate queueing of subsequent sends inside a transactional
consumer?

--Dan


Claus Ibsen-2 wrote:
> 
> Just a quick idea. Maybe in the producer template sendBody you could
> use a JMS endpoint where you set transacted=false.
> 

-- 
View this message in context: http://www.nabble.com/How-to-control-transactions-when-already-in-a-transaction-tp23873683p23877666.html
Sent from the Camel - Users mailing list archive at Nabble.com.


Re: How to control transactions when already in a transaction

Posted by Claus Ibsen <cl...@gmail.com>.
Hi

What does your route look like?

Just a quick idea. Maybe in the producer template sendBody you could
use a JMS endpoint where you set transacted=false.


On Thu, Jun 4, 2009 at 6:43 PM, dcheckoway <dc...@gmail.com> wrote:
>
> Camel 1.6.1, ActiveMQ 5.2.0, Spring 2.5.6
>
> I have a POJO consumer that gets invoked by Camel for messages on an
> ActiveMQ JMS queue.  It's set up as transacted (JMS transaction manager).
> While my POJO is consuming a message, it needs to send a subsequent message
> (or several messages) to a different JMS queue.  I use
> ProducerTemplate.sendBody to accomplish this...it works fine...except...
>
> My "complaint" is that the messages my consumer ends up sending don't
> actually "appear" (in their respective JMS queue) until my consumer returns
> (commits?).
>
> Based on what I've read here (
> http://activemq.apache.org/how-do-transactions-work.html ActiveMQ: How do
> transactions work ) I'm convinced that ActiveMQ is buffering up the sent
> messages until the consumer commits its transaction.  Something like that --
> I'm definitely not an expert on transactions...and that's why I'm posting
> this.
>
> Is there any way to force an already-in-transaction consumer to use a
> *separate* transaction when calling ProducerTemplate.sendBody?
>
> Is there another trick?
>
> My goal is to avoid the whole buffer-til-commit thing if possible, and just
> have those sent messages queued "immediately."
>
> Thanks in advance...
> --
> View this message in context: http://www.nabble.com/How-to-control-transactions-when-already-in-a-transaction-tp23873683p23873683.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>
>



-- 
Claus Ibsen
Apache Camel Committer

Open Source Integration: http://fusesource.com
Blog: http://davsclaus.blogspot.com/
Twitter: http://twitter.com/davsclaus