How to Use Out of Process ActiveMQ with WildFly

Version 4

    This document explains how to use an out of process ActiveMQ to send and receive JMS messages inside WildFly Application Server.

     

    Start standalone ActiveMQ

     

    This documentation assumes that ActiveMQ is started as a standalone application and listens on localhost:61616 to send and receive JMS messages.

     

    Setup WildFly module for ActiveMQ RA

     

    ActiveMQ Resource Adaptater (RA) must be included and configured in WildFly application server. There are two ways to do so:

    • include activemq-rar.rar in WildFly deployments directory
    • create a JBoss module containing the RA code.

     

    In this documentation, we will use the second way (create a JBoss module).

     

    Create a JBoss module in $JBOSS_HOME/modules directory that will be name org.apache.activemq.ra:

     

    mkdir  -p $JBOSS_HOME/modules/org/apache/activemq/ra/main/
    
    
    
    
    
    
    

     

    Copy the ActiveMQ RAR in this main directory and unzip it:

     

    cd modules/org/apache/activemq/ra/main/
    wget http://repo1.maven.org/maven2/org/apache/activemq/activemq-rar/5.9.1/activemq-rar-5.9.1.rar
    unzip activemq-rar-5.9.1.rar
    
    
    
    
    
    
    

     

    The RAR archive contains many jars that are required to run ActiveMQ RA.

    It also contains the RA definition in META-INF/ra.xml

     

    Once everything is unzipped, we create a module.xml file in the main directory that contains the module definition:

     

    <?xml version='1.0' encoding='UTF-8'?>
    <module xmlns="urn:jboss:module:1.3" name="org.apache.activemq.ra">
      <resources>
        <resource-root path="."/>
        <resource-root path="activemq-broker-5.9.1.jar"/>
        <resource-root path="activemq-client-5.9.1.jar"/>
        <resource-root path="activemq-jms-pool-5.9.1.jar"/>
        <resource-root path="activemq-kahadb-store-5.9.1.jar"/>
        <resource-root path="activemq-openwire-legacy-5.9.1.jar"/>
        <resource-root path="activemq-pool-5.9.1.jar"/>
        <resource-root path="activemq-protobuf-1.1.jar"/>
        <resource-root path="activemq-ra-5.9.1.jar"/>
        <resource-root path="activemq-spring-5.9.1.jar"/>
        <resource-root path="aopalliance-1.0.jar"/>
        <resource-root path="commons-net-3.3.jar"/>
        <resource-root path="hawtbuf-1.9.jar"/>
        <resource-root path="spring-aop-3.2.5.RELEASE.jar"/>
        <resource-root path="spring-beans-3.2.5.RELEASE.jar"/>
        <resource-root path="spring-context-3.2.5.RELEASE.jar"/>
        <resource-root path="spring-core-3.2.5.RELEASE.jar"/>
        <resource-root path="spring-expression-3.2.5.RELEASE.jar"/>
        <resource-root path="xbean-spring-3.15.jar"/>
      </resources>
      <dependencies>
        <module name="javax.api" slot="main"/>
        <module name="javax.jms.api" slot="main"/>
        <module name="javax.management.j2ee.api" slot="main"/>
        <module name="javax.resource.api" slot="main"/>
        <module name="org.apache.commons.logging"/>
        <module name="org.apache.commons.pool"/>
        <module name="org.apache.log4j"/>
        <module name="org.slf4j"/>
      </dependencies>
    </module>
    
    
    
    
    
    
    

     

    Note that the list of jars may differ depending on ActiveMQ versions.

    There are jars included in ActiveMQ RA that have corresponding JBoss modules. In that case, the jar file was removed from the module directory and a dependency to the JBoss module was added in the module.xml file instead.

    All jars that were inside the activemq-rar.rar must be referenced either as resource-root or module dependency.

     

    JBoss modules allow to modularize the code. We do not recommend adding all jars as <resource-root> in a module but instead to use dependencies to other modules.

            This module example is the simplest way to include the ActiveMQ RA in a module but not the cleanest or most efficient.

            Further work is encourage to remove jars from the module resource and use dependencies instead.

     

    Setup WildFly standalone configuration

     

    Once the org.apache.activemq.ra module has been created, the WildFly standalone configuration must be updated to use the ActiveMQ RA as the default resource adapters for message-driven beans

     

    <?xml version='1.0' encoding='UTF-8'?>
    <server xmlns="urn:jboss:domain:2.1">
    
    
       ...
    
            <subsystem xmlns="urn:jboss:domain:ejb3:2.0">
                <session-bean>
                    <stateful default-access-timeout="5000" cache-ref="simple" passivation-disabled-cache-ref="simple"/>
                    <singleton default-access-timeout="5000"/>
                </session-bean>
                <mdb>
                    <resource-adapter-ref resource-adapter-name="activemq-rar"/>
                    <bean-instance-pool-ref pool-name="mdb-strict-max-pool"/>
                </mdb>
    
               ...
    
            </subsystem>
            ...
    
          
            <subsystem xmlns="urn:jboss:domain:resource-adapters:2.0">
                <resource-adapters>
                    <resource-adapter id="activemq-rar.rar">
                      <module slot="main" id="org.apache.activemq.ra" />
                        <transaction-support>XATransaction</transaction-support>
                        <config-property name="UseInboundSession">
                            false
                        </config-property>
                        <config-property name="Password">
                            defaultPassword
                        </config-property>
                        <config-property name="UserName">
                            defaultUser
                        </config-property>
                        <config-property name="ServerUrl">
                            tcp://localhost:61616?jms.rmIdFromConnectionId=true
                        </config-property>
                        <connection-definitions>
                            <connection-definition class-name="org.apache.activemq.ra.ActiveMQManagedConnectionFactory" jndi-name="java:/ConnectionFactory" enabled="true" pool-name="ConnectionFactory">
                                <xa-pool>
                                    <min-pool-size>1</min-pool-size>
                                    <max-pool-size>20</max-pool-size>
                                    <prefill>false</prefill>
                                    <is-same-rm-override>false</is-same-rm-override>
                                </xa-pool>
                            </connection-definition>
                        </connection-definitions>
                        <admin-objects>
                            <admin-object class-name="org.apache.activemq.command.ActiveMQQueue" jndi-name="java:/queue/HELLOWORLDMDBQueue" use-java-context="true" pool-name="HELLOWORLDMDBQueue">
                                <config-property name="PhysicalName">
                                    HELLOWORLDMDBQueue
                                </config-property>
                            </admin-object>
                            <admin-object class-name="org.apache.activemq.command.ActiveMQTopic" jndi-name="java:/topic/HELLOWORLDMDBTopic" use-java-context="true" pool-name="HELLOWORLDMDBTopic">
                                <config-property name="PhysicalName">
                                    HELLOWORLDMDBTopic
                                </config-property>
                            </admin-object>
                        </admin-objects>
                    </resource-adapter>
                </resource-adapters>
            </subsystem>
           ...
    </server>
    
    
    
    
    
    
    

    The activemq-rar.rar <resource-adapter> is loaded from the module org.apache.activemq.ra.main

     

    Start WildFly

     

    When WildFly is started with this configuration, the ActiveMQ RA is started and the managed JMS objects are deployed and ready to be used:

     

    17:41:18,044 INF

    O  [org.jboss.as.connector.deployment] (MSC service thread 1-14) JBAS010406: Registered connection factory java:/ConnectionFactory
    17:41:18,049 INFO  [org.jboss.as.connector.deployment] (MSC service thread 1-14) JBAS010405: Registered admin object at java:/queue/HELLOWORLDMDBQueue
    17:41:18,052 INFO  [org.jboss.as.connector.deployment] (MSC service thread 1-14) JBAS010405: Registered admin object at java:/topic/HELLOWORLDMDBTopic
    17:41:18,055 INFO  [org.jboss.as.connector.deployers.RaXmlDeployer] (MSC service thread 1-14) IJ020002: Deployed: file:/Users/jmesnil/Developer/wildfly/build/target/wildfly-8.1.0.Final-SNAPSHOT/modules/org/apache/activemq/ra/main/./
    17:41:18,057 INFO  [org.jboss.as.connector.deployment] (MSC service thread 1-11) JBAS010401: Bound JCA AdminObject [java:/topic/HELLOWORLDMDBTopic]
    17:41:18,057 INFO  [org.jboss.as.connector.deployment] (MSC service thread 1-14) JBAS010401: Bound JCA AdminObject [java:/queue/HELLOWORLDMDBQueue]
    17:41:18,057 INFO  [org.jboss.as.connector.deployment] (MSC service thread 1-2) JBAS010401: Bound JCA ConnectionFactory [java:/ConnectionFactory]
    ...
    17:41:19,634 INFO  [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.1.0.Final-SNAPSHOT "Kenny" started in 4037ms - Started 327 of 380 services (90 services are lazy, passive or on-
    
    
    
    
    
    

    Run helloworld-mdb quickstart

     

    With this configuration, WildFly will use the out-of-process ActiveMQ to send and receive messages. This can be tested using the helloworld-mdb quickstart quickstart/helloworld-mdb at master · wildfly/quickstart · GitHub that sends JMS messages to a queue or a topic from a Servlet and has message-driven beans configured to consume them.

     

    Unfortunately, the quickstart can not be run as it because ActiveMQ lags behind Java EE7 at this time (it does not implement JMS 2.0, standard MDB activation property names are not recognized).

    The changes to make to the quickstart are listed at Comparing wildfly:master...jmesnil:helloworld-mdb-activemq-ra · jmesnil/quickstart · GitHub

     

    * change the destinationLookup property name to destination in both MDB

    * remove the @JMSDestinationDefinition from the servlet

    * replace use of JMS 2.0 simplified API by the corresponding JMS 1.1 API

     

    Once these changes are done, the quickstart can be deployed as expected with

     

    mvn clean wildfly:deploy
    
    
    
    
    

     

    and the WildFly logs will show the application is deployed successfully:

     

    17:52:23,746 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-10) JBAS015876: Starting deployment of "wildfly-helloworld-mdb.war" (runtime-name: "wildfly-helloworld-mdb.war")
    ...
    17:52:24,391 INFO  [org.jboss.as.ejb3] (MSC service thread 1-14) JBAS014142: Started message driven bean 'HelloWorldQueueMDB' with 'activemq-rar' resource adapter
    17:52:24,392 INFO  [org.jboss.as.ejb3] (MSC service thread 1-15) JBAS014142: Started message driven bean 'HelloWorldQTopicMDB' with 'activemq-rar' resource adapter
    17:52:24,988 INFO  [stdout] (ServerService Thread Pool -- 13) 2014-04-22 17:52:24,987 [read Pool -- 13] INFO  ActiveMQEndpointWorker         - Starting
    17:52:24,989 INFO  [stdout] (ServerService Thread Pool -- 23) 2014-04-22 17:52:24,987 [read Pool -- 23] INFO  ActiveMQEndpointWorker         - Starting
    17:52:24,996 INFO  [stdout] (default-threads - 1) 2014-04-22 17:52:24,996 [ult-threads - 1] INFO  ActiveMQEndpointWorker         - Establishing connection to broker [tcp://localhost:61616?jms.rmIdFromConnectionId=true]
    17:52:24,997 INFO  [stdout] (default-threads - 2) 2014-04-22 17:52:24,996 [ult-threads - 2] INFO  ActiveMQEndpointWorker         - Establishing connection to broker [tcp://localhost:61616?jms.rmIdFromConnectionId=true]
    17:52:25,100 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-3) JBAS017534: Registered web context: /wildfly-helloworld-mdb
    17:52:25,148 INFO  [org.jboss.as.server] (management-handler-thread - 1) JBAS018559: Deployed "wildfly-helloworld-mdb.war" (runtime-name : "wildfly-helloworld-mdb.war")
    17:52:25,201 INFO  [stdout] (default-threads - 2) 2014-04-22 17:52:25,200 [ult-threads - 2] INFO  ActiveMQEndpointWorker         - Successfully established connection to broker [tcp://localhost:61616?jms.rmIdFromConnectionId=true]
    17:52:25,201 INFO  [stdout] (default-threads - 1) 2014-04-22 17:52:25,200 [ult-threads - 1] INFO  ActiveMQEndpointWorker         - Successfully established connection to broker [tcp://localhost:61616?jms.rmIdFromConnectionId=true]
    
    
    
    
    


    If you go to http://localhost:8080/wildfly-helloworld-mdb/HelloWorldMDBServletClient, the servlet will send 5 JMS messages. The MDB consuming from the queue will receive them and display their text in the application server log:


    17:53:10,356 INFO  [class org.jboss.as.quickstarts.mdb.HelloWorldQueueMDB] (default-threads - 3) Received Message from queue: This is message 1
    17:53:10,356 INFO  [class org.jboss.as.quickstarts.mdb.HelloWorldQueueMDB] (default-threads - 6) Received Message from queue: This is message 4
    17:53:10,356 INFO  [class org.jboss.as.quickstarts.mdb.HelloWorldQueueMDB] (default-threads - 7) Received Message from queue: This is message 5
    17:53:10,356 INFO  [class org.jboss.as.quickstarts.mdb.HelloWorldQueueMDB] (default-threads - 5) Received Message from queue: This is message 3
    17:53:10,356 INFO  [class org.jboss.as.quickstarts.mdb.HelloWorldQueueMDB] (default-threads - 4) Received Message from queue: This is message 2