Chapter 6. JMS and Message-Driven Beans

One thing that’s missing from the Duke’s Bank application is any use of JMS messaging, so we’ll work through the tutorial example on Message Driven Beans (MDBs) to see how to use messaging in JBoss. We’ll assume you’re already familiar with general JMS and MDB concepts. The J2EE tutorial code for the MDB is in j2eetutorial14/examples/ejb/simplemessage. We’ve supplied a jboss-build.xml file in the simplemessage directory which will allow you to build the example from scratch and run it in JBoss.

The example code is very simple. There are only two classes, one for the client and one for the bean (unlike normal EJBs, MDBs don’t need any interfaces). The client publishes messages to a JMS Queue and the MDB handles them via its standard onMessage method. The messages are all of type javax.jms.TextMessage and the bean simply prints out the text contained in each message.

The only container-specific tasks required are setting up the Queue in JBoss, and configuring the MDB to accept messages from it.

6.1. Building the Example

6.1.1. Compiling and Packaging the MDB and Client

To compile the files, invoke the compile-mdb target from the simplemessage directory.

ant -f jboss-build.xml compile-mdb

Then run the following targets to produce archives for the bean and the client and a combined EAR file in the jar directory.

ant -f jboss-build.xml package-mdb 
ant -f jboss-build.xml package-mdb-client 
ant -f jboss-build.xml assemble-mdb

We’ve retained the same layout we used in the Duke’s Bank build, with a dd directory containing the deployment descriptors and the jar directory containing the archives produced by the build.

6.1.1.1. Specifying the Source Queue for the MDB

As with other container-specific information, the queue name for the MDB is specified in the jboss.xml file:

<jboss> 
    <enterprise-beans> 
        <message-driven> 
            <ejb-name>SimpleMessageBean</ejb-name> 
            <destination-jndi-name>queue/MyQueue</destination-jndi-name> 
        </message-driven> 
    </enterprise-beans> 
</jboss> 

So the MDB will receive messages from the queue with JNDI name queue/MyQueue.

6.2. Deploying and Running the Example

To deploy the MDB, just copy the SimpleMessage.ear file to the JBoss deploy directory. The deploy-mdb target does this.

ant -f jboss-build.xml deploy-mdb

A successful deployment should look something like this:

13:37:06,868 INFO  [EARDeployer] Init J2EE application: file:/private/tmp/jboss-4.0
.1/server/default/deploy/SimpleMessage.ear
13:37:07,845 INFO  [EjbModule] Deploying SimpleMessageEJB
13:37:08,756 WARN  [JMSContainerInvoker] Could not find the queue destination-jndi-
name=queue/MyQueue
13:37:08,850 WARN  [JMSContainerInvoker] destination not found: queue/MyQueue reaso
n: javax.naming.NameNotFoundException: MyQueue not bound
13:37:08,852 WARN  [JMSContainerInvoker] creating a new temporary destination: queu
e/MyQueue
13:37:08,877 INFO  [MyQueue] Bound to JNDI name: queue/MyQueue
13:37:09,192 INFO  [EJBDeployer] Deployed: file:/private/tmp/jboss-4.0.1/server/def
ault/tmp/deploy/tmp29311SimpleMessage.ear-contents/simplemessage.jar
13:37:09,393 INFO  [EARDeployer] Started J2EE application: file:/private/tmp/jboss-
4.0.1/server/default/deploy/SimpleMessage.ear

If you look more closely at this, you will see warnings that the message queue specified in the deployment doesn’t exist. In this case JBoss will create a temporary one for the application and bind it under the supplied name. You can check it exists using the JNDIView MBean again. Look under the global JNDI namespace. We’ll look at how to explicitly create JMS destinations below.

6.2.1. Running the Client

Run the client with the run-mdb Ant target.

ant -f jboss-build.xml run-mdb

You should see output in both the client and server windows as they send and receive the messages respectively.

6.3. Managing JMS Destinations

As with most things in JBoss, JMS Topics and Queues are implemented using MBeans. There are two ways you can create them: you can add MBean declarations to the appropriate configuration file, or you can create them dynamically using the JMX Console. However, if you use the latter method, they won’t survive a server restart.

6.3.1. The jbossmq-destinations-service.xml File

You’ll find this file in the jms directory inside the deploy directory. It contains a list of JMS destinations and sets up a list of test topics and queues which illustrate the syntax used. To add the queue for our example, you would simply add the following MBean declaration to the file.

<mbean code="org.jboss.mq.server.jmx.Queue" 
      name="jboss.mq.destination:service=Queue,name=MyQueue"> 
</mbean> 

6.3.2. Using the DestinationManager from the JMX Console

With JBoss running, bring up the JMX Console in your browser and look for the section labelled jboss.mq in the main agent view. Click on the link which says service=DestinationManager. The DestinationManager MBean is the main JMS service in JBoss and you can use it to create and destroy queues and topics at runtime. Look for the operation called createQueue. This takes two parameters. The first is a name for the Queue MBean (so will not usually be relevant to your application code) and the second is the JNDI name. So enter MyQueue and queue/MyQueue for these respectively. We’ve adopted the standard JBoss convention of binding queues under the JNDI name queue and topics under topic but this isn’t necessary. You can use any name. Note that this will fail if either of these names is already in use (for example if you have deployed the application as above or added a Queue MBean using the XML configuration file. If this is the case you can either remove the existing queue or just try another name.

6.3.3. Administering Destinations

You can access the attributes and operations that the MBeans representing a queue or topic exposes via JMX. Look at the main JMX Console view again and you’ll find a separate jboss.mq.destination section which should contain an entry for our Queue (no matter how it was created). Click on this and you’ll see the attributes for the queue. Amongst these is the QueueDepth which is the number of messages which are currently on the queue.

As an exercise, you can try temporarily stopping the delivery of messages to the MDB. Locate the section called jboss.j2ee in the JMX console and you should find an MBean listed there which is responsible for invoking your MDB. The name will be binding=message-driven-bean, jndiName=local/SimpleMessageEJB, plugin=invoker,service=EJB

You can start and stop the delivery of messages using the corresponding MBean operations which it supports. Invoke the stopDelivery() method, and then run the client a few times. You will see the QueueDepth increase as the messages accumulate. If you re-start message delivery, with the startDelivery() method, you should see all the messages arriving at once.