JBoss AS 7 – Setting up HornetQ JMS

JBoss AS 7

JBoss AS 7 was released in July 2011. I had worked on JBoss server 4 years ago – on JBoss 4.2.3 GA. For me, it was a complete shift in architecture of the JBoss. I couldn’t even start the server! So here I would explain step by step – how to start the server -to setting up JMS queue and topic – to creating clients.
The article is divided into 7 major chunks

  1. Setting up and running the JBoss AS 7.
  2. Setting up users.
  3. JMS Configuration files walkthrough
  4. Creating and Running Queue
  5. Creating and Running Topic
  6.  Running the sample code
  7. Exceptions I encountered while preparing this article

We assume that you already have a fair idea on JMS before proceeding.

For this article, we shall use the default configurations provided by the server – so that it is easy to create.

Setting up and Running JBoss AS 7

Download and extract JBoss from JBoss Website. For current explaination, we use 7.1.1.Final version.
Extract it to desired location. For me, it is “F:\JavaStuff\Servers\jboss-as-7.1.1.Final”. It will be refered as ‘jboss-home’ henceforth.
Previous versions of JBoss were run using run.bat (for windows and run.sh for linux). But things have changed now. We run it through profiles. We will be using ‘standalone’ profile.
Each profile has a set of configuration files. For standalone, they are kept at location “jboss-home\standalone\configuration” folder. This folder contains 4 configuration files
  1. standalone.xml (default)
  2. standalone-full.xml
  3. standalone-full-ha.xml
  4. standalone-ha.xml

The default configuration for standalone server – standalone.xml doesnot have JMS enabled by default. So we will use standalone-full.xml.

Now its time to run the JBoss with our desired configuration.
Go to command prompt and reach “jboss-home\bin” folder. And fire up the following command.

standalone -server-config=standalone-full.xml

And this starts our JBoss in standalone-full.xml.

Setting up users

JBoss 7 AS comes with enhanced security. Enhanced security means enhanced overheads and lots of user IDs and Passwords :).
JBoss has 2 types of users (or lets say 2 realms for users)
  1. Management Realm (server administrators)
  2. Application Realm (application users)

For JMS, we need an application realm user with a role. We shall use “guest” role for example. We shall also need a management realm user to validate if our JMS is up and running.

To create a user, go to “jboss-home\bin”. Use command

add-user

This will add a user to the application. Create following 2 users

User1
Select option a.
Realm: Management User
ID: administrator
Password: password
Role:
User 2
Select option b
Realm: Application User
ID: testuser
Password: password
Role: guest
Creating a user will look as below
F:\JavaStuff\Servers\jboss-as-7.1.1.Final\bin>add-user

What type of user do you wish to add?
a) Management User (mgmt-users.properties)
b) Application User (application-users.properties)
(a): b

Enter the details of the new user to add.
Realm (ApplicationRealm) :
Username : testuser
Password :
Re-enter Password :
What roles do you want this user to belong to? (Please enter a comma separated list, or leave blank for none) : guest

We need to follow the above mentioned steps for both the users.

JMS Configuration files – Walkthrough

JBoss AS 7 simplifies the server configuration by combining the configurations under 1 roof – one file. The configuration files are kept in folder: “jboss-home\standalone\configuration”.
We will be using ‘standalone-full.xml’ configuration file.
For JMS, we need to identify 4 items in this file.
  1. The user ‘roles’ permissions
  2. The RemoteConnectionFactory JNDI entry
  3. The Topic JNDI entry
  4. The Queue JNDI entry

 The user ‘roles’ permissions

Open the config file and search for text

<permission roles=”guest” type=”send”>

This text takes us to lines –

<security-setting match="#">
    <permission type="send" roles="guest"/>
    <permission type="consume" roles="guest"/>
    <permission type="createNonDurableQueue" roles="guest"/>
    <permission type="deleteNonDurableQueue" roles="guest"/>
</security-setting>

Note the roles – they have been marked as guests. These roles must match the roles of user we have created. This is the reason why we created application user ‘testuser’ with role as guest.

The RemoteConnectionFactory JNDI Entry

Now search for text

RemoteConnectionFactory

We reach place where code looks like

<connection-factory name="RemoteConnectionFactory">
    <connectors>
        <connector-ref connector-name="netty"/>
    </connectors>
    <entries>
        <entry name="RemoteConnectionFactory"/>
        <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>
    </entries>
</connection-factory>

Check the code for the tag with name attribute as “java:jboss/exported/jms/RemoteConnectionFactory”. This is the JNDI name using which connection factory can be obtained. The JNDI name always starts with “java:jboss/exported/”. If we don’t give this, and pass the JNDI name as “jms/RemoteConnectionFactory”, the JBoss itself prepends “java:jbpss/exported/” to complete the JNDI name.
Remember – only “java:jboss/exported/” is prepended to the JNDI string if it doesn’t exist in the string. The whole name should resolve to the JNDI name. Otherwise the JNDI lookup fails.

The Topic JNDI Entry

A sample Topic is already provided with the config file. Search for it in configuration file as

<jms -topic=”-topic” name=”testTopic”></jms>

Upon search, we see entry as

<jms-topic name="testTopic">
    <entry name="topic/test"/>
    <entry name="java:jboss/exported/jms/topic/test"/>
