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

Reply via email to