Различия между javax.jms.ConnectionFactory и javax.jms.XAConnectionFactory - PullRequest
2 голосов
/ 07 ноября 2010

Я вхожу в мир JTA из-за необходимости распределенных транзакций, и я не уверен относительно различий между javax.jms.ConnectionFactory и javax.jms.XAConnectionFactory или, точнее, как получилось, что javax.jms.ConnectionFactory выполнил то, что ожидал только javax.jms.XAConnectionFactory может сделать для меня.

Подробности: я использую основы Atomikos в качестве менеджера транзакций, и мое приложение работает на 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);

А позже в коде я использую этот сеанс в UserTransaction, и он работает безупречно с двумя MessageProducer с Commit или Rollback.

Чего я не понимаю, так это как получается, что я использую метод javax.jms.XAConnectionFactory.createConnection() и получаю Session, который выполняет эту работу? Какова javax.jms.XAConnectionFactory роль?

Я также добавлю, что я просмотрел исходный код обоих классов (и javax.jms.BasicConnectionFactory) и проверил, что класс XA не переопределяет createConnection.

Ответы [ 2 ]

2 голосов
/ 07 ноября 2010

Основное различие между ConnectionFactory и XAConnectionFactory заключается в том, что XAConnectionFactory создает XAConnections, которые создают XASessions. XASessions представляют реальную разницу, потому что (цитируя JMS JavaDocs :)

Интерфейс XASession расширяет возможности Session, добавляя доступ к поддержке провайдера JMS для Java Transaction API (JTA) (необязательно). Эта поддержка принимает форму объекта javax.transaction.xa.XAResource.

Другими словами, XASession - это то, что дает экземплярам XA их транзакционную осведомленность. Однако эта конкретная реализация является необязательной даже для полностью совместимого поставщика JMS. Из того же JavaDoc:

XAResource предоставляет некоторые довольно сложные средства для чередования работы над несколькими транзакциями, восстановления списка выполняемых транзакций и так далее. Поставщик JMS, осведомленный о JTA, должен полностью реализовать эту функцию. Это можно сделать с помощью служб базы данных, которая поддерживает XA, или поставщик JMS может решить реализовать эту функцию с нуля. Клиент сервера приложений получает то, что он считает обычной сессией JMS. За кулисами сервер приложений контролирует управление транзакциями базового сеанса XASession.

Другими словами, провайдер может потребовать, чтобы вы указали ресурс JA XA или не-XA, или, как может показаться в вашем случае, провайдер может прозрачно выполнить всю работу JTA с помощью того, что выглядит обычная сессия JMS .

1 голос
/ 07 ноября 2010

На самом деле, ни один из приведенных вами примеров кода не будет работать с функциональностью XA.Если все, что требуется, это то, что ваши сообщения находятся под синхронизацией, то вы можете обойтись с 1-фазовой фиксацией (1PC).Однако, если вы хотите, например, чтобы сообщения JMS и обновления БД происходили в одной скоординированной единице работы, вы должны использовать 2-фазную фиксацию (2PC), которая является XA.Координация между двумя производителями сообщений на одном и том же транспортном провайдере не требует XA 2PC.

Если вы использовали 2PC, то в дополнение к COMMIT и ROLLBACK вы бы вызывали BEGIN где-нибудь в коде.Отсутствие этого глагола в вашем примере объясняет, почему я сказал, что вы не делаете 2PC.Вызов BEGIN будет связываться с менеджером транзакций для установления контекста транзакции между участвующими менеджерами ресурсов.Тогда команда COMMIT заставит сообщения и обновления БД завершиться за одну единицу работы.Интересно то, что если у вас есть только один участвующий менеджер ресурсов, некоторые транспорты будут молча оптимизировать вас обратно до 1PC.В этом случае выглядит так, как будто вы делаете 2PC, но на самом деле получаете 1PC.Поскольку имеется только один менеджер ресурсов, в этой оптимизации нет потери надежности.

С другой стороны, если вы делаете 1PC, вы не увидите никакой разницы между двумя типами фабрики соединений.Он будет демонстрировать именно то поведение, которое вы описываете.

Последний случай, который следует рассмотреть, это то, что вы используете ConnectionFactory и пытаетесь вызвать BEGIN.Поскольку фабрика соединений не-XA не может участвовать в скоординированной транзакции XA, этот вызов должен завершиться неудачей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...