JBoss JMS configuration

The Java Messaging Service (JMS) has been implemented by means of different providers in the releases 4.x, 5.x and 6.x of JBoss application server. This tutorial explains how to configure and run some JMS destinations using a managed JMS environment (consumer located in JBoss AS) or a standalone JMS application.

The JMS API stands for Java Message Service Application Programming Interface, and it is used by applications to send asynchronous business-quality messages to other applications. In the messaging world, messages are not sent directly to other applications. Instead, messages are sent to destinations, known as queues or topics.

Applications sending messages do not need to worry if the receiving applications are up and running, and conversely, receiving applications do not need to worry about the sending application’s status. Both senders, and receivers only interact with the destinations.

The JMS API is the standardized interface to a JMS provider, sometimes called a Message Oriented Middleware (MOM) system.

In order to run a JMS application on JBoss AS you need to configure:

  • The JMS destionation on JBoss AS
  • The JMS libraries on the client

Configuring JMS destinations on JBoss

Case 1: WildFly 10 (ArtemisMQ)

JBoss AS 7 JMS destinations can be configured either by adding them in the core configuration file (standalone.xml/domain.xml) or via management interfaces such as the CLI :

Via CLI:

Add JMS queue:

jms-queue add --queue-address= jms.queue.ExampleQueue --entries=java:/jms/queue/exampleQueue,java:/jboss/exported/jms/queue/exampleQueue

Add JMS Topic:

jms-topic add --topic-address=jms.topic.ExampleTopic --entries=java:/jms/topic/exampleTopic,java:/jboss/exported/jms/topic/exampleTopic

Please note that the JNDI binding “java:/jboss/exported/jms/[destination]” is only required if you are connecting to your JMS Destination from a remote JMS Client

Via the configuration file:

<subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
    <server name="default">
         . . . .  
        <jms-queue name="jms.queue.ExampleQueue" entries="java:/jms/queue/exampleQueue java:/jboss/exported/jms/queue/exampleQueue"/>
        <jms-topic name="jms.topic.ExampleTopic" entries="java:/jms/topic/exampleTopic java:/jboss/exported/jms/topic/exampleTopic"/>

    </server>
</subsystem>

Case 2: JBoss AS 7 / JBoss EAP 6 (Hornet Q)

JBoss AS 7 JMS destinations can be configured either by adding them in the core configuration file (standalone.xml/domain.xml) or via management interfaces such as the CLI :

Via CLI:

Add JMS queue:

[standalone@localhost:9999 /] jms-queue add  --queue-address=queue1 --entries=queues/queue1

Add JMS Topic:

[standalone@localhost:9999 /] jms-topic add  --topic-address=topic1 --entries=topics/topic1

Via the configuration file:

<subsystem xmlns="urn:jboss:domain:messaging:1.1">

 <hornetq-server>

    . . . . . . . . . . .
    <jms-destinations>
       <jms-queue name="testQueue">
           <entry name="queue/test"/>
       </jms-queue>
       <jms-topic name="testTopic">
           <entry name="topic/test"/>
       </jms-topic>
    </jms-destinations>

 </hornetq-server>
</subsystem>

Case 3: JBoss AS 6 (HornetQ)

HornetQ configuration is located in JBoss 6 in deploy\hornetq.sar. You can add new Topic/Queues by adding them into hornetq-jms.xml file.

<queue name="testQueue">
  <entry name="/queue/queueA"/>
</queue>

<topic name="testTopic">
  <entry name="/topic/topicA"/>
</topic>

Case 4: JBoss AS 5 (JBoss Messaging)
If you are running JBoss 5, which ships with JBoss messaging you can add the following XML (-service.xml) to your deploy folder:

<mbean code="org.jboss.jms.server.destination.QueueService"
 name="jboss.messaging.destination:service=Queue,name=queueA"
 xmbean-dd="xmdesc/Queue-xmbean.xml">
  <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
  <depends>jboss.messaging:service=PostOffice</depends>
</mbean>

<mbean code="org.jboss.jms.server.destination.TopicService"
 name="jboss.messaging.destination:service=Topic,name=topicA"
 xmbean-dd="xmdesc/Topic-xmbean.xml">
  <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
  <depends>jboss.messaging:service=PostOffice</depends>
</mbean>   

Case 5: JBoss AS 4 (JBoss MQ)
If you using JBoss older JMS provider, you can add the following XML (-service.xml) to your deploy folder:

 <mbean code="org.jboss.mq.server.jmx.Queue"
 name="jboss.mq.destination:service=Queue,name=queueA">
  <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>

<mbean code="org.jboss.mq.server.jmx.Topic"
 name="jboss.mq.destination:service=Queue,name=topicA">
  <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>

Configuring JMS client libraries (WildFly):

If you are running a Remote JMS Client, all you need in your Maven pom.xml is including the wildfly-jms-client-bom with the correct version of WildFly in it:

<dependencies>
		<dependency>
			<groupId>org.wildfly</groupId>
			<artifactId>wildfly-jms-client-bom</artifactId>
			<version>${version.wildfly}</version>
			<type>pom</type>
		</dependency>
</dependencies>

For example, if running WildFly 10, set as Property:

<properties>
		<version.wildfly>10.0.0.Final</version.wildfly>
</properties>

On the other hand, if you are using InVM local Clients (such as MDBs), you need to include the jboss-jms-api in your project:

