javax.jms.ConnectionFactory和javax.jms.XAConnectionFactory之间的差异

我正在进入JTA的世界,由于需要分布式事务,我不确定javax.jms.ConnectionFactoryjavax.jms.XAConnectionFactory之间的区别,或者更准确地说, javax.jms.ConnectionFactory执行的方式如何?我所期望的只有javax.jms.XAConnectionFactory才能为我做。

细节:我使用Atomikos essentials作为我的事务管理器,我的应用程序在Apache Tomcat 6上运行。

我正在运行一个带有虚拟应用程序的小型POC,我将JMS提供程序( OpenMQ )注册为JNDI资源。

  

奇怪的是,在我的代码中我这样做:

 Context ctx = new InitialContext(); ConnectionFactory queueConnectionFactory = (ConnectionFactory)ctx.lookup("java:comp/env/jms/myQueueFactory"); javax.jms.Connection connection = queueConnectionFactory.createConnection(); Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE); 

稍后在代码中,我在UserTransaction使用此会话,并且它使用CommitRollback两个MessageProducer完美地执行。

我不明白的是,我是如何使用javax.jms.XAConnectionFactory.createConnection()方法的,我得到了一个能完成工作的Session ? 什么是javax.jms.XAConnectionFactory角色?

我还要补充一点,我已经查看了两个类(和javax.jms.BasicConnectionFactory )的源代码,并且我validation了XA类没有覆盖createConnection

ConnectionFactory和XAConnectionFactory之间的区别在于XAConnectionFactory创建了创建XASessions的XAConnections。 XASessions代表了真正的区别,因为(引用JMS JavaDocs 🙂

XASession接口通过添加对JMS提供程序对Java Transaction API(JTA)(可选)的支持的访问来扩展Session的function。 此支持采用javax.transaction.xa.XAResource对象的forms。

换句话说,XASession为XA实例提供了事务感知。 但是,即使对于完全兼容的JMS提供程序,此特定实现也是可选的。 来自相同的JavaDoc:

XAResource提供了一些相当复杂的工具,用于交叉多个事务的工作,恢复正在进行的事务列表等。 JTA感知JMS提供程序必须完全实现此function。 这可以通过使用支持XA的数据库的服务来完成,或者JMS提供者可以选择从头开始实现此function。 应用程序服务器的客户端被赋予它认为是常规JMS会话的内容。 在幕后,应用程序服务器控制底层XASession的事务管理。

换句话说,提供程序可能要求您指定XA或非XA JMS资源,或者,在您的情况下,提供程序可能会透明地使用看似常规的JMS会话执行所有JTA管道。

实际上,您提供的示例代码都不会执行XAfunction。 如果所需要的只是您的消息在同步点下,那么您可以通过单阶段提交(1PC)。 但是,如果您希望,例如,JMS消息和数据库更新发生在单个协调工作单元中,那么您将使用XA的两阶段提交(2PC)。 协调同一传输提供商上的两个消息生成器不需要XA 2PC。

如果您使用的是2PC,那么除了COMMIT和ROLLBACK,您将在代码中的某处调用BEGIN。 你的例子中缺少那个动词就是为什么我说它看起来你没有做2PC。 BEGIN调用将与事务管理器通信,以在参与的资源管理器之间建立事务上下文。 然后COMMIT将导致消息数据库更新在一个工作单元中完成。 这里有趣的是,如果你只有一个参与资源管理器,一些传输将默默地优化你回到1PC。 在这种情况下,它看起来好像你正在做2PC,但真的得到1PC。 由于只有一个资源管理器,因此优化中不会丢失可靠性。

另一方面,如果您正在进行1PC,您将看不到两种类型的连接工厂之间的任何差异。 它会完全展示您描述的行为。

最后一个需要考虑的情况是你使用ConnectionFactory并尝试调用BEGIN。 由于非XA连接工厂无法参与协调的XA事务,因此此调用将失败。