world what hello example descargar con java java-ee jboss activemq

java - what - ¿Cómo configurar el conector ActiveMQ JCA en JBoss para usar conexiones XA?



jms hello world (1)

En JBoss 5.1.0 tengo Datasource (PostgreSQL 8.3.11) configurado usando * -ds.xml (estándar jboss DS). Utiliza XADataSource ( PGXADataSource ). También tengo el agente de ActiveMQ (ahora mismo se ejecuta como en VM, bajo JBoss, pero estará en un servidor por separado).

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 método de inicio de PGXAConnection ). Intenté configurar ActiveMQXAConnectionFactory directamente en Spring (estoy usando Spring 3.0.2.RELEASE), pero esto no funciona, porque en este caso Spring transaction manager (utilizo la anotación para permitir que Spring configure JtaTransactionManager, que simplemente delega todo el trabajo en Administrador de transacciones Jboss) no alista XAResource para ActiveMQXAConnection dado. 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 .

Como eso no funcionó, cambié a la configuración JCA de ActiveMQ ConnectionFactory (basado en este documento) y funciona para ConnectionFactory normal, pero no entiendo cómo puedo configurarlo para usar XAConnectionFactory. Parece que el Adaptador de recursos simplemente no tiene implementaciones apropiadas de ManagedConnectionFactory, ManagedConnection, etc. para la fábrica de conexiones XA.

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


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é.

Primero, el activemq-jms-ds.xml que va al directorio deploy 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 que mire en jms-ra.rar y encuentre un adaptador que pueda proporcionar una fábrica de conexiones gestionadas para 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).

Yo uso la etiqueta mbean para configurar JMSProviderLoader (esto se copia desde una de las configuraciones internas de JBoss). Ahora, todo lo que tengo que hacer es de alguna manera crear una instancia de mi fábrica de conexiones XA y vincularla a 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). activemq-jms-jboss-beans.xml archivo activemq-jms-jboss-beans.xml al deployers implementadores:

<?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 bean 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.