8 votes

Comment configurer le connecteur ActiveMQ JCA dans JBoss pour utiliser les connexions XA ?

Sur JBoss 5.1.0, j'ai une source de données (PostgreSQL 8.3.11) configurée à l'aide de *-ds.xml (DS standard de jboss). Il utilise XADataSource ( PGXADataSource ). J'ai également un courtier ActiveMQ (pour l'instant, il fonctionne en tant que in-VM, sous JBoss, mais il sera plus tard sur un serveur séparé).

Ce que je veux faire, c'est que la Connection Factory et la Datasource d'ActiveMQ participent aux transactions XA. Par exemple, je veux mettre à jour un enregistrement de la base de données et envoyer un message JMS comme un UOW. Vous voyez l'idée.

J'ai configuré PGXADataSource dans mon-pg-ds.xml et cela fonctionne (je peux tracer l'exécution jusqu'à Méthode de démarrage de PGXAConnection ). J'ai essayé de configurer ActiveMQXAConnectionFactory directement dans Spring (j'utilise Spring 3.0.2.RELEASE), mais cela ne fonctionne pas, car dans ce cas, le gestionnaire de transactions de Spring (j'utilise une annotation pour permettre à Spring de configurer l'application JtaTransactionManager qui délègue simplement tout le travail au gestionnaire de transactions de Jboss) ne fait pas appel à XAResource pour les tâches suivantes Connexion ActiveMQXAConnection . Chaque fois que j'essaie d'envoyer un message, j'obtiens une exception JMSException disant "La XAResource de la session n'a pas été enrôlée dans une transaction distribuée. ActiveMQXASession .

Comme cela n'a pas fonctionné, je suis passé à la configuration JCA de la ConnectionFactory d'ActiveMQ (basée sur este ) et cela fonctionne pour les ConnectionFactory mais je ne comprends pas comment je peux le configurer pour utiliser XAConnectionFactory. Il semble que Adaptateur de ressources ne dispose tout simplement pas des implémentations ManagedConnectionFactory, ManagedConnection, etc. appropriées pour l'usine de connexion XA.

Est-ce que je rate quelque chose ou est-ce que je n'ai pas d'autre choix que d'écrire des wrappers XA pour l'adaptateur de ressources ?

7voto

Georgy Bolyuba Points 3932

Ok, j'ai trouvé la solution. Jboss inclut un connecteur JCA pour toute usine JMS (supporte les deux types de transactions : XA et local). Il est situé dans /server//deploy/jms-ra.rar. Voici comment je l'ai configuré.

D'abord, activemq-jms-ds.xml qui va dans le répertoire de déploiement à côté de 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>

Cela indique à Jboss de regarder dans jms-ra.rar et de trouver l'adaptateur qui peut fournir une usine de connexion gérée pour les éléments suivants org.jboss.resource.adapter.jms.JmsConnectionFactory . En interne, l'adaptateur jms dépend de JmsProviderAdapter, qui est utilisé pour stocker les noms JNDI des usines de connexion (dans ma configuration, tous les noms sont les mêmes).

J'utilise le tag mbean pour configurer JMSProviderLoader (il est copié à partir d'une des configurations internes de JBoss). Maintenant, tout ce que j'ai à faire est de créer une instance de ma fabrique de connexions XA et de la lier à java:/activemq/XAConnectionFactory . Il y a plusieurs façons de le faire (implémenter un wrapper MBean, par exemple).

Comme je suis sous Jboss 5, j'ai utilisé microcontainer (qui fonctionnera probablement sous Jboss 6). J'ai ajouté activemq-jms-jboss-beans.xml dans deployers directivité :

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

Je crée un ActiveMQXAConnectionFactory haricot. Pour le lier à JNDI, je l'annote avec l'annotation JndiBinding. Pour que cette annotation fonctionne, nous avons besoin de JndiLifecycleCallback. Pour autant que je puisse dire, JndiLifecycleCallback est appelé sur chaque bean créé par microcontainer et vérifie l'annotation JndiBinding sur ce bean.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X