JMS Example using Glassfish and a Remote Client

Aim
The aim of this Java Messaging Service JMS tutorial is to configure a simple JNDI JMS Topic in glassfish, publish to the topic using a serverlet and listen in on the JMS topic using a remote java client. For some reason this took a long time simply because of the number of errors I kept getting. The well documented java.lang.ClassNotFoundException: com.sun.messaging.jms.ra.ResourceAdapter among the more famous ones. Leave any questions or problems as comments and I will endeavour to answer them.

If you wish to connect to JMS using C/C++ please have a look at Connecting to Glassfish JMS using C++/C API.

Assumptions
This article assumes that you have Galssfish 2 installed and a domain configured. Please see Installing and Setting up Glassfish 2 for more details. For purposes of this example the glassfish domain is running on port 8082 and the project directory is GlassfishJMSHelloWorld.

Versions used in this example
Sofware/ComponentImage
Windows XP SP2N/A
Glassfish 2glassfish-installer-v2.1-b60e-windows.jar
JDK 1.5.0N/A
Links to these files can be found here

Although this is a quick 'helloworld' tutorial we will not sacrifice neatness for speed - so all the source files, class files etc will be kept in separate directories and as clean as possible. You will thank me for this later.

Create this webapp directory structure in your working directory- similar to something you would get from eclipse. The structure used in this example is given below. GlassfishJMSHelloWorld will be referred to as your project or working directory. Create this structure.

GlassfishJMSHelloWorld
_|_src
_|__|_PublisherServlet.java
_|__|_TopicListener.java
_|_WEB-INF
_|__|_web.xml
_|__|_classes
_|_bin
_|__|_appserv-rt.jar
_|__|_imqmsra.jar
_|__|_javaee.jar
_|__|_appserv-admin.jar
_|__|_appserv-deployment-client.jar


The Glassfish app server is installed in the D:\downloads\glassfish directory for this tutorial.

Configure the JMS ConnectionFactory and Topic in Glassfish
  1. Login to the admin console in you Glassfish domain (see Installing and Setting up Glassfish 2 for more details).
  2. `
  3. Select Resources -> JMS Resources -> Connection Factories. Select New.
  4. `
  5. Set the name as jms/MyConnectionFactory and select javax.jms.ConnectionFactory as the "Resource Type" dropdown. Select OK.
  6. `
  7. Now select Resources -> JMS Resources -> Destination Resources. Select New
  8. `
  9. Enter jms/MyFirstTopic as the JNDI name. Enter MyFirstTopic into the Physical Destination Name and select javax.jms.Topic from the "Resource Type" dropdown. Select OK. The physical destination is what you would use to connect outside of JNDI - forexample using the JMS C-API.

  10. `
  11. Once this is done open a cmd prompt/terminal and navigate to the Glassfish asadmin directory (D:\downloads\glassfish\bin) in this example.
  12. `
  13. Use the asadmin list-jndi-entities to make sure your JNDI names are visible.
    d:\downloads\glassfish\bin>asadmin -list-jndi-entities --context jms

    Jndi Entries for server within jms context:
    MyConnectionFactory: javax.naming.Reference
    MyFirstTopic: javax.naming.Reference
    Command list-jndi-entries executed successfully.
Copy required jars
  1. Copy these files below from your glassfish\lib directory to the bin directory under your working directory
    appserv-rt.jar
    appserv-admin.jar
    appserv-deployment-client.jar
    javaee.jar

    Copy the imqjmsra.jar file from the glassfish\lib\install\applications\jmsra to the bin directory in your working directory.

    This is the best way to isolate these files so you can be sure to pick up the correct one, without specifying directories.

