camel-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Raul Kripalani <r...@fusesource.com>
Subject Re: OSGI Transaction Propagation to Camel Route
Date Tue, 17 Apr 2012 23:36:35 GMT
Also, see https://issues.apache.org/jira/browse/AMQ-3251.

I think the fix was backported to a release of Fuse ESB 4.4.1, that's
why we don't experience it in the example.

You may want to try with a Fuse ESB release if using an AMQ snapshot
is not an option for you.

Regards,
Raul.

On 18 Apr 2012, at 00:28, Raul Kripalani <raul@fusesource.com> wrote:

> I noticed you are using PROPAGATION_MANDATORY, which will throw an
> exception if a transaction doesn't already exist. Could that justify
> the exception you see when isolating only Camel? Can you try with
> PROPAGATION_REQUIRED instead?
>
> The sample I pointed you to works with no changes. In fact, you may
> want to try it out locally substituting the DB interactions with
> another JMS send...
>
> Thanks.
>
> On 17 Apr 2012, at 22:21, Chris Geer <chris@cxtsoftware.com> wrote:
>
>> The only place I'm not using an already XA aware connection factory is in
>> the API side, which is working perfectly because I'm manually enlisting the
>> Session.
>>
>> On the camel side, I used your example exactly as you can see in my
>> blueprint file and everything depends on XA aware activemq objects. Just to
>> make sure the API side of things wasn't interfering with the camel part
>> (which would be odd), I commented out all the code except for the camel
>> send and commented out the reference to the standard JMS Connection
>> Factory. Even with those drastic measures, I still got all the same errors
>> even though the camel route was the only participant in the transaction
>> along with the OSGI component itself.
>>
>> What was the change you made to get it working without errors?
>>
>> Chris
>>
>> On Tue, Apr 17, 2012 at 1:48 PM, Raul Kripalani <raul@fusesource.com> wrote:
>>
>>> It looks like you may not be using an XA-aware Pooled Connection Factory :D
>>>
>>> See
>>> http://activemq.apache.org/maven/5.5.0/activemq-pool/apidocs/org/apache/activemq/pool/XaPooledConnectionFactory.html
>>>
>>> It may look catchy, but all the layers of the stack need to be
>>> XA-aware, as XA requires a different behaviour when handling borrowing
>>> and returning to the pool.
>>>
>>> Let me know if it works for you.
>>>
>>> Regards,
>>> Raul.
>>>
>>> On 17 Apr 2012, at 18:31, Chris Geer <chris@cxtsoftware.com> wrote:
>>>
>>>> Raul,
>>>>
>>>> Thanks for the information. I tried what you said and I think it did have
>>>> some success with rolling back the transaction but it causes significant
>>>> errors to be thrown during a success case. As I've written a sample to
>>>> debug this issue I wanted you to have my latest code so we can be
>>>> referencing the same thing if you're willing to take another look.
>>>>
>>>> README: http://pastebin.com/UWq3yk4c
>>>> OSGI Implementation: http://pastebin.com/ifQTybn3
>>>> OSGI Interface: http://pastebin.com/zEUP8jJJ
>>>> Blueprint File: http://pastebin.com/sxBtxNCq
>>>> Test Driver/Logger: http://pastebin.com/SDVFvjGm
>>>> pom.xml: http://pastebin.com/kTXXaebV
>>>>
>>>> Part of the error I'm seeing is this (commit -> rollback)
>>>>
>>>> 10:12:52,624 | WARN  | 52 - timer://foo | PooledSession
>>>> | 57 - org.apache.activemq.activemq-pool - 5.5.1 | Caught exception
>>> trying
>>>> rollback() when putting session back into the pool:
>>>> javax.jms.TransactionInProgressException: Cannot rollback() inside an
>>>> XASession
>>>> javax.jms.TransactionInProgressException: Cannot rollback() inside an
>>>> XASession
>>>> at
>>>>
>>> org.apache.activemq.ActiveMQXASession.rollback(ActiveMQXASession.java:76)[60:org.apache.activemq.activemq-core:5.5.1]
>>>> at
>>>>
>>> org.apache.activemq.pool.PooledSession.close(PooledSession.java:111)[57:org.apache.activemq.activemq-pool:5.5.1]
>>>> at
>>>>
>>> org.apache.activemq.pool.XaConnectionPool$Synchronization.afterCompletion(XaConnectionPool.java:90)[57:org.apache.activemq.activemq-pool:5.5.1]
>>>> at
>>>>
>>> org.apache.geronimo.transaction.manager.TransactionImpl.afterCompletion(TransactionImpl.java:540)[45:org.apache.aries.transaction.manager:0.3.0]
>>>> at
>>>>
>>> org.apache.geronimo.transaction.manager.TransactionImpl.afterCompletion(TransactionImpl.java:533)[45:org.apache.aries.transaction.manager:0.3.0]
>>>> at
>>>>
>>> org.apache.geronimo.transaction.manager.TransactionImpl.commit(TransactionImpl.java:329)[45:org.apache.aries.transaction.manager:0.3.0]
>>>> at
>>>>
>>> org.apache.geronimo.transaction.manager.TransactionManagerImpl.commit(TransactionManagerImpl.java:252)[45:org.apache.aries.transaction.manager:0.3.0]
>>>>
>>>>
>>>> Chris
>>>>
>>>> On Tue, Apr 17, 2012 at 9:44 AM, Raul Kripalani <raul@fusesource.com>
>>> wrote:
>>>>
>>>>> I noticed several things in your config.
>>>>>
>>>>> 1) the JMS config should be inside the 'configuration' property of the
>>>>> ActiveMQComponent:
>>>>>
>>>>> <!-- ActiveMQ JMS Configuration is defined as Transacted and leverages
>>> XA
>>>>> Transactions -->
>>>>> <bean id="activemq"
>>>>> class="org.apache.activemq.camel.component.ActiveMQComponent">
>>>>>  <property name="configuration">
>>>>>   <bean class="org.apache.camel.component.jms.JmsConfiguration">
>>>>>      <property name="connectionFactory"
>>>>> ref="pooledConnectionFactoryXa"/>
>>>>>      <property name="transactionManager" ref="platformTxManager" />
>>>>>      <property name="transacted" value="false"/>
>>>>>      <property name="cacheLevelName" value="CACHE_NONE"/>
>>>>>   </bean>
>>>>> </property>
>>>>> </bean>
>>>>>
>>>>> 2) the 'transacted' property should be false as above, because you don't
>>>>> want the component to manage the transactions locally. The enrolment
of
>>>>> resources and coordination of transaction will happen on the XA level.
>>>>>
>>>>> 3) you are missing the ActiveMQResourceManager, which needs an
>>> injection of
>>>>> a javax.transaction.TransactionManager, which in reality is the same
as
>>> the
>>>>> PlatformTransactionManager, but you under a different interface
>>>>>
>>>>> See the following link for how your config should look like:
>>>>>
>>>>>
>>> https://github.com/FuseByExample/camel-persistence-part2/blob/master/route-one-tx-manager/src/main/resources/META-INF/spring/springConfig.xml
>>>>> .
>>>>>
>>>>> And of course, the route must be invoked from the same thread where the
>>>>> transaction is being started, and you cannot use the SEDA component for
>>>>> that. You must invoke it via a direct endpoint and I think
>>>>> requestBodyAndHeader(), but I'm not sure about this last point.
>>>>>
>>>>> Regards,
>>>>>
>>>>> *Raúl Kripalani*
>>>>> Principal Consultant | FuseSource Corp.
>>>>> raul@fusesource.com | fusesource.com <http://www.fusesource.com/>
>>> skype:
>>>>> raul.fuse | twitter: @raulvk <http://twitter.com/raulvk>,
>>>>> @fusenews<http://twitter.com/fusenews>
>>>>>
>>>>> <http://twitter.com/fusenews>
>>>>>
>>>>> On 17 April 2012 16:53, Chris Geer <chris@cxtsoftware.com> wrote:
>>>>>
>>>>>> Raul,
>>>>>>
>>>>>> I gave that a shot but it actually made the problem worse.
>>>>>> ProducerTemplate.requestBodyAndHeader uses an InOut exchange pattern
>>> but
>>>>>> since I'm not sending responses it always fails (regardless of
>>>>> transaction)
>>>>>> with a timeout saying it didn't get a response. It also send the
>>> message
>>>>> to
>>>>>> the topic even without the transaction being committed so it wouldn't
>>>>> solve
>>>>>> the transaction problem anyway.
>>>>>>
>>>>>> Chris
>>>>>>
>>>>>> On Tue, Apr 17, 2012 at 1:47 AM, Raul Kripalani <raul@fusesource.com>
>>>>>> wrote:
>>>>>>
>>>>>>> Hi Chris!
>>>>>>>
>>>>>>> Transaction Managers bind transactions to threads, and a possible
>>> cause
>>>>>> for
>>>>>>> your transaction getting lost is that your route is being called
>>>>>>> asynchronously from another thread.
>>>>>>>
>>>>>>> This is because you are using ProducerTemplate.send...().
>>>>>>>
>>>>>>> Can you replace this with ProducerTemplate.requestBodyAndHeader(...),
>>>>>> which
>>>>>>> in theory should call the route synchronously in the same thread?
>>>>>>>
>>>>>>> Regards,
>>>>>>>
>>>>>>> *Raúl Kripalani*
>>>>>>> Principal Consultant | FuseSource Corp.
>>>>>>> raul@fusesource.com | fusesource.com <http://www.fusesource.com/>
>>>>> skype:
>>>>>>> raul.fuse | twitter: @raulvk <http://twitter.com/raulvk>,
>>>>>>> @fusenews<http://twitter.com/fusenews>
>>>>>>>
>>>>>>> <http://twitter.com/fusenews>
>>>>>>>
>>>>>>> On 16 April 2012 23:09, Chris Geer <chris@cxtsoftware.com>
wrote:
>>>>>>>
>>>>>>>> Claus,
>>>>>>>>
>>>>>>>> I'm still struggling with this so I've put together a quick
sample
>>>>>>> project
>>>>>>>> that shows the problem. It consists of an OSGI component
that runs
>>>>>> under
>>>>>>> a
>>>>>>>> transaction and posts two JMS messages (one with Camel and
one with
>>>>> JMS
>>>>>>>> APIs) then rolls back the transactions. I would hope to see
both
>>>>>> messages
>>>>>>>> not be delivered but instead what I see if the one sent via
camel
>>>>> being
>>>>>>>> delivered while the other one is rolled back. I'm sure I'm
probably
>>>>>> doing
>>>>>>>> something wrong but I can't figure it out.
>>>>>>>>
>>>>>>>> Is there a place I can post my sample project where someone
might be
>>>>>> able
>>>>>>>> to give it a quick look?
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> Chris
>>>>>>>>
>>>>>>>> On Sat, Apr 7, 2012 at 3:19 AM, Claus Ibsen <claus.ibsen@gmail.com>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>>> On Thu, Apr 5, 2012 at 5:57 PM, Chris Geer <chris@cxtsoftware.com>
>>>>>>>> wrote:
>>>>>>>>>> Claus,
>>>>>>>>>>
>>>>>>>>>> I realize that but I can't explain what I'm seeing.
Here is an
>>>>>>>> additional
>>>>>>>>>> piece of info, here is debug log for the sending
of the message.
>>>>> As
>>>>>>> you
>>>>>>>>> can
>>>>>>>>>> see, the transaction fields are all null but I don't
know if that
>>>>>> is
>>>>>>>>> normal
>>>>>>>>>> or a symptom of the problem.
>>>>>>>>>>
>>>>>>>>>> 08:51:22,906 | DEBUG | erations/address | JmsConfiguration
>>>>>>>>>> | 169 - org.apache.camel.camel-jms - 2.9.2.SNAPSHOT
| Sending JMS
>>>>>>>> message
>>>>>>>>>> to: topic://event-notifications with message:
>>>>> ActiveMQBytesMessage
>>>>>>>>>> {commandId = 0, responseRequired = false, messageId
= null,
>>>>>>>>>> originalDestination = null, originalTransactionId
= null,
>>>>>> producerId
>>>>>>> =
>>>>>>>>>> null, destination = null, transactionId = null, expiration
= 0,
>>>>>>>>> timestamp =
>>>>>>>>>> 0, arrival = 0, brokerInTime = 0, brokerOutTime =
0,
>>>>> correlationId
>>>>>> =
>>>>>>>>> null,
>>>>>>>>>> replyTo = null, persistent = true, type = null, priority
= 0,
>>>>>>> groupID =
>>>>>>>>>> null, groupSequence = 0, targetConsumerId = null,
compressed =
>>>>>> false,
>>>>>>>>>> userID = null, content = null, marshalledProperties
= null,
>>>>>>>>> dataStructure =
>>>>>>>>>> null, redeliveryCounter = 0, size = 0, properties
=
>>>>>>>> {EntityType=Address,
>>>>>>>>>> breadcrumbId=ID-CXTMBP-Chris-local-62052-1333577461603-22-3,
>>>>>>>>>> EventType=EntityCreated, ClientID=0}, readOnlyProperties
= false,
>>>>>>>>>> readOnlyBody = false, droppable = false} ActiveMQBytesMessage{
>>>>>>>> bytesOut =
>>>>>>>>>> org.apache.activemq.util.ByteArrayOutputStream@51762faf,
>>>>> dataOut =
>>>>>>>>>> java.io.DataOutputStream@2634b3f1, dataIn = null
}
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> I would only suspect transaction ids being populated
in the AMQ
>>>>>>>>> message if the message originated from the AMQ broker.
Creating a
>>>>> new
>>>>>>>>> message to be send would most likely not populate TX
ids and
>>>>> whatnot.
>>>>>>>>> But the work is still carried out under the TX manager.
(if TX is
>>>>>>>>> properly configured and working - yeah thats the hard
part).
>>>>>>>>>
>>>>>>>>>> Here is more of the stack trace that shows the transaction
being
>>>>>>>>> committed
>>>>>>>>>> for some reason.
>>>>>>>>>>
>>>>>>>>>> 08:51:22,888 | DEBUG | erations/address | TransactionErrorHandler
>>>>>>>>>> | 166 - org.apache.camel.camel-core - 2.9.2.SNAPSHOT
|
>>>>> Transaction
>>>>>>>> begin
>>>>>>>>>> (0x1f2198ab) redelivered(unknown) for (MessageId:
>>>>>>>>>> ID-CXTMBP-Chris-local-62052-1333577461603-22-3 on
ExchangeId:
>>>>>>>>>> ID-CXTMBP-Chris-local-62052-1333577461603-22-4))
>>>>>>>>>> 08:51:22,888 | DEBUG | erations/address | JtaTransactionManager
>>>>>>>>>> | 139 - org.springframework.transaction - 3.0.6.RELEASE
|
>>>>>>>> Participating
>>>>>>>>> in
>>>>>>>>>> existing transaction
>>>>>>>>>> 08:51:22,906 | DEBUG | erations/address | JmsConfiguration
>>>>>>>>>> | 169 - org.apache.camel.camel-jms - 2.9.2.SNAPSHOT
| Sending JMS
>>>>>>>> message
>>>>>>>>>> to: topic://event-notifications with message:
>>>>> ActiveMQBytesMessage
>>>>>>>>>> {commandId = 0, responseRequired = false, messageId
= null,
>>>>>>>>>> originalDestination = null, originalTransactionId
= null,
>>>>>> producerId
>>>>>>> =
>>>>>>>>>> null, destination = null, transactionId = null, expiration
= 0,
>>>>>>>>> timestamp =
>>>>>>>>>> 0, arrival = 0, brokerInTime = 0, brokerOutTime =
0,
>>>>> correlationId
>>>>>> =
>>>>>>>>> null,
>>>>>>>>>> replyTo = null, persistent = true, type = null, priority
= 0,
>>>>>>> groupID =
>>>>>>>>>> null, groupSequence = 0, targetConsumerId = null,
compressed =
>>>>>> false,
>>>>>>>>>> userID = null, content = null, marshalledProperties
= null,
>>>>>>>>> dataStructure =
>>>>>>>>>> null, redeliveryCounter = 0, size = 0, properties
=
>>>>>>>> {EntityType=Address,
>>>>>>>>>> breadcrumbId=ID-CXTMBP-Chris-local-62052-1333577461603-22-3,
>>>>>>>>>> EventType=EntityCreated, ClientID=0}, readOnlyProperties
= false,
>>>>>>>>>> readOnlyBody = false, droppable = false} ActiveMQBytesMessage{
>>>>>>>> bytesOut =
>>>>>>>>>> org.apache.activemq.util.ByteArrayOutputStream@51762faf,
>>>>> dataOut =
>>>>>>>>>> java.io.DataOutputStream@2634b3f1, dataIn = null
}
>>>>>>>>>> 08:51:22,907 | DEBUG | erations/address | JtaTransactionManager
>>>>>>>>>> | 139 - org.springframework.transaction - 3.0.6.RELEASE
|
>>>>>>> Registering
>>>>>>>>>> after-completion synchronization with existing JTA
transaction
>>>>>>>>>> 08:51:22,907 | DEBUG | erations/address | TransactionErrorHandler
>>>>>>>>>> | 166 - org.apache.camel.camel-core - 2.9.2.SNAPSHOT
|
>>>>> Transaction
>>>>>>>>> commit
>>>>>>>>>> (0x1f2198ab) redelivered(unknown) for (MessageId:
>>>>>>>>>> ID-CXTMBP-Chris-local-62052-1333577461603-22-3 on
ExchangeId:
>>>>>>>>>> ID-CXTMBP-Chris-local-62052-1333577461603-22-4))
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> That last debug logging is just Camel saying that the
TX completed
>>>>>>>>> successfully (in that leg). Its up to the TX manager
when actually
>>>>> to
>>>>>>>>> commit the TX. If a TX was started outside, then the
commit is
>>>>>>>>> executed at that point.
>>>>>>>>>
>>>>>>>>> So this is normal.
>>>>>>>>>
>>>>>>>>>> On Thu, Apr 5, 2012 at 8:19 AM, Claus Ibsen <
>>>>> claus.ibsen@gmail.com
>>>>>>>
>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>>> On Thu, Apr 5, 2012 at 4:59 PM, Chris Geer <
>>>>> chris@cxtsoftware.com
>>>>>>>
>>>>>>>>> wrote:
>>>>>>>>>>>> Christian,
>>>>>>>>>>>>
>>>>>>>>>>>> I have that book and that is what I used
for a lot of my
>>>>>>> reference.
>>>>>>>> In
>>>>>>>>>>>> fact, they only major difference between
his source and mine
>>>>> is
>>>>>> he
>>>>>>>> is
>>>>>>>>>>> using
>>>>>>>>>>>> Atomikos as the transaction manager and I'm
using aries. I am
>>>>>>>>> referencing
>>>>>>>>>>>> an existing PlatformTransactionManager instead
of creating a
>>>>>>>>>>>> JtaTransactionManager but PlatformTransactionManager
>>>>> implements
>>>>>>>>>>>> JtaTransactionManager so it should be ok.
>>>>>>>>>>>>
>>>>>>>>>>>> As for the datasource, I'm actually publishing
it from another
>>>>>>> OSGI
>>>>>>>>>>>> component as a service so it can be reused.
I'm creating it in
>>>>>>> code
>>>>>>>>> right
>>>>>>>>>>>> now as defined below.
>>>>>>>>>>>>
>>>>>>>>>>>>     BasicManagedDataSource ds = new
>>>>> BasicManagedDataSource();
>>>>>>>>>>>>
>>>>>>>>>>>>     if(xaDataSourceClass != null &&
>>>>>>>> !xaDataSourceClass.isEmpty()) {
>>>>>>>>>>>>         try {
>>>>>>>>>>>>             XADataSource dsi =
>>>>>>>>>>>> (XADataSource)Class.forName(xaDataSourceClass).newInstance();
>>>>>>>>>>>>             Method setUrl =
>>>>>> dsi.getClass().getMethod("setUrl",
>>>>>>>> new
>>>>>>>>>>>> Class[] {String.class});
>>>>>>>>>>>>             setUrl.invoke(dsi, (String)
>>>>>>> config.get(CONNSTR_KEY));
>>>>>>>>>>>>             ds.setXADataSource(xaDataSourceClass);
>>>>>>>>>>>>             ds.setXaDataSourceInstance(dsi);
>>>>>>>>>>>>         } catch (IllegalArgumentException
ex) {
>>>>>>>>>>>>             throw new
>>>>>>> ConfigurationException("xaDataSourceClass",
>>>>>>>>>>>> "Couldn't create instance", ex);
>>>>>>>>>>>>         } catch (InvocationTargetException
ex) {
>>>>>>>>>>>>             throw new
>>>>>>> ConfigurationException("xaDataSourceClass",
>>>>>>>>>>>> "Couldn't create instance", ex);
>>>>>>>>>>>>         } catch (NoSuchMethodException ex)
{
>>>>>>>>>>>>             throw new
>>>>>>> ConfigurationException("xaDataSourceClass",
>>>>>>>>>>>> "Couldn't create instance", ex);
>>>>>>>>>>>>         } catch (SecurityException ex) {
>>>>>>>>>>>>             throw new
>>>>>>> ConfigurationException("xaDataSourceClass",
>>>>>>>>>>>> "Couldn't create instance", ex);
>>>>>>>>>>>>         } catch (InstantiationException ex)
{
>>>>>>>>>>>>             throw new
>>>>>>> ConfigurationException("xaDataSourceClass",
>>>>>>>>>>>> "Couldn't create instance", ex);
>>>>>>>>>>>>         } catch (IllegalAccessException ex)
{
>>>>>>>>>>>>             throw new
>>>>>>> ConfigurationException("xaDataSourceClass",
>>>>>>>>>>>> "Couldn't create instance", ex);
>>>>>>>>>>>>         } catch (ClassNotFoundException ex)
{
>>>>>>>>>>>>             throw new
>>>>>>> ConfigurationException("xaDataSourceClass",
>>>>>>>>>>>> "Class not found", ex);
>>>>>>>>>>>>         }
>>>>>>>>>>>>     } else {
>>>>>>>>>>>>         ds.setDriverClassName((String)
>>>>>> config.get(DRIVER_KEY));
>>>>>>>>>>>>         ds.setUrl((String) config.get(CONNSTR_KEY));
>>>>>>>>>>>>     }
>>>>>>>>>>>>
>>>>>>>>>>>>     BundleContext context =
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>> FrameworkUtil.getBundle(BedrockConnectionPoolFactory.class).getBundleContext();
>>>>>>>>>>>>
>>>>>>>>>>>>     ds.setTransactionManager(transMgr);
>>>>>>>>>>>>
>>>>>>>>>>>>     Hashtable<String, String> sp =
new Hashtable<String,
>>>>>>>> String>();
>>>>>>>>>>>>     sp.put(DSNAME_KEY, (String) config.get(DSNAME_KEY));
>>>>>>>>>>>>     ServiceRegistration reg =
>>>>>>>>>>>> context.registerService("javax.sql.XADataSource",
>>>>>>>>>>>> ds.getXaDataSourceInstance(), sp);
>>>>>>>>>>>>     regMap.put(id, reg);
>>>>>>>>>>>>
>>>>>>>>>>>> The transMgr variable above is looking up
the Aries
>>>>> transaction
>>>>>>>>> manager
>>>>>>>>>>>> deployed in SMX (same one my JMS code is
getting through the
>>>>>>>>>>>> PlatformTransactionManager interface).
>>>>>>>>>>>>
>>>>>>>>>>>> The biggest challenge I've had is that every
single camel
>>>>>>>> transaction
>>>>>>>>>>>> example I've seen starts the transaction
INSIDE camel. They
>>>>> all
>>>>>>>>> resemble
>>>>>>>>>>>> the diagram on page 300 of Claus' book. I
haven't seen any
>>>>>> example
>>>>>>>>> where
>>>>>>>>>>>> camel is enlisted in an already existing
transaction. I was
>>>>>> hoping
>>>>>>>>> that
>>>>>>>>>>> was
>>>>>>>>>>>> just because examples are traditionally simple
but maybe it
>>>>>> wasn't
>>>>>>>>>>> designed
>>>>>>>>>>>> to do that?
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Camel does not have its own TX manager etc. All
we do is to hook
>>>>>>> into
>>>>>>>>>>> the Spring TX manager.
>>>>>>>>>>> So if there is already a TX in progress, then
Camel should just
>>>>>> play
>>>>>>>>>>> along, and run in that same TX.
>>>>>>>>>>>
>>>>>>>>>>> The Camel processing occurs in a Spring TX template
in its -
>>>>>>>>>>> doInTransaction method. That happens when you
use the
>>>>> <transacted>
>>>>>>> in
>>>>>>>>>>> the Route.
>>>>>>>>>>>
>>>>>>>>>>>> Chris
>>>>>>>>>>>>
>>>>>>>>>>>> On Thu, Apr 5, 2012 at 1:11 AM, Christian
Müller <
>>>>>>>>>>>> christian.mueller@gmail.com> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>> Chris,
>>>>>>>>>>>>> may be the source code of Claus book
"Camel in Action" is
>>>>>> helpful
>>>>>>>> for
>>>>>>>>>>> you
>>>>>>>>>>>>> [1].
>>>>>>>>>>>>>
>>>>>>>>>>>>> Could you als share your datasource configuration
with us? It
>>>>>> was
>>>>>>>>> not in
>>>>>>>>>>>>> your post...
>>>>>>>>>>>>>
>>>>>>>>>>>>> [1]
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>> http://code.google.com/p/camelinaction/source/browse/trunk/chapter9/xa/src/test/resources/spring-context.xml
>>>>>>>>>>>>>
>>>>>>>>>>>>> Best,
>>>>>>>>>>>>> Christian
>>>>>>>>>>>>>
>>>>>>>>>>>>> On Thu, Apr 5, 2012 at 7:13 AM, Chris
Geer <
>>>>>>> chris@cxtsoftware.com>
>>>>>>>>>>> wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>>> We are building an application using
ServiceMix (CXF,
>>>>> Camel,
>>>>>>>>> Karaf...)
>>>>>>>>>>>>> and
>>>>>>>>>>>>>> we've run into an issue with transactions
not propagating
>>>>> to
>>>>>>>> camel
>>>>>>>>>>> routes
>>>>>>>>>>>>>> as we'd like them to. We have several
OSGI components that
>>>>>> run
>>>>>>>>> under
>>>>>>>>>>>>>> transactions using the Aries transaction
management like
>>>>> the
>>>>>>>>>>> following:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>  <bean id="serviceBean" class="<class>">
>>>>>>>>>>>>>>     <property name="dataSource"
ref="ds"/>
>>>>>>>>>>>>>>     <property name="camelContext"
ref="camelCtx"/>
>>>>>>>>>>>>>>     <tx:transaction method="updateAddress,
>>>>> createAddress,
>>>>>>>>>>>>>> deleteAddress" value="Required" />
>>>>>>>>>>>>>>     <tx:transaction method="getAddress,
findAddresses"
>>>>>>>>>>>>> value="Supports"
>>>>>>>>>>>>>> />
>>>>>>>>>>>>>> </bean>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> We have published a DataSource which
is transaction aware
>>>>> for
>>>>>>> our
>>>>>>>>>>>>>> components to use. It shows up in
SMX as the following:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> aries.xa.aware = true
>>>>>>>>>>>>>> dsName = ds
>>>>>>>>>>>>>> objectClass = javax.sql.DataSource
>>>>>>>>>>>>>> service.id = 298
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> In our components we are able to
perform database
>>>>>> transactions
>>>>>>>> that
>>>>>>>>>>>>>> successfully get committed/rolled
back as expected without
>>>>>>> having
>>>>>>>>> to
>>>>>>>>>>>>>> manually enlist the JDBC connection.
It works great. Those
>>>>>> same
>>>>>>>>>>>>> components
>>>>>>>>>>>>>> also will send various JMS messages
as they succeed/fail.
>>>>> Our
>>>>>>>> goal
>>>>>>>>> is
>>>>>>>>>>>>> that
>>>>>>>>>>>>>> if a component sends a JMS message
on success and later
>>>>> rolls
>>>>>>>> back
>>>>>>>>> the
>>>>>>>>>>>>> JMS
>>>>>>>>>>>>>> message would be retracted. If we
lookup a JMS
>>>>>>> ConnectionFactory,
>>>>>>>>>>> create
>>>>>>>>>>>>> a
>>>>>>>>>>>>>> connection, session, manually enlist
the session into the
>>>>>>> current
>>>>>>>>>>>>>> transaction and send the message
all in code it actually
>>>>>> works
>>>>>>> as
>>>>>>>>>>>>> desired.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> What we hope to be able to do however
is to remove the code
>>>>>> and
>>>>>>>> use
>>>>>>>>>>> camel
>>>>>>>>>>>>>> instead to process the message and
pass it along to the JMS
>>>>>>>> topic,
>>>>>>>>> in
>>>>>>>>>>> the
>>>>>>>>>>>>>> same transaction that the OSGI component
is running in but
>>>>> we
>>>>>>>> can't
>>>>>>>>>>> quite
>>>>>>>>>>>>>> get it to work. Below is our latest
configuration and code
>>>>>> and
>>>>>>> at
>>>>>>>>> this
>>>>>>>>>>>>>> point the message posts to the topic
but never rolls back.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Blueprint File
>>>>>>>>>>>>>> <bean id="activemq"
>>>>>>>>>>>>>>
>>>>>> class="org.apache.activemq.camel.component.ActiveMQComponent">
>>>>>>>>>>>>>>     <property name="connectionFactory"
>>>>>>>>>>> ref="jmsXaConnectionFactory"/>
>>>>>>>>>>>>>>     <property name="transacted"
value="true"/>
>>>>>>>>>>>>>>     <property name="transactionManager"
>>>>>>>>>>> ref="jmsTransactionManager"/>
>>>>>>>>>>>>>> </bean>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> <bean id="mandatory"
>>>>>>>>>>>>>>
>>>>> class="org.apache.camel.spring.spi.SpringTransactionPolicy">
>>>>>>>>>>>>>>     <property name="transactionManager"
>>>>>>>>>>> ref="jmsTransactionManager"/>
>>>>>>>>>>>>>>     <property name="propagationBehaviorName"
>>>>>>>>>>>>>> value="PROPAGATION_MANDATORY"/>
>>>>>>>>>>>>>> </bean>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> <bean id="jmsXaConnectionFactory"
>>>>>>>>>>>>>>
>>>>>>> class="org.apache.activemq.ActiveMQXAConnectionFactory">
>>>>>>>>>>>>>>     <property name="brokerURL"
>>>>>>> value="tcp://localhost:61616"/>
>>>>>>>>>>>>>> </bean>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> <reference id="jmsTransactionManager"
>>>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>
>>>>>>
>>> interface="org.springframework.transaction.PlatformTransactionManager"/>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> <camel:camelContext id="camelCtx"
trace="true">
>>>>>>>>>>>>>>     <camel:route>
>>>>>>>>>>>>>>         <camel:from uri="direct:genEvent"/>
>>>>>>>>>>>>>>         <camel:wireTap uri="direct:wireTap"/>
>>>>>>>>>>>>>>         <camel:transacted ref="mandatory"/>
>>>>>>>>>>>>>>         <camel:to
>>>>>> uri="activemq:topic:event-notifications"/>
>>>>>>>>>>>>>>     </camel:route>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>     <camel:route>
>>>>>>>>>>>>>>         <camel:from uri="direct:wireTap"/>
>>>>>>>>>>>>>>         <camel:to uri="log:logger?showAll=true"/>
>>>>>>>>>>>>>>     </camel:route>
>>>>>>>>>>>>>> </camel:camelContext>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Code:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>     ProducerTemplate pt =
>>>>>> camelCtx.createProducerTemplate();
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>     Map<String, Object> headers
= new HashMap<String,
>>>>>>>> Object>();
>>>>>>>>>>>>>>     headers.put("EventType", eventType);
>>>>>>>>>>>>>>     headers.put("ClientID", 0);
>>>>>>>>>>>>>>     headers.put("EntityType", "Address");
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>     pt.sendBodyAndHeaders("direct:genEvent",
>>>>>>>>> getAddress(addressID),
>>>>>>>>>>>>>> headers);
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Like I mentioned, the code all works
in the success case
>>>>> but
>>>>>>>>> doesn't
>>>>>>>>>>>>>> rollback the JMS message in the failure
case. Apparently
>>>>> the
>>>>>>>>>>> transaction
>>>>>>>>>>>>>> context isn't being passed on to
the camel route even
>>>>> though
>>>>>>> it's
>>>>>>>>>>> using
>>>>>>>>>>>>> the
>>>>>>>>>>>>>> same transaction manager under the
covers. Is that by
>>>>> design
>>>>>> or
>>>>>>>> is
>>>>>>>>>>> there
>>>>>>>>>>>>> a
>>>>>>>>>>>>>> way to make this scenario work? We'd
really like to be able
>>>>>> use
>>>>>>>> the
>>>>>>>>>>> camel
>>>>>>>>>>>>>> route approach so we can do more
complex things than what I
>>>>>>> show
>>>>>>>>> here.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>> Chris
>>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> --
>>>>>>>>>>> Claus Ibsen
>>>>>>>>>>> -----------------
>>>>>>>>>>> CamelOne 2012 Conference, May 15-16, 2012: http://camelone.com
>>>>>>>>>>> FuseSource
>>>>>>>>>>> Email: cibsen@fusesource.com
>>>>>>>>>>> Web: http://fusesource.com
>>>>>>>>>>> Twitter: davsclaus, fusenews
>>>>>>>>>>> Blog: http://davsclaus.blogspot.com/
>>>>>>>>>>> Author of Camel in Action: http://www.manning.com/ibsen/
>>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> Claus Ibsen
>>>>>>>>> -----------------
>>>>>>>>> CamelOne 2012 Conference, May 15-16, 2012: http://camelone.com
>>>>>>>>> FuseSource
>>>>>>>>> Email: cibsen@fusesource.com
>>>>>>>>> Web: http://fusesource.com
>>>>>>>>> Twitter: davsclaus, fusenews
>>>>>>>>> Blog: http://davsclaus.blogspot.com/
>>>>>>>>> Author of Camel in Action: http://www.manning.com/ibsen/
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>

Mime
View raw message