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 } 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)) On Thu, Apr 5, 2012 at 8:19 AM, Claus Ibsen <claus.ib...@gmail.com> wrote: > 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/ >