Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Синхронизировать JMS и JDBC транзакции


Автор: fitdnu2014 12.9.2014, 14:10
Добрый день всем! Хочу использовать ActiveMQ для отправки сообщения в очередь при изменении данных в БД (Sybase). Для управления транзакциями БД в приложении используется Spring DataSourceTransactionManager. Для отправки сообщений в очередь использую JmsTemplate. Проблема заключается в том, что нужно в рамках одной транзакции сделать примерно слюдующие действия:
Шаг 1: апдэйт БД;
Шаг 2: отправка сообщения в очередь;
Шаг 3: апдэйт БД;
Шаг 4: отправка сообщения в очередь.

Если на каком-то этапе возникает исключение - нужно откатить всю транзакцию целиком. Как я понял из документации по JmsTemplate, в моём случае я должен установить параметр "sessionTransacted" = true:
Цитата

Setting this flag to "true" will use a short local JMS transaction when running outside of a managed transaction, and a synchronized local JMS transaction in case of a managed transaction (other than an XA transaction) being present. The latter has the effect of a local JMS transaction being managed alongside the main transaction (which might be a native JDBC transaction), with the JMS transaction committing right after the main transaction.


Конфигурационный файл для JMS содержит только две секции:
Код


<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" ref="url"/>
        <property name="userName" ref="username"/>
        <property name="password" ref="password"/>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="connectionFactory"/>
        <property name="defaultDestinationName" value="SomeQueue"/>
        <property name="sessionTransacted" value="true"/>
</bean>


Решил проверить работоспособность этого, кидая запросы на два простых метода, которые прикрутил к контроллеру:

Код

@Transactional
public void sendMessageTransactionalErr(Object message, List<String> queueDestinationNames) throws Exception {
    sender.sendMessage(message, queueDestinationNames);
    throw new Exception("FatalException!");
}


Код

@Transactional
public void sendMessageTransactionalOK(Object message, List<String> queueDestinationNames) throws Exception {
    sender.sendMessage(message, queueDestinationNames);
}


Но в обоих случаях сообщение попадает в очередь. Даже если возникает исключение (в методе sendMessageTransactionalErr), и происходит роллбэк транзакции JDBC, JMS-ная транзакция всё равно завершается успешно. Что я должен сделать, чтобы заставить эту схему работать так как мне нужно?

Автор: d_k 12.9.2014, 14:35
ну во первых, чекед эксепшин не приведет к откату трензакции, если явно не прописан rollBackFor, а во вторых тут нужны нелокальные а глобальные транзакции, т.е. надо корректно сконфигурить менеджер транзакций, датасорс заменить на XA.
Но! С ActiveMq этого не выйдет, поскольку эта реализация jms не поддерживает глобальные транзакции...

Автор: fitdnu2014 12.9.2014, 16:01
Цитата(d_k @ 12.9.2014,  14:35)
ну во первых, чекед эксепшин не приведет к откату трензакции, если явно не прописан rollBackFor, а во вторых тут нужны нелокальные а глобальные транзакции, т.е. надо корректно сконфигурить менеджер транзакций, датасорс заменить на XA.
Но! С ActiveMq этого не выйдет, поскольку эта реализация jms не поддерживает глобальные транзакции...

Спасибо за наводку, совсем забыл уже, что контролируемые эксепшены не откатывают транзакцию. Удивительно, но после добавления
Код

@Transactional(rollbackFor = Exception.class)

сообщение в очередь не попадает smile

P.S.: Попробую потестировать ещё на более сложных примерах, позже отпишусь о результатах.

Автор: fitdnu2014 15.9.2014, 09:46
Протестировал более сложный вариант - апдэйт БД + отправка сообщения в цикле несколько раз, и затем пробросил исключение - транзакция откатилась и сообщения в очередь не попали. Причём когда закомментировал флаг "sessionTransacted" = true - соощебния попадают в очередь даже при откате транзакции. Так что вопрос можно считать решённым smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)