</jms-topic>

Check out the tag with attribute name as “java:jboss/exported/jms/topic/test”. This is the JNDI name for the Topic. The short hand name for this topic is “jms/topic/test”.
Note: The shorthand name is added “java:jboss/exported/” in front by the JBoss server when we do a JNDI lookup.

The Queue JNDI Entry

A sample queue is already provided with the config file. Search for it in configuration file as

<jms -queue=”-queue” name=”testQueue”> </jms>

The JNDI name and other things are same as the ‘topic’ we discussed.

Creating and Running Queue

The topics and queues are used in almost the similar fashion. The only things worth mentioning are
  1. The required JAR file
  2. The InitialContext creation
  3. The JNDI Lookup
  4. Creating Queue Sender
  5. Creating Queue Receiver

The required JAR file

The only JAR file we would need to include here is “jboss-home\bin\client\jboss-client.jar” file. We would need to keep this in classpath while both compiling and running.

 The InitialContext creation

InitialContext is created so that we can perform JNDI lookups. This is required step for both the queue and topic coding. Following is the code:

// Create an initial context.
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, “org.jboss.naming.remote.client.InitialContextFactory”);
props.put(Context.PROVIDER_URL, “remote://localhost:4447”);
props.put(Context.SECURITY_PRINCIPAL, “testuser”);
props.put(Context.SECURITY_CREDENTIALS, “password”);
InitialContext context = new InitialContext(props);

Note the properties Context.SECURITY_PRINCIPAL and Context.SECURITY_CREDENTIALS. These have the application user User ID and Password respectively. This user has the permissions as mentioned in the standalone-full.xml’s permissions configuration discussed earlier.

The JNDI Lookup

            // Strings for JNDI names
String factoryName = “jms/RemoteConnectionFactory”;
String queueName =  “jms/queue/test”;
            // Perform JNDI lookup
            QueueConnectionFactory factory = (QueueConnectionFactory) context.lookup(factoryName);
Queue queue = (Queue) context.lookup(queueName);

Creating Queue Sender

We first create a connection out of the factory by passing the user id and password of the user who is in application realm and has the permissions (roles) for JMS usage.
Then we create a session out of the connection. From session we get the sender by passing to the session the JNDI name of topic
The code looks as below
// Create JMS objects
QueueConnection connection = factory.createQueueConnection(“testuser”, “password”);
QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
QueueSender sender = session.createSender(queue);
            // Create the messages to be sent
            TextMessage message = session.createTextMessage(messageText);
sender.send(message);
             // Close the connection after usage.
            connection.close();

Creating Queue Receiver

A receiver follows the same steps as a sender – upto creating the receiver. The Receiver is also obtained from Session object. And thisis done as
            QueueReceiver receiver = session.createReceiver(queue);
receiver.setMessageListener(this);
Rest all of the code remains same.

Creating and Running Topic

Creating and running a topic is same as a queue. The difference is that we call a sender as publisher and receiver as a subscriber. And then there are internal differences – but none from code perspective. So I am sure if you go through the example code, you can understand.

Running the Sample Code

  1. Download the sample code from here: Download JBoss AS 7 JMS Sample Code
  2. Extract these files into a directory say Code. Recheck that the directory structure looks like Code\com\marshall\jms\queue and Code\com\marshall\jms\topic.
  3. Copy the jboss-home\bin\client\jboss-client.jar to folder Code\lib\jboss-client.jar
  4. Compile the sample code classes as
    1. javac -classpath lib\jboss-client.jar com\marshall\jms\queue\QSender.java
    2. javac -classpath lib\jboss-client.jar com\marshall\jms\queue\QReceiver.java
    3. javac -classpath lib\jboss-client.jar com\marshall\jms\topic\TPublisher.java
    4. javac -classpath lib\jboss-client.jar com\marshall\jms\topic\TSubscriber.java
  5. Run the queue classes as
    1. start java -classpath .;lib\jboss-client.jar; com.marshall.jms.queue.QSender
    2. start java -classpath .;lib\jboss-client.jar; com.marshall.jms.queue.QReceiver
  6. Run the topic classes as
    1. start java -classpath .;lib\jboss-client.jar; com.marshall.jms.topic.TPublisher
    2. start java -classpath .;lib\jboss-client.jar; com.marshall.jms.topic.TSubscriber

Exceptions I encountered during preparation of this article

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
This means something went wrong during the initial context creation. Please check that the JNDI names are correct and the code is proper.
javax.jms.JMSSecurityException: User: testuser doesn’t have permission=’CONSUME’ on address jms.queue.testQueue

OR

javax.jms.JMSSecurityException: User: testuser doesn’t have permission=’SEND’ on address jms.queue.testQueue

This means the user whose credentials we are using does not have permissions over the JMS system. Check the “jboss-home\stabdalone\configuration\application-roles.properties” to see if the user we are using has the correct role. This role must match with the role that has permissions mentioned in “jboss-home\standalone\configuration\standalone-full.xml” file.

javax.jms.JMSSecurityException: Unable to validate user: testuser

Check if the user being passed when creating both initial context and the connection is correct. He should have already been created. If you created it now and it doesn’t work, try restarting the server.