抛出RuntimeException时,Spring中的XA事务无法正确处理JMS

时间:2014-09-04 21:58:47

标签: java spring spring-jms websphere-liberty

我需要使用IBM Websphere Liberty Core Tx Manager和ActiveMQ作为Broker进行XA事务。 制作人工作得很好,但消费者并没有“回滚”#34;失败后的消息。

消费者被定义为:

<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    <property name="connectionFactory" ref="cachedConnectionFactory"/>
    <property name="destination" ref="queue"/>
    <property name="messageListener" ref="messageListener"/>
    <property name="transactionManager" ref="transactionManager" />
</bean>

Tx定义为:

<tx:jta-transaction-manager />

Connection Factory是ActiveMQXAConnectionFactory的实例。

我的messageListener抛出RuntimeException,这导致在Spring Code中将标志设置为ReadOnly。有趣的部分是在这个Snipped of Spring代码中:

protected boolean receiveAndExecute(Object invoker, Session session, MessageConsumer consumer)
        throws JMSException {

    if (this.transactionManager != null) {
        // Execute receive within transaction.
        TransactionStatus status = this.transactionManager.getTransaction(this.transactionDefinition);
        boolean messageReceived;
        try {
            messageReceived = doReceiveAndExecute(invoker, session, consumer, status);
        }
        catch (JMSException ex) {
            rollbackOnException(status, ex);
            throw ex;
        }
        catch (RuntimeException ex) {
            rollbackOnException(status, ex);
            throw ex;
        }
        catch (Error err) {
            rollbackOnException(status, err);
            throw err;
        }
        this.transactionManager.commit(status);
        return messageReceived;
    }

    else {
        // Execute receive outside of transaction.
        return doReceiveAndExecute(invoker, session, consumer, null);
    }
}

方法doReceiveAndExecute正确调用侦听器,并将Tx标记为rollbackOnly。但是,它会消耗RuntimeException,因为它可以在下面的代码中显示,因此根本不会调用rollbackOnException。

这是在AbstractPollingMessageListenerContainer类中剪切的异常消费者

catch (Throwable ex) {
                if (status != null) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Rolling back transaction because of listener exception thrown: " + ex);
                    }
                    status.setRollbackOnly();
                }
                handleListenerException(ex);
                // Rethrow JMSException to indicate an infrastructure problem
                // that may have to trigger recovery...
                if (ex instanceof JMSException) {
                    throw (JMSException) ex;
                }
            }

我是否遗漏了某些内容,或者是Spring代码或其他地方的错误?我的Spring-jms版本是4.0.5.RELEASE

---更新---

使用Active MQ的XA事务存在很大问题。

我们从Liberty连接到Active MQ(远程)。如果我们在XA模式下使用WLC TX Manager, Active MQ中没有回滚(如果是异常)。

如果我们为 Atomikos Tx经理更改Tx经理,一切正常。 (如果出现问题,我们会回滚,并且消息会保留在队列中......)

因此,与XA连接工厂合作的WLC Tx Manager或WLC Tx Manager可能存在问题... :(嗯,这意味着WLC tx管理器在Spring + WLC + ActiveMQ + XA中有问题堆栈。

我们向IBM提出了一个问题并等待响应。

更新:

    @Bean
    public ConnectionFactory connectionFactory() throws NamingException {
        ActiveMQXAConnectionFactory cf = (ActiveMQXAConnectionFactory) activeMqInitialContext().lookup("XAConnectionFactory");

        RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
        redeliveryPolicy.setInitialRedeliveryDelay(500);
        redeliveryPolicy.setUseExponentialBackOff(true);
        redeliveryPolicy.setMaximumRedeliveries(-1);
        cf.setRedeliveryPolicy(redeliveryPolicy);

        return cf;
    }

    <bean id="cachedConnectionFactory"
            class="org.springframework.jms.connection.CachingConnectionFactory">
        <constructor-arg ref="connectionFactory" />
    </bean>

    <bean id="eStampMessageListener" class="sk.posta.ekolky.oek.jms.EStampMessageListener" />

0 个答案:

没有答案