[ 
https://issues.apache.org/jira/browse/ARTEMIS-2144?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Jonathan Halliday updated ARTEMIS-2144:
---------------------------------------
    Description: 
org.apache.activemq.artemis.ra.inflow.ActiveMQMessageHandler.onMessage calls to 
endpoint.beforeDelivery(ActiveMQActivation.ONMESSAGE) (i.e. Spring framework) 
to begin a Transaction (associating it to the Thread) and enlist the XAResource 
to that Transaction. These operations may fail independently:
{code:java}
// AbstractMessageEndpointFactory.java
public void beginTransaction() throws Exception {
  if (transactionFactory != null && this.xaResource != null) {
    // This line works, associating the tx to the Thread, because that's a 
local operation.
    this.transaction = transactionFactory.createTransaction(transactionName, 
transactionTimeout);
    // This line fails, because it's a remote call to a dead MQ server
    this.transaction.enlistResource(this.xaResource);
  }
}
{code}
{code:java}
# example trace (wildfly application server, artemis 1.5.5)
ERROR [org.apache.activemq.artemis.ra] (Thread-40 
(ActiveMQ-client-global-threads)) AMQ154004: Failed to deliver message: 
javax.resource.spi.ApplicationServerInternalException: Failed to begin 
transaction
 at 
org.springframework.jca.endpoint.AbstractMessageEndpointFactory$AbstractMessageEndpoint.beforeDelivery(AbstractMessageEndpointFactory.java:221)
 at 
org.apache.activemq.artemis.ra.inflow.ActiveMQMessageHandler.onMessage(ActiveMQMessageHandler.java:293)
 at 
org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl.callOnMessage(ClientConsumerImpl.java:1001)
 at 
org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl.access$400(ClientConsumerImpl.java:49)
 at 
org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl$Runner.run(ClientConsumerImpl.java:1124)
 at 
org.apache.activemq.artemis.utils.OrderedExecutorFactory$OrderedExecutor$ExecutorTask.run(OrderedExecutorFactory.java:122)
 at 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
 at 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 at java.lang.Thread.run(Thread.java:745)
Caused by: javax.transaction.SystemException: WFTXN0089: Failed to configure 
transaction timeout of 299
 at 
org.wildfly.transaction.client.LocalTransaction.enlistResource(LocalTransaction.java:155)
 at 
org.springframework.transaction.jta.ManagedTransactionAdapter.enlistResource(ManagedTransactionAdapter.java:83)
 at 
org.springframework.jca.endpoint.AbstractMessageEndpointFactory$TransactionDelegate.beginTransaction(AbstractMessageEndpointFactory.java:313)
 at 
org.springframework.jca.endpoint.AbstractMessageEndpointFactory$AbstractMessageEndpoint.beforeDelivery(AbstractMessageEndpointFactory.java:218)
 ... 8 more

{code}
In such case, it is necessary that ActiveMQMessageHandler ensure termination of 
the transaction before returning control. This can be accomplished by e.g.
|{code:java}
try {
   endpoint.beforeDelivery(ActiveMQActivation.ONMESSAGE);
} catch(ApplicationServerInternalException asie) {
   Throwable cause = asie.getCause();
   if(cause instanceof SystemException) {
      if(tm != null &&  tm.getStatus() != Status.STATUS_NO_TRANSACTION) {
         ActiveMQRALogger.LOGGER.trace("HornetQMessageHandler::tx begin failed 
uncleanly with "+cause.getMessage()+". Trying to clean up.");
         tm.setRollbackOnly();
         endpoint.afterDelivery();
      }
   }
   throw asie;
}
{code}|

Failure to include this cleanup step results in the broken Transaction 
remaining associated to the Thread, which thereafter cannot be reused in a 
pooled environment.

  was:
org.apache.activemq.artemis.ra.inflow.ActiveMQMessageHandler.onMessage calls to 
endpoint.beforeDelivery(ActiveMQActivation.ONMESSAGE) (i.e. Spring framework) 
to begin a Transaction (associating it to the Thread) and enlist the XAResource 
to that Transaction. These operations may fail independently:
{code:java}
// AbstractMessageEndpointFactory.java
public void beginTransaction() throws Exception {
  if (transactionFactory != null && this.xaResource != null) {
    // This line works, associating the tx to the Thread, because that's a 
local operation.
    this.transaction = transactionFactory.createTransaction(transactionName, 
transactionTimeout);
    // This line fails, because it's a remote call to a dead MQ server
    this.transaction.enlistResource(this.xaResource);
  }
}
{code}
{code:java}
# example trace (wildfly application server, artemis 1.5.5)
ERROR [org.apache.activemq.artemis.ra] (Thread-40 
(ActiveMQ-client-global-threads)) AMQ154004: Failed to deliver message: 
javax.resource.spi.ApplicationServerInternalException: Failed to begin 
transaction
 at 
org.springframework.jca.endpoint.AbstractMessageEndpointFactory$AbstractMessageEndpoint.beforeDelivery(AbstractMessageEndpointFactory.java:221)
 at 
org.apache.activemq.artemis.ra.inflow.ActiveMQMessageHandler.onMessage(ActiveMQMessageHandler.java:293)
 at 
org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl.callOnMessage(ClientConsumerImpl.java:1001)
 at 
org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl.access$400(ClientConsumerImpl.java:49)
 at 
org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl$Runner.run(ClientConsumerImpl.java:1124)
 at 
org.apache.activemq.artemis.utils.OrderedExecutorFactory$OrderedExecutor$ExecutorTask.run(OrderedExecutorFactory.java:122)
 at 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
 at 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
 at java.lang.Thread.run(Thread.java:745)
Caused by: javax.transaction.SystemException: WFTXN0089: Failed to configure 
transaction timeout of 299
 at 
org.wildfly.transaction.client.LocalTransaction.enlistResource(LocalTransaction.java:155)
 at 
org.springframework.transaction.jta.ManagedTransactionAdapter.enlistResource(ManagedTransactionAdapter.java:83)
 at 
org.springframework.jca.endpoint.AbstractMessageEndpointFactory$TransactionDelegate.beginTransaction(AbstractMessageEndpointFactory.java:313)
 at 
org.springframework.jca.endpoint.AbstractMessageEndpointFactory$AbstractMessageEndpoint.beforeDelivery(AbstractMessageEndpointFactory.java:218)
 ... 8 more

{code}
In such case, it is necessary that ActiveMQMessageHandler ensure termination of 
the transaction before returning control. This can be accomplished by e.g.
|{code:java}
try {
   endpoint.beforeDelivery(ActiveMQActivation.ONMESSAGE);
} catch(ApplicationServerInternalException asie) {
   Throwable cause = asie.getCause();
   if(cause instanceof SystemException) {
      if(tm.getStatus() != Status.STATUS_NO_TRANSACTION) {
         ActiveMQRALogger.LOGGER.trace("HornetQMessageHandler::tx begin failed 
uncleanly with "+cause.getMessage()+". Trying to clean up.");
         tm.setRollbackOnly();
         endpoint.afterDelivery();
      }
   }
   throw asie;
}
{code}|

Failure to include this cleanup step results in the broken Transaction 
remaining associated to the Thread, which thereafter cannot be reused in a 
pooled environment.


> tx begin failure in ra doesn't get cleaned up
> ---------------------------------------------
>
>                 Key: ARTEMIS-2144
>                 URL: https://issues.apache.org/jira/browse/ARTEMIS-2144
>             Project: ActiveMQ Artemis
>          Issue Type: Bug
>          Components: Broker
>    Affects Versions: 1.5.5, 2.6.3
>            Reporter: Jonathan Halliday
>            Priority: Major
>
> org.apache.activemq.artemis.ra.inflow.ActiveMQMessageHandler.onMessage calls 
> to endpoint.beforeDelivery(ActiveMQActivation.ONMESSAGE) (i.e. Spring 
> framework) to begin a Transaction (associating it to the Thread) and enlist 
> the XAResource to that Transaction. These operations may fail independently:
> {code:java}
> // AbstractMessageEndpointFactory.java
> public void beginTransaction() throws Exception {
>   if (transactionFactory != null && this.xaResource != null) {
>     // This line works, associating the tx to the Thread, because that's a 
> local operation.
>     this.transaction = transactionFactory.createTransaction(transactionName, 
> transactionTimeout);
>     // This line fails, because it's a remote call to a dead MQ server
>     this.transaction.enlistResource(this.xaResource);
>   }
> }
> {code}
> {code:java}
> # example trace (wildfly application server, artemis 1.5.5)
> ERROR [org.apache.activemq.artemis.ra] (Thread-40 
> (ActiveMQ-client-global-threads)) AMQ154004: Failed to deliver message: 
> javax.resource.spi.ApplicationServerInternalException: Failed to begin 
> transaction
>  at 
> org.springframework.jca.endpoint.AbstractMessageEndpointFactory$AbstractMessageEndpoint.beforeDelivery(AbstractMessageEndpointFactory.java:221)
>  at 
> org.apache.activemq.artemis.ra.inflow.ActiveMQMessageHandler.onMessage(ActiveMQMessageHandler.java:293)
>  at 
> org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl.callOnMessage(ClientConsumerImpl.java:1001)
>  at 
> org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl.access$400(ClientConsumerImpl.java:49)
>  at 
> org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl$Runner.run(ClientConsumerImpl.java:1124)
>  at 
> org.apache.activemq.artemis.utils.OrderedExecutorFactory$OrderedExecutor$ExecutorTask.run(OrderedExecutorFactory.java:122)
>  at 
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
>  at 
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
>  at java.lang.Thread.run(Thread.java:745)
> Caused by: javax.transaction.SystemException: WFTXN0089: Failed to configure 
> transaction timeout of 299
>  at 
> org.wildfly.transaction.client.LocalTransaction.enlistResource(LocalTransaction.java:155)
>  at 
> org.springframework.transaction.jta.ManagedTransactionAdapter.enlistResource(ManagedTransactionAdapter.java:83)
>  at 
> org.springframework.jca.endpoint.AbstractMessageEndpointFactory$TransactionDelegate.beginTransaction(AbstractMessageEndpointFactory.java:313)
>  at 
> org.springframework.jca.endpoint.AbstractMessageEndpointFactory$AbstractMessageEndpoint.beforeDelivery(AbstractMessageEndpointFactory.java:218)
>  ... 8 more
> {code}
> In such case, it is necessary that ActiveMQMessageHandler ensure termination 
> of the transaction before returning control. This can be accomplished by e.g.
> |{code:java}
> try {
>    endpoint.beforeDelivery(ActiveMQActivation.ONMESSAGE);
> } catch(ApplicationServerInternalException asie) {
>    Throwable cause = asie.getCause();
>    if(cause instanceof SystemException) {
>       if(tm != null &&  tm.getStatus() != Status.STATUS_NO_TRANSACTION) {
>          ActiveMQRALogger.LOGGER.trace("HornetQMessageHandler::tx begin 
> failed uncleanly with "+cause.getMessage()+". Trying to clean up.");
>          tm.setRollbackOnly();
>          endpoint.afterDelivery();
>       }
>    }
>    throw asie;
> }
> {code}|
> Failure to include this cleanup step results in the broken Transaction 
> remaining associated to the Thread, which thereafter cannot be reused in a 
> pooled environment.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to