Write and compile the servlet
  1. Write the servlet and save it as PublisherServlet.jar under the "src" directory in your working directory.
     1. import java.io.*;
     2. import java.util.*;
     3. 
     4. import javax.servlet.*;
     5. import javax.servlet.http.*;
     6. 
     7. import javax.jms.*;
     8. import javax.naming.*;
     9. 
    10. public class PublisherServlet extends HttpServlet {
    11.     
    12.     public void doGet(HttpServletRequest request, HttpServletResponse response){
    13.     try{
    14.         Context context = new InitialContext();
    15.         TopicConnectionFactory tfactory = (TopicConnectionFactory) context.lookup("jms/MyConnectionFactory");
    16.         
    17.         TopicConnection tconnection = tfactory.createTopicConnection();
    18.         TopicSession tsession = tconnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
    19.         TopicPublisher publisher = tsession.createPublisher((Topic)context.lookup("jms/MyFirstTopic"));
    20.         
    21.         TextMessage message = tsession.createTextMessage();
    22.         message.setText("Hello there buddy");
    23.         publisher.publish(message);
    24.         
    25.         context.close();
    26.         tconnection.close();
    27.         
    28.           response.setContentType("text/html");
    29.           response.getWriter().println("<html><body>message sent</body></html>");
    30. 
    31.         
    32.     }catch(Exception e){
    33.         e.printStackTrace();
    34.     }
    35.     }
    36. }
    Hide line numbers
  2. `
  3. Compile the code and install it using

    ..workspace\GlassfishJMSHelloWorld\src>javac -extdirs d:\downloads\glassfish\lib -d ..\WEB-INF\classes PublisherServlet.java
    Substitue your local glassfish\lib directory for the -extdirs.
  4. `
  5. Create the web.xml file in the same WEB-INF directory.
     1. <?xml version="1.0" encoding="UTF-8"?>
     2. <web-app>
     3. 
     4.   <display-name>GlassfishJMS sender/publisher</display-name>
     5. 
     6.   <servlet>
     7.     <servlet-name>Glassfish JMS Publisher</servlet-name>
     8.     <servlet-class>PublisherServlet</servlet-class>
     9.   </servlet>
    10. 
    11.   <servlet-mapping>
    12.     <servlet-name>Glassfish JMS Publisher</servlet-name>
    13.     <url-pattern>/publish</url-pattern>
    14.   </servlet-mapping>
    15. 
    16. </web-app>
    Hide line numbers
  6. `
  7. Now cd out to the workingdirectory and jar up the WEB-INF directory using

    ..workspace\GlassfishJMSHelloWorld>jar -cfv glassfishjms.jar WEB-INF
Deploying the Service
  1. Login to you Glassfish admin console (see Installing and Setting up Glassfish 2 for more details).
  2. `
  3. Select Applications -> Web Applications and select "Deploy."
  4. `
  5. Under "Type" select  App client(.jar). Under "Location" select  "Packaged file to be uploaded to the server". Select "Browse Files" and navigate to your working directory and select the glassfishjms.jar you created in the previous step. Select OK.
  6. `
  7. Now navigate to 'http://127.0.0.1:8082/glassfishjms/publish' in your browser. You should see a response saying "message sent."
Creating and compiling remote Listener
  1. Create the TopicListerner.java file and save it under the src directory in your working directory.
     1. import java.io.*;
     2. import java.util.*;
     3. 
     4. import javax.jms.*;
     5. import javax.naming.*;
     6. 
     7. public class TopicListener implements MessageListener{
     8.     
     9.     public static void main(String args[]){
    10.         new TopicListener().Go(args);
    11.     }
    12.     
    13.     public void Go(String[] args){
    14.         try{
    15.             Properties props = new Properties();
    16.             props.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.appserv.naming.S1ASCtxFactory");
    17.             props.put(Context.PROVIDER_URL,"iiop://127.0.0.1:3700");  
    18. 
    19.             Context context = new InitialContext(props);
    20.             TopicConnectionFactory tfactory = (TopicConnectionFactory) context.lookup("jms/MyConnectionFactory");
    21.         
    22.             TopicConnection tconnection = tfactory.createTopicConnection();
    23.             TopicSession tsession = tconnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
    24.         
    25.             TopicSubscriber subscriber = tsession.createSubscriber((Topic)context.lookup("jms/MyFirstTopic"));
    26.             
    27.             subscriber.setMessageListener(this);
    28.             
    29.             tconnection.start();
    30.         
    31.             (new BufferedReader(new InputStreamReader(System.in))).readLine();
    32.         
    33.             context.close();
    34.             tconnection.close();
    35.         }catch(Exception e){
    36.             e.printStackTrace();
    37.         }
    38.     }
    39. 
    40.     public void onMessage(Message message){
    41.         if(message instanceof TextMessage){
    42.             try{
    43.                 System.out.println( ((TextMessage)message).getText());
    44.             }catch(Exception e){
    45.             }
    46.         }
    47.     }
    48. }
    Hide line numbers
  2. `
  3. Compile and install the class in your bin directory

    ..workspace\GlassfishJMSHelloWorld\src>javac -extdirs d:\downloads\glassfish\lib -d ..\bin TopicListener.java
Running the example
  1. Open a prompt into the bin directory and fire up the client like so.

    ..workspace\GlassfishJMSHelloWorld\bin>java -cp javaee.jar;imqjmsra.jar;appserv-rt.jar;appserv-admin.jar;. TopicListener
  2. `
  3. Now navigate to 'http://127.0.0.1:8082/glassfishjms/publish' in your browser. You should see a response saying "message sent." The message should now magically appear in the prompt where your remote client is running.

