이 콘텐츠는 선택한 언어로 제공되지 않습니다.

7.4. XA Client with Two Connections to a Broker


Overview

A special case arises where an XA client opens two separate connections to the same remote broker instance. You might want to open two connections, for example, in order to send messages to the broker with different properties and qualities of service.
Each XA connection is implicitly associated with its own dedicated XA resource object. When two XA resource objects are equivalent (as determined by calling XAResource.isSameRM), however, many Transaction Managers treat these XA resource objects in a special way: when the current transaction finishes (committed or rolled back), the Transaction Manager calls XAResource.end only on the first enlisted XAResource instance. This creates a problem for Apache ActiveMQ, which expects XAResource.end to be called on every enlisted XAResource instance. To avoid this problem, Apache ActiveMQ provides an option which forces the Transaction Manager to call XAResource.end on every XA resource instance.

jms.rmIdFromConnectionId option

To cope with the scenario where an XA client opens two connections to the same remote broker, it is normally necessary to set the jms.rmIdFromConnectionId option to true. The effect of setting this option to true is that XA resource names are then based on the connection ID, instead of being based on the broker ID. This ensures that all connections have distinct XA resource names, even if they are connected to the same broker instance (note that every connection is associated with its own XA resource object). A side effect of setting this option is that the Transaction Manager is guaranteed to call XAResource.end on each of the XA resource objects.
Note
When you set the jms.rmIdFromConnectionId option to true, the transaction manager adopts the 2-phase commit protocol (2-PC). Hence, there is a significant overhead associated with sending messages on one connection and receiving messages on another, when transactions are enabled.

Setting rmIdFromConnectionId option on an endpoint URI

You can enable the rmIdFromConnectionId option by setting jms.rmIdFromConnectionId to true on an Apache ActiveMQ endpoint URI. For example, to enable this option on an OpenWire URI:
tcp://brokerhost:61616?jms.rmIdFromConnectionId=true
Copy to Clipboard Toggle word wrap

Setting rmIdFromConnectionId option directly on ActiveMQXAConnectionFactory

You can enable the rmIdFromConnectionId option directly on the ActiveMQXAConnectionFactory class, by invoking the setRmIdFromConnectionId method. For example, you can set the rmIdFromConnectionId option in Java, as follows:
// Java
ActiveMQXAConnectionFactory cf = new ActiveMQXAConnectionFactory( ... );
cf.setRmIdFromConnectionId(true);
Copy to Clipboard Toggle word wrap
And you can set the rmIdFromConnectionId option in XML, as follows:
<!--
    ActiveMQ XA Resource Manager
-->
<bean id="resourceManager"
      class="org.apache.activemq.pool.ActiveMQResourceManager"
      init-method="recoverResource">
    <property name="transactionManager" ref="osgiJtaTransactionManager" />
    <property name="connectionFactory" ref="jmsXaPoolConnectionFactory" />
    <property name="resourceName" value="activemq.default" />
    <property name="rmIdFromConnectionId" value="true" />
</bean>
Copy to Clipboard Toggle word wrap

Example using rmIdFromConnectionId

The following example shows you how to use the rmIdFromConnectionId option in the context of an XA aware JMS client written in Java:
// Java
import org.apache.activemq.ActiveMQXAConnectionFactory

import javax.jms.XAConnection;
import javax.jms.XASession;
import javax.jms.XATopicConnection;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
...
ActiveMQXAConnectionFactory cf = new ActiveMQXAConnectionFactory("tcp://brokerhost:61616?jms.rmIdFromConnectionId=true");
... // Configure other connection factory options (not shown)

XAConnection connection1 = (XAConnection)cf.createConnection();
XASession session1 = connection1.createXASession();
XAResource resource1 = session1.getXAResource();

XAConnection connection2 = (XAConnection)cf.createConnection();
XASession session2 = connection2.createXASession();
XAResource resource2 = session2.getXAResource();
...
// Send messages using 'connection1' AND connection2' in this thread
...
// Commit transaction => transaction manager sends xa.end() to BOTH XAResource objects
Copy to Clipboard Toggle word wrap
In this case, the XA transaction proceeds as follows:
  1. Because this is an XA example, it does not show any explicit transaction demarcation (for example, begin or commit invocations). In this case, the XA Transaction Manager (TM) is responsible for transaction demarcation. For example, if you were deploying this code into a container that supports transactions, the container would normally be responsible for transaction demarcation.
  2. When you create the first XAConnection object, connection1, it automatically creates the associated XAResource object for this connection, resource1. The TM automatically enlists resource1 into the current transaction by calling XAResource.start().
  3. When you create the second XAConnection object, connection2, it automatically creates the associated XAResource object for this connection, resource2. The TM automatically joins resource2 to the current transaction: the TM does this by calling XAResource.start() with the TMJOIN flag.
  4. Because you have set rmIdFromConnectionId to true in this example, resource1 and resource2 have different XA resource names, which means that the TM treats them as two different resources.
  5. You can now do some work in the current transaction by sending messages on connection1 and on connection2. All of these message sends belong to the current transaction.
  6. When the current transaction is finished (committed or rolled back), the TM will call XAResource.end() on both resource1 and resource2. This behaviour is guaranteed, because the TM perceives resource1 and resource2 to be different resources (due to different XA resource names).
    Note
    If you have not set the rmIdFromConnectionId option, the typical behaviour of the TM at this point would be to call XAResource.end only on the first resource, resource1. This creates problems in the context of Apache ActiveMQ, because the second connection, connection2, can send messages asynchronously and these asynchronous messages will not be synchronized with the transaction unless the TM calls XAResource.end on resource2 as well.
맨 위로 이동
Red Hat logoGithubredditYoutubeTwitter

자세한 정보

평가판, 구매 및 판매

커뮤니티

Red Hat 문서 정보

Red Hat을 사용하는 고객은 신뢰할 수 있는 콘텐츠가 포함된 제품과 서비스를 통해 혁신하고 목표를 달성할 수 있습니다. 최신 업데이트를 확인하세요.

보다 포괄적 수용을 위한 오픈 소스 용어 교체

Red Hat은 코드, 문서, 웹 속성에서 문제가 있는 언어를 교체하기 위해 최선을 다하고 있습니다. 자세한 내용은 다음을 참조하세요.Red Hat 블로그.

Red Hat 소개

Red Hat은 기업이 핵심 데이터 센터에서 네트워크 에지에 이르기까지 플랫폼과 환경 전반에서 더 쉽게 작업할 수 있도록 강화된 솔루션을 제공합니다.

Theme

© 2025 Red Hat