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.

Embedded Server – Tomcat 7

What is an Embedded Server?

Traditionally, java web applications have been seen as WAR files deployed on servlet containers and application servers.
Simultaneously another school of thought advocates deploying a server with an application; pioneered by Jetty. Tomcat too comes in this flavour – as embedded tomcat. In an embedded server application, the application is deployed and run as a JAR. This JAR file launches a main() method which in turn starts the server and deploys itself on it. With such an application, we eliminate dependency on having a server. Any machine that can run java, can act as a server.What advantages such a server have? None. The only advantage we have is that we can use it to develop small applications. Applications that can be run on machine that have just a JRE. For example, say in my uncle’s medicine shop. There is no setup cost involved – other than the machine itself.

In this article

In this article, we shall discuss about
  1. Softwares involved
  2. Project setup using maven
  3. Embedding tomcat server

Softwares involved

  1. JDK – preferably the latest
  2. Maven – preferably the latest
  3. An editor to write java classes.

You should also be connected to internet – to allow maven download its dependencies – and I bet there are many.

Project setup using Maven

We shall be creating a web archieve project – inline with J2EE specification. But we shall also be using maven. So the folder structure will follow maven standard, and not the structure that we see in eclipse projects.
Create the following depicted folder structure
  • The name of project is ‘SampleProject’.
  • There is an src folder that houses 2 folders – ‘main’ and ‘test’.
  • The ‘test’ folder is used to write test scripts. We won’t be doing that.
  • The ‘src’ folder is where we keep java source and also the web appllication files. So it has 2 children – ‘java’ for source code and ‘webapp’ for the web application resources. See the ‘WEB-INF’ folder that houses web.xml file.
Next create a pom.xml file in ‘SampleProject’ folder. And write the following in it.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.heroku.sample</groupId>
<artifactId>embeddedTomcatSample</artifactId>
<version>1.0-SNAPSHOT</version>
<name>embeddedTomcatSample Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>7.0.22</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-juli</artifactId>
<version>7.0.22</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>7.0.22</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>7.0.22</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper-el</artifactId>
<version>7.0.22</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jsp-api</artifactId>
<version>7.0.22</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
</dependencies>
<build>
<finalName>embeddedTomcatSample</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.1.1</version>
<configuration>
<assembleDirectory>target</assembleDirectory>
<programs>
<program>
<mainClass>com.ego.apps.Launch</mainClass>
<name>webapp</name>
</program>
</programs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>assemble</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

Note – the dependencies section list out the JARs needed for embedded tomcat.

Now we need to tell maven to download these dependencies – so that we can continue with our application. Navigate to the SampleProject folder and issue command

mvn install

This would install all the dependencies required.

Now, go ahead and create a servlet. We created following

package com.ego.apps.servlets;

import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

public class TestServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
{
try
    {
    response.getOutputStream().print("Hello World!");
    }
catch (IOException e)
    {
    }
}
}

And edit the web.xml in WEB-INF as

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>

<servlet>
<servlet-name>Test</servlet-name>
<servlet-class>com.ego.apps.servlets.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Test</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

</web-app>

This completes our web application setup by issuing final command

mvn clean install

Embedding tomcat server

We have our web application ready. It can be archieved as a WAR and deployed on any server.
But no, we are smart and will package our server with out application. So create a java file as given below
package com.ego.apps;

import java.io.File;

import org.apache.catalina.startup.Tomcat;
import org.apache.log4j.Logger;

public class Launch {
public static void main(String[] args) throws Exception {
Logger logger = Logger.getLogger(Launch.class);
String webappDirLocation = "src/main/webapp/";
Tomcat tomcat = new Tomcat();

// Look for that variable and default to 8080 if it isn't there.
String webPort = System.getenv("PORT");
if (webPort == null || webPort.isEmpty()) {
webPort = "8080";
}
logger.info("Application port set to: " + webPort);
tomcat.setPort(Integer.valueOf(webPort));

tomcat.addWebapp("/", new File(webappDirLocation).getAbsolutePath());
logger.info("configuring app with basedir: "
+ new File("./" + webappDirLocation).getAbsolutePath());

tomcat.start();
logger.info("Application started.");
tomcat.getServer().await();
}
}
 If you go through the main() method of the class, you will figure out that it instantiates tomcat with a port number to run upon.
