On Thu, Apr 5, 2012 at 4:59 PM, Chris Geer <ch...@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.muel...@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 <ch...@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: cib...@fusesource.com
Web: http://fusesource.com
Twitter: davsclaus, fusenews
Blog: http://davsclaus.blogspot.com/
Author of Camel in Action: http://www.manning.com/ibsen/

Reply via email to