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
Comments