Scratch that - setting the activeMQConfiguration.setUseSingleConnection(true) causes everything to run in the same thread and the problem still occurs.
On 27 November 2017 at 23:59, Gary Hodgson <gary.s.hodg...@gmail.com> wrote: > Hi > > So after a hiatus I got time to look at this problem again. From delving > into the atomikos code and the trace logs I believe the issue lies in > threading. As shown in the logs below the atomikos jms factory bean > appears to correctly create a composite transaction on the camel > JmsConsumer thread. However the jms session requesting the transaction is > running on the main thread and cannot find it. (The composite transaction > managers appear to be stored in a map keyed by thread). > > I realise this is quite a specific problem which the majority of people > avoid by (sensibly) running camel-cdi and jta in wildfly, but if anyone has > experience or ideas on how to make camel and atomikos find each other here > it would be most appreciated. I'll also have a go with Narayana whether > that yields more success. > > Transaction created on this thread... > > [Camel (camel-1) thread #1 - JmsConsumer[start]] DEBUG > com.atomikos.icatch.imp.CompositeTransactionManagerImp - > createCompositeTransaction ( 10000 ): created new ROOT transaction with id > 10.0.75.1.tm151182109511700001 > [Camel (camel-1) thread #1 - JmsConsumer[start]] DEBUG > com.atomikos.jms.AtomikosConnectionFactoryBean > - AtomikosConnectionFactoryBean 'xamq': createConnection()... > [Camel (camel-1) thread #1 - JmsConsumer[start]] INFO > com.atomikos.jms.AtomikosConnectionFactoryBean > - AtomikosConnectionFactoryBean 'xamq': init... > [Camel (camel-1) thread #1 - JmsConsumer[start]] TRACE > com.atomikos.icatch.imp.CompositeTransactionManagerImp - > getCompositeTransaction() returning instance with id > 10.0.75.1.tm151182109511700001 > [Camel (camel-1) thread #1 - JmsConsumer[start]] TRACE > com.atomikos.datasource.pool.ConnectionPool - atomikos connection pool > 'xamq': about to wait for connection during 30000ms... > [main] TRACE com.atomikos.datasource.xa.session.SessionHandleState - a > SessionHandleState with 0 context(s): notifySessionBorrowed > [main] TRACE com.atomikos.datasource.xa.session.TransactionContext - a > TransactionContext: changing to state com.atomikos.datasource.xa.session. > NotInBranchStateHandler@a826ff8 > [main] DEBUG com.atomikos.jms.AtomikosJmsXaSessionProxy - atomikos xa > session proxy for resource xamq: calling toString on JMS driver session... > [main] TRACE com.atomikos.jms.AtomikosJmsXaSessionProxy - atomikos xa > session proxy for resource xamq: toString returning ActiveMQSession > {id=ID:garyhodgson-PC-57091-1511821093820-1:1:2,started=false} > java.lang.Object@63187d63 > [main] TRACE com.atomikos.jms.AtomikosJmsConnectionProxy - atomikos > connection proxy for resource xamq: returning ActiveMQSession > {id=ID:garyhodgson-PC-57091-1511821093820-1:1:2,started=false} > java.lang.Object@63187d63 > [main] DEBUG com.atomikos.jms.AtomikosJmsXaSessionProxy - atomikos xa > session proxy for resource xamq: calling createQueue on JMS driver > session... > [main] TRACE com.atomikos.jms.AtomikosJmsXaSessionProxy - atomikos xa > session proxy for resource xamq: createQueue returning queue://start > [main] DEBUG com.atomikos.jms.AtomikosJmsXaSessionProxy - atomikos xa > session proxy for resource xamq: calling createProducer on JMS driver > session ActiveMQSession {id=ID:garyhodgson-PC-57091- > 1511821093820-1:1:2,started=false} java.lang.Object@63187d63 > [main] TRACE com.atomikos.jms.AtomikosJmsXaSessionProxy - atomikos xa > session proxy for resource xamq: createProducer returning atomikos > MessageProducer proxy for ActiveMQMessageProducer { > value=ID:garyhodgson-PC-57091-1511821093820-1:1:2:1 } > [main] DEBUG com.atomikos.jms.AtomikosJmsXaSessionProxy - atomikos xa > session proxy for resource xamq: calling createTextMessage on JMS driver > session... > [main] TRACE com.atomikos.jms.AtomikosJmsXaSessionProxy - atomikos xa > session proxy for resource xamq: createTextMessage returning > ActiveMQTextMessage {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 = false, 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 = null, > readOnlyProperties = false, readOnlyBody = false, droppable = false, > jmsXGroupFirstForConsumer = false, text = null} > [main] DEBUG com.atomikos.jms.AtomikosJmsMessageProducerProxy - > atomikos MessageProducer proxy for ActiveMQMessageProducer { > value=ID:garyhodgson-PC-57091-1511821093820-1:1:2:1 }: send ( message )... > > Attempt to get transaction here... > > [main] TRACE com.atomikos.icatch.imp.CompositeTransactionManagerImp - > getCompositeTransaction() returning NULL! > [main] WARN com.atomikos.jms.ConsumerProducerSupport - atomikos > MessageProducer proxy for ActiveMQMessageProducer { > value=ID:garyhodgson-PC-57091-1511821093820-1:1:2:1 }: The JMS session > you are using requires a JTA transaction context for the calling thread and > none was found. > Please correct your code to do one of the following: > 1. start a JTA transaction if you want your JMS operations to be subject > to JTA commit/rollback, or > 2. increase the maxPoolSize of the AtomikosConnectionFactoryBean to > avoid transaction timeout while waiting for a connection, or > 3. create a non-transacted session and do session acknowledgment > yourself, or > 4. set localTransactionMode to true so connection-level commit/rollback > are enabled. > > > Cheers, > Gary > > > On 6 November 2017 at 18:16, Gary Hodgson <gary.s.hodg...@gmail.com> > wrote: > >> Hi Antonin. >> >> Thanks for the response. >> >> I attempted a naive implementation of TransactionServices and it appears >> to load via the serviceloader correctly, and produce UserTransactions: >> https://github.com/garyhodgson/camel-example-cdi-standalone- >> jta/blob/TransactionServices/src/main/java/org/apache/ >> camel/example/cdi/util/TransactionServices.java >> >> Sadly the AtomikosTransactionRequiredJMSException is still thrown. >> >> >> On 6 November 2017 at 11:52, Antonin Stefanutti <anto...@stefanutti.fr> >> wrote: >> >>> Hi Gary, >>> >>> Your CDI producers for the ActiveMQ component and the transaction >>> manager look OK (aside that you would have to destroy the connection >>> factory in a dispose method). >>> >>> However The way you produce the UserTransaction may be problematic. With >>> Weld SE, you would typically implement >>> org.jboss.weld.transaction.spi.TransactionServices >>> and add it as a Weld service before starting the CDI container. >>> >>> Let me know if that helps. >>> >>> Antonin >>> >>> > On 5 Nov 2017, at 21:54, Gary Hodgson <gary.s.hodg...@gmail.com> >>> wrote: >>> > >>> > Hi, >>> > >>> > I am trying to get camel-cdi to work with a standalone JTA provider in >>> a >>> > non-JEE environment. I've made some progress but have a couple of >>> issues >>> > which I am not sure is due to my understanding or the code. >>> > >>> > I created a standalone demo project here to show the issues: >>> > https://github.com/garyhodgson/camel-example-cdi-standalone-jta >>> > >>> > The demo uses Atomikos as the JTA provider and embedded ActiveMQ for >>> JMS. >>> > Running the project with camel:run results in three messages being >>> sent to >>> > the route. The first two are called explicitly in a userTransaction and >>> > behave as expected: the first is processed normally, the second >>> triggers a >>> > rollback (as expected). >>> > >>> > The third message is outside a userTransaction and throws the following >>> > exception from Atomikos: >>> > >>> > Caused by: com.atomikos.jms.AtomikosTrans >>> actionRequiredJMSException: >>> > The JMS session you are using requires a JTA transaction context for >>> the >>> > calling thread and none was found. >>> > Please correct your code to do one of the following: >>> > 1. start a JTA transaction if you want your JMS operations to be >>> > subject to JTA commit/rollback, or >>> > 2. increase the maxPoolSize of the AtomikosConnectionFactoryBean to >>> > avoid transaction timeout while waiting for a connection, or >>> > 3. create a non-transacted session and do session acknowledgment >>> > yourself, or >>> > 4. set localTransactionMode to true so connection-level >>> commit/rollback >>> > are enabled. >>> > at >>> > com.atomikos.jms.AtomikosTransactionRequiredJMSException.thr >>> owAtomikosTransactionRequiredJMSException(AtomikosTransactio >>> nRequiredJMSException.java:23) >>> > ~[transactions-jms-4.0.4.jar:?] >>> > at >>> > com.atomikos.jms.ConsumerProducerSupport.enlist(ConsumerProd >>> ucerSupport.java:90) >>> > ~[transactions-jms-4.0.4.jar:?] >>> > at >>> > com.atomikos.jms.AtomikosJmsMessageProducerProxy.send(Atomik >>> osJmsMessageProducerProxy.java:34) >>> > ~[transactions-jms-4.0.4.jar:?] >>> > at >>> > org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:626) >>> > ~[spring-jms-4.3.11.RELEASE.jar:4.3.11.RELEASE] >>> > at >>> > org.apache.camel.component.jms.JmsConfiguration$CamelJmsTemp >>> late.doSend(JmsConfiguration.java:624) >>> > ~[camel-jms-2.20.0.jar:2.20.0] >>> > at >>> > org.apache.camel.component.jms.JmsConfiguration$CamelJmsTemp >>> late.doSendToDestination(JmsConfiguration.java:563) >>> > ~[camel-jms-2.20.0.jar:2.20.0] >>> > at >>> > org.apache.camel.component.jms.JmsConfiguration$CamelJmsTemp >>> late.access$100(JmsConfiguration.java:505) >>> > ~[camel-jms-2.20.0.jar:2.20.0] >>> > at >>> > org.apache.camel.component.jms.JmsConfiguration$CamelJmsTemp >>> late$1.doInJms(JmsConfiguration.java:519) >>> > ~[camel-jms-2.20.0.jar:2.20.0] >>> > at >>> > org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:484) >>> > ~[spring-jms-4.3.11.RELEASE.jar:4.3.11.RELEASE] >>> > at >>> > org.apache.camel.component.jms.JmsConfiguration$CamelJmsTemp >>> late.send(JmsConfiguration.java:516) >>> > ~[camel-jms-2.20.0.jar:2.20.0] >>> > at >>> > org.apache.camel.component.jms.JmsProducer.doSend(JmsProduce >>> r.java:440) >>> > ~[camel-jms-2.20.0.jar:2.20.0] >>> > at >>> > org.apache.camel.component.jms.JmsProducer.processInOnly(Jms >>> Producer.java:394) >>> > ~[camel-jms-2.20.0.jar:2.20.0] >>> > at >>> > org.apache.camel.component.jms.JmsProducer.process(JmsProduc >>> er.java:157) >>> > ~[camel-jms-2.20.0.jar:2.20.0] >>> > at >>> > org.apache.camel.processor.SharedCamelInternalProcessor.proc >>> ess(SharedCamelInternalProcessor.java:186) >>> > ~[camel-core-2.20.0.jar:2.20.0] >>> > at >>> > org.apache.camel.processor.SharedCamelInternalProcessor.proc >>> ess(SharedCamelInternalProcessor.java:86) >>> > ~[camel-core-2.20.0.jar:2.20.0] >>> > at >>> > org.apache.camel.impl.ProducerCache$1.doInProducer(ProducerC >>> ache.java:541) >>> > ~[camel-core-2.20.0.jar:2.20.0] >>> > at >>> > org.apache.camel.impl.ProducerCache$1.doInProducer(ProducerC >>> ache.java:506) >>> > ~[camel-core-2.20.0.jar:2.20.0] >>> > at >>> > org.apache.camel.impl.ProducerCache.doInProducer(ProducerCac >>> he.java:369) >>> > ~[camel-core-2.20.0.jar:2.20.0] >>> > at >>> > org.apache.camel.impl.ProducerCache.sendExchange(ProducerCac >>> he.java:506) >>> > ~[camel-core-2.20.0.jar:2.20.0] >>> > at org.apache.camel.impl.ProducerCache.send(ProducerCache.java: >>> 229) >>> > ~[camel-core-2.20.0.jar:2.20.0] >>> > at >>> > org.apache.camel.impl.DefaultProducerTemplate.send(DefaultPr >>> oducerTemplate.java:144) >>> > ~[camel-core-2.20.0.jar:2.20.0] >>> > at >>> > org.apache.camel.impl.DefaultProducerTemplate.sendBody(Defau >>> ltProducerTemplate.java:161) >>> > ~[camel-core-2.20.0.jar:2.20.0] >>> > ... 56 more >>> > >>> > >>> > I expected that "transacted()" on the route to have caused a >>> transaction to >>> > be created, and I am not sure why it has not been - other than it >>> having >>> > something to do with this example running outside of a JEE Application >>> > Server. Is my expectation here incorrect? >>> > >>> > I believe the various required beans have been correctly configured as >>> > Producer methods under org.apache.camel.example.cdi.util.CdiProducers >>> > >>> > As an aside: in order to get this working in a Weld SE environment I >>> use a >>> > CDI extension >>> > (org.apache.camel.example.cdi.util.ResourceInjectReplacementExtension) >>> to >>> > add an @Inject annotation to the transactionManager attribute in >>> > org.apache.camel.cdi.transaction.JtaTransactionPolicy. Perhaps it >>> would be >>> > worth considering adding the annotation in camel-cdi to enable it to be >>> > used in a SE environment? (though I don't know if this would adversely >>> > affect the JEE world.) >>> > >>> > >>> > Any insights would be appreciated. >>> > >>> > Cheers, >>> > Gary >>> >>> >> >