Bitronix 事务不适用于 JMS 队列

Bitronix Transaction not working with JMS queue

我有一个 objective 使用 Bitronix 事务,我应该使用两个资源:

  1. 数据库
  2. JMS

我有以下 java 代码:

package com.mycompany.app;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Enumeration;

import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.QueueBrowser;
import javax.jms.QueueReceiver;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.broker.BrokerFactory;
import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.transaction.Transaction;
import org.apache.xbean.spring.context.ClassPathXmlApplicationContext;
import org.springframework.context.ApplicationContext;
import org.springframework.transaction.jta.JtaTransactionManager;

import bitronix.tm.BitronixTransactionManager;
import bitronix.tm.TransactionManagerServices;

public class JMSExample {

    static String serverUrl = "tcp://localhost:61616"; // values changed
    static String userName = "admin";
    static String password = "admin";

    static TextMessage message;

    public static void sendTopicMessage(String topicName, String messageStr) {

        Connection connection = null;

        try {
            BitronixTransactionManager btm = TransactionManagerServices.getTransactionManager();
            btm.begin();
            System.out.println("Publishing to destination '" + topicName + "'\n");
            ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(serverUrl);
            connection = connectionFactory.createConnection();
            Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
            Queue queue = session.createQueue(topicName);
            Message msg = session.createTextMessage(messageStr);
            msg.setJMSCorrelationID("correlationID1");
            MessageProducer producer = session.createProducer(queue);
            producer.send(msg);
            System.out.println("Published message: " + messageStr);
            session.commit();
            session.close();
            connection.close();
            btm.rollback();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        JMSExample.sendTopicMessage("test", "Hi");
    }
}

当我运行上面的程序时,我能够看到队列中的消息。 但我希望 JMS 事务与 Bitronix 事务一起嵌套。换句话说,如果 Bitronix 回滚,队列中也不应该有任何消息。

删除 session.commit() 而 btm.rollback() 完成工作

如果您想在一个事务中以原子方式处理 2 个资源,那么您需要从每个资源管理器(即 JMS 代理和数据库)获取 javax.transaction.xa.XAResource 实现。一旦您拥有了这些,您就可以将它们登记到您使用事务管理器启动的 JTA 事务中。然后任何提交或回滚都将使用登记的 XA 资源自动执行。

要从 JMS 获取 XAResource,请查看 javax.jms.XAConnectionFactory. You can use createXAConnection() to get an instance of javax.jms.XAConnection and then use createXASession() to get an javax.jms.XASession,然后最后使用 getXAResource()

要从 JDBC 获得 XAResource,请查看 javax.sql.XADataSource. You can use getXAConnection() to get an instance of javax.sql.XAConnection,然后使用 getXAResource()

然后您可以使用您的 XAResources 调用 getTransaction() on the transaction manager and use the returned javax.transaction.Transaction to invoke enlistResource()。然后,当您调用 commit()rollback() 时,事务管理器将处理您所有的 XAResource 实现,并确保一切都以原子方式执行。