На JBoss 5.1.0 у меня есть Источник данных (PostgreSQL 8.3.11), настроенный с помощью *-ds.xml (стандарт jboss DS). Это использует XADataSource (PGXADataSource). У меня также есть брокер ActiveMQ (прямо сейчас, это работает как в - VM под JBoss, но это будет на отдельном последнем сервере).
То, что я хочу сделать, должно сделать Фабрику Соединения ActiveMQ и Источник данных для участия в Транзакциях XA. Например, я хочу обновить DB, записывают и отправляют сообщение JMS как UOW. Вы получаете идею.
Я настроил PGXADataSource в my-pg-ds.xml, и он работает (я могу проследить выполнение полностью до метода запуска PGXACONNECTION). Я попытался настроить ActiveMQXAConnectionFactory непосредственно в Spring (я использую Spring 3.0.2. ВЫПУСК), но это не работает, потому что в этом менеджере транзакций Spring случая (я использую аннотацию, чтобы позволить Spring настроить JtaTransactionManager, который просто делегирует всю работу к менеджеру транзакций Jboss) не включает в список XAResource для данного ActiveMQXAConnection. Каждый раз, когда я пытаюсь отправить сообщение, я получаю исключение JMSException, высказывание "XAResource сессии не было включено в список в распределенную транзакцию". брошенный от ActiveMQXASession.
Так как это не работало, я переключился на конфигурацию JCA ActiveMQ ConnectionFactory (на основе этого документа), и это работает на обычный ConnectionFactory, но я не понимаю, как я могу настроить его для использования XAConnectionFactory. Кажется, что Адаптер Ресурса просто не имеет надлежащего ManagedConnectionFactory, ManagedConnection, и т.д. реализаций для фабрики соединения XA.
Я пропускаю что-то, или у меня нет выбора, кроме как записать обертки XA для адаптера ресурса?
Хорошо, я нашел решение. Jboss включает коннектор JCA для любой фабрики JMS (поддерживает оба типа транзакций: XA и локальные). Он находится в /server//deploy/jms-ra.rar. Вот как я это настроил.
Во-первых, файл activemq-jms-ds.xml
, который входит в каталог развертывания рядом с jms-ra.rar:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE connection-factories
PUBLIC "-//JBoss//DTD JBOSS JCA Config 1.5//EN"
"http://www.jboss.org/j2ee/dtd/jboss-ds_1_5.dtd">
<connection-factories>
<mbean code="org.jboss.jms.jndi.JMSProviderLoader"
name="jboss.messaging:service=JMSProviderLoader,name=ActiveMQJMSProvider">
<attribute name="ProviderName">ActiveMQJMSProvider</attribute>
<attribute name="ProviderAdapterClass">org.jboss.jms.jndi.JNDIProviderAdapter</attribute>
<attribute name="FactoryRef">java:/activemq/XAConnectionFactory</attribute>
<attribute name="QueueFactoryRef">java:/activemq/XAConnectionFactory</attribute>
<attribute name="TopicFactoryRef">java:/activemq/XAConnectionFactory</attribute>
</mbean>
<tx-connection-factory>
<jndi-name>JmsXAConnectionFactory</jndi-name>
<xa-transaction/>
<rar-name>jms-ra.rar</rar-name>
<connection-definition>org.jboss.resource.adapter.jms.JmsConnectionFactory</connection-definition>
<config-property name="JmsProviderAdapterJNDI" type="java.lang.String">java:/ActiveMQJMSProvider</config-property>
</tx-connection-factory>
</connection-factories>
Это указывает Jboss заглянуть в jms-ra.rar и найти адаптер, который может предоставить фабрику управляемых соединений для org.jboss.resource.adapter.jms.JmsConnectionFactory
. Внутренне адаптер jms зависит от JmsProviderAdapter, который используется для хранения JNDI-имен фабрик соединений (в моей конфигурации все имена совпадают).
Я использую тег mbean для настройки JMSProviderLoader (он скопирован из одного из внутренних конфигов JBoss). Теперь все, что мне нужно сделать, это каким-то образом создать экземпляр моей фабрики соединений XA и привязать его к java: / activemq / XAConnectionFactory
. Есть несколько способов сделать это (например, реализовать оболочку MBean).
Поскольку я Jboss 5, я использовал микроконтейнер (который, вероятно, будет работать в Jboss 6). Я добавил файл activemq-jms-jboss-beans.xml
в директорию deployers
:
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="urn:jboss:bean-deployer:2.0">
<!-- Define a Jndi binding aspect/annotation that exposes beans via jndi
when they are registered with the kernel.
-->
<aop:lifecycle-configure xmlns:aop="urn:jboss:aop-beans:1.0"
name="DependencyAdvice"
class="org.jboss.aop.microcontainer.aspects.jndi.JndiLifecycleCallback"
classes="@org.jboss.aop.microcontainer.aspects.jndi.JndiBinding"
manager-bean="AspectManager"
manager-property="aspectManager">
</aop:lifecycle-configure>
<bean name="ActiveMQXAConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory">
<annotation>@org.jboss.aop.microcontainer.aspects.jndi.JndiBinding(name="activemq/XAConnectionFactory", aliases={"java:/activemq/XAConnectionFactory"})</annotation>
<property name="brokerURL">vm://localhost</property>
</bean>
</deployment>
Я создаю bean-компонент ActiveMQXAConnectionFactory
. Чтобы привязать его к JNDI, я аннотирую его аннотацией JndiBinding. Чтобы эта аннотация работала, нам нужен JndiLifecycleCallback. Насколько я могу судить, JndiLifecycleCallback вызывается для каждого bean-компонента, созданного микроконтейнером, и проверяет аннотацию JndiBinding для этого bean-компонента.