camel-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Chris Geer <ch...@cxtsoftware.com>
Subject Re: OSGI Transaction Propagation to Camel Route
Date Wed, 18 Apr 2012 16:42:48 GMT
After an upgrade to 5.6-SNAPSHOT everything works as expected. I'm still
curious about my last question though :)

Thank you all for your help.

Chris

On Tue, Apr 17, 2012 at 6:28 PM, Chris Geer <chris@cxtsoftware.com> wrote:

> Thanks Raul, that issue does look like the problem I'm seeing on the
> success case. I'll try and upgrade to 5.6-SNAPSHOT tomorrow and see if that
> resolves the issue.
>
> I now see that I need to have a XA Connection Factory and XA Connection
> Pool for Camel to be able to integrate with a XA transaction. What I don't
> understand is why I'm able to, in code, take a connection from a normal
> connection factory/pool, that is configured with a transaction manager and
> has a ResourceManager associated with it, and enlist it in a XA transaction
> but that same setup won't work with Camel. I'm sure there is a good reason,
> I just don't understand why. Any thoughts?
>
> Here is my normal ActiveMQ setup that works with XA transactions from code.
>
>     <bean id="activemqConnectionFactory"
> class="org.apache.activemq.ActiveMQConnectionFactory">
>         <property name="brokerURL"
> value="vm://default?create=false&amp;waitForStart=10000" />
>     </bean>
>
>     <bean id="pooledConnectionFactory"
> class="org.apache.activemq.pool.PooledConnectionFactory">
>         <property name="maxConnections" value="8" />
>         <property name="connectionFactory" ref="activemqConnectionFactory"
> />
>     </bean>
>
>     <bean id="resourceManager"
> class="org.apache.activemq.pool.ActiveMQResourceManager"
> init-method="recoverResource">
>           <property name="transactionManager" ref="transactionManager" />
>           <property name="connectionFactory"
> ref="activemqConnectionFactory" />
>           <property name="resourceName" value="activemq.default" />
>     </bean>
>
>     <reference id="transactionManager"
> interface="javax.transaction.TransactionManager" />
>
>     <service ref="pooledConnectionFactory"
> interface="javax.jms.ConnectionFactory">
>         <service-properties>
>             <entry key="name" value="localhost"/>
>         </service-properties>
>     </service>
>
> Thanks again for helping me out, I appreciate it,
> Chris
>
>
> On Tue, Apr 17, 2012 at 4:36 PM, Raul Kripalani <raul@fusesource.com>wrote:
>
>> 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
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message