2010-07-02 15 views
7

En JBoss 5.1.0 tengo Datasource (PostgreSQL 8.3.11) configurado con * -ds.xml (DS estándar jboss). Utiliza XADataSource (PGXADataSource). También tengo el agente de ActiveMQ (ahora se ejecuta como en VM, bajo JBoss, pero estará en un servidor por separado más tarde).¿Cómo configurar el conector ActiveMQ JCA en JBoss para usar conexiones XA?

Lo que quiero hacer es hacer que ActiveMQ Connection Factory y Datasource participen en XA Transactions. Por ejemplo, quiero actualizar el registro de BD y enviar un mensaje JMS como un UOW. Entiendes la idea.

Configuré PGXADataSource en my-pg-ds.xml y funciona (puedo rastrear la ejecución hasta el final en PGXAConnection's start method). He intentado configurar ActiveMQXAConnectionFactory directamente en Spring (estoy usando Spring 3.0.2.RELEASE), pero esto no funciona, porque en este caso Spring transaction manager (uso la anotación para permitir que Spring configure JtaTransactionManager que simplemente delega todo el trabajo en Jboss transaction manager) no alista XAResource para el dado ActiveMQXAConnection. Cada vez que trato de enviar un mensaje recibo una excepción JMSException que dice "XAResource de la sesión no se ha alistado en una transacción distribuida". lanzado desde ActiveMQXASession.

Dado que no funcionó, he cambiado la configuración de la JCA ActiveMQ ConnectionFactory (basado en la this documento) y funciona para regular de , pero no entienden cómo puedo configurarlo para usar XAConnectionFactory. Parece que Resource Adapter simplemente no tiene las implementaciones apropiadas de ManagedConnectionFactory, ManagedConnection, etc. para la fábrica de conexiones XA.

¿Me falta algo o no tengo más remedio que escribir envoltorios XA para el adaptador de recursos?

Respuesta

6

Ok, encontré la solución. Jboss incluye el conector JCA para cualquier fábrica JMS (admite ambos tipos de transacciones: XA y local). Se encuentra en /server//deploy/jms-ra.rar. Así es como lo configuré.

En primer lugar, activemq-jms-ds.xml archivo que entra en directorio de despliegue junto a 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> 

Esto le dice a Jboss mirar en JMS-ra.rar y encontrar adaptador que puede proporcionar la fábrica de conexiones de administración de org.jboss.resource.adapter.jms.JmsConnectionFactory . Internamente el adaptador jms depende de JmsProviderAdapter, que se usa para almacenar los nombres JNDI de las fábricas de conexiones (en mi configuración, todos los nombres son iguales).

Utilizo la etiqueta mbean para configurar JMSProviderLoader (esto se copia de una de las configuraciones internas de JBoss). Ahora, todo lo que tengo que hacer es crear de alguna manera una instancia de mi fábrica de conexiones XA y vincularla al java:/activemq/XAConnectionFactory. Hay varias formas de hacerlo (implementar MBean wrapper, por ejemplo).

Como soy Jboss 5, utilicé microcontainer (que probablemente funcione en Jboss 6). Añadí activemq-jms-jboss-beans.xml archivo en 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> 

creo un grano de ActiveMQXAConnectionFactory. Para enlazarlo a JNDI, lo anoto con la anotación JndiBinding. Para que funcione esta anotación, necesitamos JindLifecycleCallback. Por lo que puedo decir, se llama a JndiLifecycleCallback en cada bean creado por el microcontenedor y comprueba la anotación JndiBinding en ese bean.

Cuestiones relacionadas