Tomcat tomcat = new Tomcat();</pre>
tomcat.setPort(Integer.valueOf(webPort));

The command above instantiated tomcat and sets the port to listen to as 8080.

Now we need to guide tomcat to deploy our application.  This is done as

tomcat.addWebapp("/", new File("src/main/webapp/").getAbsolutePath());

Once web application is added to tomcat, we can start it. It runs as a thread and awaits requests. The command is

tomcat.start();
tomcat.getServer().await();

And ta-da.

Now its time to compile and run our application.
First we clean maven directory, compile the code and package it as

mvn clean install

The packaging creates target directory where all the temporary artifacts are kept. The war file is kept here as “embeddedTomcatSample” because this what we mentioned in POM dependencies section. This JAR is run using the batch file generated in target\bin. Run it as

target\bin\webapp.bat

This would start the tomcat server for us.

Strings and String literals in String Literal Pool

A lot of times I have been asked questions to count the number of string objects created in a statement. Yes, typically by product companies. So it triggered me to actually write an article on it.

Let us discuss on the following topics then

  • String is immutable
  • String pool
  • String literal and garbage collection

String is immutable?

Strings are immutable objects. 

Yes, once created, they cannot be change. Although we can perform operations on it to create new string objects.

 
String str = "a" + "b";

In the statement above, we actually create string object “a”, then string object “b” and then append them to create new string object “c”. We do not alter the original strings “a” and “b”.
Same is the case when we write

 String s1 = "a";
String s2 = s1.concat("b");

String object “a” is created. String object “b” is created and concatenated to “a”. Oh no, String object “a” and “b” are added and new String object “ab” is created. The concat() is hence a misnomer. But one thing worth noting about the concat() according to javadoc is

If the length of the argument string is 0, then this String object is returned. Otherwise, a new String object is created, representing a character sequence that is the concatenation of the character sequence represented by this String object and the character sequence represented by the argument string.

Fairly simple but worth noting.

 String literal pool

String literal pool is a collection of references to String objects.

But the String objects are themselves created on heap, just like other objects. And the String literal pool references are maintained by the JVM (say in a table).

String literals and String pool

Now since the String objects are immutable, it is safe for multiple references to same literal actually share the same object.

 String s1 = "harsh";
String s2 = "harsh";

The code above seems to create 2 String objects, with literal as “harsh”. But in JVM, both the references s1 and s2 point to the same String object.
How do we test that?

System.out.println("Equals method: " + s1.equals(s2));
System.out.println("==: " + (s1 == s2));

This should explain you what I am trying to say.

What happens behind the scenes is that the string literals are noted down separately by the compiler. When the classloader loads the class, goes through the literal table. When it finds a literal, it searches through the list of String pool references to see if the equivalent String already exists on heap. If one already exists, all the references in class to this String literal are replaced with the reference to the String object on heap (pointed to by the String literal table). If none exists, then a new object is created on heap and then its reference is created on String literal pool table. So any subsequent references to this literal are automatically mapped to the existing String object on heap.

The ‘new’ operator and String literal pool

When it comes to the ‘new’ operator, it forces the JVM to create a new String object on the String literal pool. It has no connection whatsoever with the objects on String literal pool.

A ‘new’ operator creates and points to a new String object on heap.

Hence, do not think ‘String literal pool’ when you encounter ‘new’ operator.

Literal mathematics through constant operations

What about the String created through literal mathematics?
String s1 = "ab" + "c";
String s2 = "a" + "bc";

The above operation also creates a single literal on string pool, and both the references point to it. How? Because compiler can calculate this at compile time, that we are doing string literal constant mathematics.

Literal mathematics through objects

String s1 = "a";
String s2 = s1 + "bc";
String s3 = "a" + "bc";
In statements above, s2 and s3 do not point to the same literal.
i.e. when we perform some mathematics through references, compiler isn’t able to identify the resultant string at compile time, and hence does not make an entry for the literal pool.
String object referenced by s1 and s3 go on the literal pool, but not the one referenced by s2 as it is created at runtime.

String literal garbage collection

An object is eligible for garbage collection when it is no longer referenced.

But our String literals on the literal pool are always referenced by the literal pool. So they are never eligible for garbage collection. They are always accessible through String interns.
But the objects created by ‘new’ operator are eligible if they are no longer referenced – as they are never referred to by the pool.