javax.jms.ConnectionFactory和javax.jms.XAConnectionFactory之间的差异
我正在进入JTA的世界,由于需要分布式事务,我不确定javax.jms.ConnectionFactory
和javax.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
使用此会话,并且它使用Commit
或Rollback
两个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事务,因此此调用将失败。