Back to the tutorial trail | Home

6 comments:

SteJav said...

Nice tutorial, thanks. I read Glassfish V3 uses only one file for the remote client lib. Have you heard anything about it?

Cheers
Ste

Eddie said...

I get the following error:

Mar 24, 2010 3:40:44 PM com.sun.appserv.naming.RoundRobinPolicy setClusterInstanceInfo
WARNING: NAM1005 : No Endpoints selected. Please specify using system property com.sun.appserv.iiop.endpoints.
Mar 24, 2010 3:40:44 PM com.sun.appserv.naming.RoundRobinPolicy getEndpointForProviderURL
WARNING: NAM1001: No Endpoints selected in com.sun.appserv.iiop.endpoints property. Using JNDI Provider URL iiop://127.0.0.1:3700 instead
Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/appserv/management/util/misc/RunnableBase$HowToRun
at com.sun.enterprise.server.ApplicationServer.(ApplicationServer.java:398)
at com.sun.enterprise.util.ORBManager.initProperties(ORBManager.java:314)
at com.sun.enterprise.util.ORBManager.getORB(ORBManager.java:276)
at com.sun.enterprise.util.ORBManager.getORB(ORBManager.java:289)
at com.sun.appserv.naming.S1ASCtxFactory.getGIS(S1ASCtxFactory.java:391)
at com.sun.appserv.naming.S1ASCtxFactory.getInitialContext(S1ASCtxFactory.java:276)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
at javax.naming.InitialContext.init(InitialContext.java:223)
at javax.naming.InitialContext.(InitialContext.java:197)
at jmsclient.TopicListener.Go(TopicListener.java:27)
at jmsclient.TopicListener.main(TopicListener.java:17)
Caused by: java.lang.ClassNotFoundException: com.sun.appserv.management.util.misc.RunnableBase$HowToRun
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
... 12 more
Java Result: 1

Anonymous said...

On step seven, I had to use command

asadmin list-jndi-entries --context jms

RHH

Anonymous said...

I had the same problem as Eddie - Seems my Glassfish download (GlassFish Server Open Source Edition- 2.1.1 Final) wanted Java EE 5 classes too. So I downloaded GlassFish Java EE, added to classpath, and sample app ran!

Had same situation with "asadmin list-jndi-entries --context jms".

This is an excellent example, simple to follow, appreciate your posting the samples.

Anonymous said...

In previous post forgot to list the jars used in my bin directory:

appserv-admin.jar:
appserv-deployment-client.jar:
appserv-ext.jar:
appserv-rt.jar:
imqjmsra.jar
j2ee.jar:
javaee.jar:

Naviya Nair said...

Very interesting and good Explanation
ASP NET Training
ASP NET Training
ASP NET Online Training
C-Sharp Training
Dot Net Training in Chennai
Online .Net Training


MVC Training
WCF Training
Web-API Training
LINQ Training
Entity Framework
Training

Dot Net Interview Questions