2

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

详细信息:我使用 Atomikos Essentials 作为我的事务管理器,并且我的应用程序在 Apache Tomcat 6 上运行。

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

<Resource name="jms/myConnectionFactory" auth="Container"  
 type="com.atomikos.jms.AtomikosConnectionFactoryBean"  
 factory="com.atomikos.tomcat.EnhancedTomcatAtomikosBeanFactory"   
uniqueResourceName="jms/myConnectionFactory"  
xaConnectionFactoryClassName="com.sun.messaging.XAConnectionFactory"  
maxPoolSize="3"/>

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

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);

后来在代码中,我在 a 中使用了这个会话,它在两个带有or 或的 s 中UserTransaction完美地执行。MessageProducerCommitRollback

我不明白的是,我怎么会使用javax.jms.XAConnectionFactory.createConnection()方法并且我得到了一个Session可以完成工作的方法?有什么javax.jms.XAConnectionFactory作用?

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

4

2 回答 2

3

ConnectionFactory 和 XAConnectionFactory 的核心区别在于 XAConnectionFactory 创建 XAConnections,XAConnections 创建 XASessions。XASessions 代表了真正的区别,因为(引用JMS JavaDocs :)

XASession 接口通过添加对 JMS 提供者对 Java Transaction API (JTA) 的支持(可选)的访问来扩展 Session 的功能。这种支持采用 javax.transaction.xa.XAResource 对象的形式。

换句话说,XASession 赋予 XA 实例事务意识。但是,即使对于完全兼容的 JMS 提供程序,此特定实现也是可选的。来自同一个 JavaDoc:

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

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

于 2010-11-07T13:00:25.557 回答
1

实际上,您提供的示例代码都不会使用 XA 功能。如果只需要您的消息处于同步点下,那么您可以使用 1 阶段提交 (1PC)。但是,例如,如果您希望 JMS 消息和 DB 更新发生在一个协调的工作单元中,那么您将使用 XA 的两阶段提交 (2PC)。在同一传输提供者上的两个消息生产者之间进行协调不需要 XA 2PC。

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

另一方面,如果你在做 1PC,你不会看到这两种类型的连接工厂之间有任何区别。它会表现出您所描述的行为。

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

于 2010-11-07T14:29:53.693 回答