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.AtomikosTransactionRequiredJMSException:
>> > 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(JmsProducer.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
>>
>>
>

Reply via email to