<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.wildfly.bom</groupId>
			<artifactId>jboss-javaee-7.0-with-all</artifactId>
			<version>8.0.0.Final</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>   
    </dependencies>


</dependencyManagement>

. . . . 
 
<dependencies>	 

	<dependency>
		<groupId>org.jboss.spec.javax.jms</groupId>
		<artifactId>jboss-jms-api_2.0_spec</artifactId>
		<scope>provided</scope>
	</dependency>

</dependencies>

And here are some examples for configuring JMS queues and destinations:

JBoss JMS 1.0 Queue standalone application:

package sample;
import java.util.Properties;
import java.util.Scanner;

import javax.jms.*;

import javax.naming.Context;

public class QueueExample implements MessageListener  
{

    public void example() throws Exception
    {
        String destinationName = "queue/queueA";

        Context ic = null;
        ConnectionFactory cf = null;
        Connection connection =  null;

        try {         
            ic = getInitialContext();

            cf = (ConnectionFactory)ic.lookup("/ConnectionFactory");
            Queue queue = (Queue)ic.lookup(destinationName);

            connection = cf.createConnection();
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageProducer publisher = session.createProducer(queue);
            MessageConsumer subscriber = session.createConsumer(queue);

            subscriber.setMessageListener(this);
            connection.start();

            TextMessage message = session.createTextMessage("Hello!");
            publisher.send(message);

            Scanner keyIn = new Scanner(System.in);

            System.out.print("JMS Server listening. Type a Key + CR to exit\n");
            keyIn.next();

        }
        finally
        {         
            if(ic != null)
            {

                try
                { ic.close(); }
                catch(Exception e)
                {
                    throw e;
                }
            }

            closeConnection(connection);
        }
    }
    public synchronized void onMessage(Message message) {
        TextMessage text = (TextMessage)message;
        String strMessage = null;
        try {
            strMessage = text.getText();
        } catch (JMSException e) {

            e.printStackTrace();
        }
        System.out.println("Message received: "+strMessage);
    }

    private void closeConnection(Connection con)
    {      
        try
        {
            if (con != null)
            {
                con.close();
            }         
        }
        catch(JMSException jmse)
        {
            System.out.println("Could not close connection " + con +" exception was " + jmse);
        }
    }

    protected boolean isQueueExample() {
        return true;
    }

    public static void main(String[] args) throws Exception
    { new QueueExample().example(); }

    public static Context getInitialContext( ) throws javax.naming.NamingException {

        Properties p = new Properties( );
        p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
        p.put(Context.URL_PKG_PREFIXES," org.jboss.naming:org.jnp.interfaces");
        p.put(Context.PROVIDER_URL, "jnp://localhost:1099");
        return new javax.naming.InitialContext(p);
    }  
}

JBoss JMS 1.0 Topic standalone application:

package sample;

import java.util.Properties;
import java.util.Scanner;

import javax.jms.*;
import javax.naming.Context;


public class TopicExample implements MessageListener  
{

    public void example() throws Exception {
        String destinationName = "topic/topicA";

        Context ic = null;
        ConnectionFactory cf = null;
        Connection connection =  null;

        try {         
            ic = getInitialContext();

            cf = (ConnectionFactory)ic.lookup("/ConnectionFactory");
            Topic topic = (Topic)ic.lookup(destinationName);

            connection = cf.createConnection();
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageProducer publisher = session.createProducer(topic);
            MessageConsumer subscriber = session.createConsumer(topic);

            subscriber.setMessageListener(this);
            connection.start();

            TextMessage message = session.createTextMessage("Hello!");
            publisher.send(message);

            Scanner keyIn = new Scanner(System.in);

            System.out.print("JMS Server listening. Type a Key + CR to exit\n");
            keyIn.next();

        }
        finally
        {   
            if(ic != null)
            {
                try
                {
                    ic.close();
                }
                catch(Exception e)  {
                    throw e;
                }
            }

            closeConnection(connection);
        }
    }
    public synchronized void onMessage(Message message)
    {
        TextMessage text = (TextMessage)message;
        String strMessage = null;
        try {
            strMessage = text.getText();
        } catch (JMSException e) {
            e.printStackTrace();
        }
        System.out.println("Message received: "+strMessage);
    }

    private void closeConnection(Connection con) {      
        try {
            if (con != null) {
                con.close();
            }         
        }
        catch(JMSException jmse)
        {
            System.out.println("Could not close connection " + con +" exception was " + jmse);
        }
    }

    protected boolean isQueueExample()
    {
        return true;
    }

    public static void main(String[] args) throws Exception {
        new TopicExample().example();
    }
    public static Context getInitialContext( ) throws javax.naming.NamingException {

        Properties p = new Properties( );
        p.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
        p.put(Context.URL_PKG_PREFIXES," org.jboss.naming:org.jnp.interfaces");
        p.put(Context.PROVIDER_URL, "jnp://localhost:1099");
        return new javax.naming.InitialContext(p);
    }  
}

JBoss MDB 3.0 Queue:

package com.sample;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.Message;
import javax.jms.MessageListener;

@MessageDriven(name = "MessageMDBSample", activationConfig = {
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/queueA"),
        @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })

public class DummyMDBean implements MessageListener {

    public void onMessage(Message message) {

        System.out.println("Message received!");

    }

}

Running WildFly ? Continue Reading the following tutorials:

JMS 2.0 tutorial

How to code a remote JMS client for WildFly