问题描述
在 JBoss 5.1.0 上,我使用 *-ds.xml(标准 jboss DS)配置了数据源(PostgreSQL 8.3.11).它使用 XADataSource(PGXADataSource).我还有 ActiveMQ 代理(现在它在 JBoss 下作为虚拟机内运行,但后者将在单独的服务器上运行).
On JBoss 5.1.0 I have Datasource (PostgreSQL 8.3.11) configured using *-ds.xml (standard jboss DS). It uses XADataSource (PGXADataSource). I also have ActiveMQ broker (right now it runs as in-VM, under JBoss, but it will be on separate server latter).
我想做的是让ActiveMQ Connection Factory和Datasource参与XA Transactions.例如,我想更新数据库记录并将 JMS 消息作为 UOW 发送.你懂的.
What I want to do is to make ActiveMQ Connection Factory and Datasource to participate in XA Transactions. For example, I want to update DB record and send a JMS message as a UOW. You get the idea.
我在 my-pg-ds.xml 中配置了 PGXADataSource 并且它工作正常(我可以一直跟踪执行到 PGXAConnection 的启动方法).我试图配置 ActiveMQXAConnectionFactory直接在 Spring 中(我使用的是 Spring 3.0.2.RELEASE),但这不起作用,因为在这种情况下 Spring 事务管理器(我使用注解让 Spring 配置 JtaTransactionManager 它只是将所有工作委托给 Jboss 事务管理器)不为给定的 ActiveMQXAConnection.每当我尝试发送消息时,我都会收到异常 JMSException,指出会话的 XAResource 尚未加入分布式事务".从 ActiveMQXASession.
I configured PGXADataSource in my-pg-ds.xml and it works (I can trace execution all the way to PGXAConnection's start method). I have tried to configure ActiveMQXAConnectionFactory directly in Spring (I am using Spring 3.0.2.RELEASE), but this does not work, because in this case Spring transaction manager (I use annotation to let Spring configure JtaTransactionManager which simply delegates all the work to Jboss transaction manager) does not enlist XAResource for given ActiveMQXAConnection. Whenever I try to send a message I get an exception JMSException saying "Session's XAResource has not been enlisted in a distributed transaction." thrown from ActiveMQXASession.
由于那不起作用,我已切换到 ActiveMQ ConnectionFactory 的 JCA 配置(基于 this 文档),它适用于常规 ConnectionFactory,但我不明白如何配置它以使用 XAConnectionFactory.看起来 Resource Adapter 根本没有合适的 ManagedConnectionFactory、ManagedConnection 等 XA 连接工厂的实现.
Since that did not work, I have switched to JCA configuration of ActiveMQ ConnectionFactory (based on this document) and it works for regular ConnectionFactory, but I do not understand how can I configure it to use XAConnectionFactory. It seems like Resource Adapter simply does not have proper ManagedConnectionFactory, ManagedConnection, etc. implementations for XA connection factory.
我是否遗漏了什么,或者我别无选择,只能为资源适配器编写 XA 包装器?
Am I missing something or do I have no choice but to write XA wrappers for resource adapter?
推荐答案
好的,我找到了解决方案.Jboss 包括用于任何 JMS 工厂的 JCA 连接器(支持两种类型的事务:XA 和本地).它位于/server//deploy/jms-ra.rar.这是我配置它的方式.
Ok, I found the solution. Jboss includes JCA connector for any JMS factory (supports both types of transactions: XA and local). It is located in /server//deploy/jms-ra.rar. Here is how I configured it.
首先,进入部署目录下jms-ra.rar旁边的activemq-jms-ds.xml
文件:
First, activemq-jms-ds.xml
file that goes into deploy directory next to 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 名称(在我的配置中所有名称都相同).
This tells Jboss to look into jms-ra.rar and find adapter that can provide managed connection factory for org.jboss.resource.adapter.jms.JmsConnectionFactory
. Internally jms adapter depends on JmsProviderAdapter, which is used to store JNDI names of connection factories (in my config all names are the same).
我使用 mbean 标记来配置 JMSProviderLoader(这是从内部 JBoss 配置之一复制的).现在,我所要做的就是以某种方式创建我的 XA 连接工厂的实例并将其绑定到 java:/activemq/XAConnectionFactory
.有几种方法可以做到(例如,实现 MBean 包装器).
I use mbean tag to configure JMSProviderLoader (this is copied from one of internal JBoss configs). Now, all I have to do is somehow create an instance of my XA connection factory and bind it to java:/activemq/XAConnectionFactory
. There are several ways to do it (implement MBean wrapper, for example).
因为我是 Jboss 5,所以我使用了微容器(它很可能在 Jboss 6 中工作).我将 activemq-jms-jboss-beans.xml
文件添加到 deployers
目录中:
Since I am Jboss 5 I used microcontainer (which is likely to work in Jboss 6). I added activemq-jms-jboss-beans.xml
file into deployers
direcotry:
<?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>
我创建了一个 ActiveMQXAConnectionFactory
bean.为了将其绑定到 JNDI,我使用 JndiBinding 注释对其进行了注释.为了让这个注解起作用,我们需要 JndiLifecycleCallback.据我所知,微容器创建的每个 bean 都会调用 JndiLifecycleCallback,并检查该 bean 上的 JndiBinding 注释.
I create a ActiveMQXAConnectionFactory
bean. To bind it to JNDI, I annotate it with JndiBinding annotation. For this annotation to work, we need JndiLifecycleCallback. As far as I can tell, JndiLifecycleCallback is called on every bean created by microcontainer and checks for JndiBinding annotation on that bean.
这篇关于如何在 JBoss 中配置 ActiveMQ JCA 连接器以使用 XA 连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!