Hello World Example

The Hello World application consists of a publisher application that publishes a "Hello World" message to a topic. This message will be received by all topic subscribers that are connected to the topic in question. In other words, the message is broadcast to all listeners.

There are three sample programs for this applications:

Topic Publisher

Synchronous Topic Subscriber

Asynchronous Topic Subscriber

As was the case with the P2P examples, none of the source code here handlings exceptions. Although this improves the readability of the example code, application programmers should notice that almost all methods in the JMS API's may raise a JMSException if the JMS provider fails.

Topic Publisher

A topic publisher must perform the usual steps to initialize before it can start to send messages:

  1. Obtain an InitialContext object for the JMS server.

  2. Use the context object to lookup a specific topic, in this case, topic0.

  3. Use the context object to lookup the topic connection factory. You only need to specify the topic/connectionFactory with the lookup because the batch file that you run this sample from has set the system properties to point to the appropriate root context for the system namespace. If you were using the JMS server with the Novell exteNd Application Server, you would have to specify the lookup as follows:

    	TopicConnectionFactory connFactory = (TopicConnectionFactory) ctx.
                lookup("iiop://localhost:53506/topic/connectionFactory");
    	
  4. Use the TopicConnectionFactory to create a TopicConnection. The TopicConnection represents a physical connection to the JMS server.

  5. Create a topic session. The first parameter in the createTopicSession method decides whether or not the session is transacted. Here, we use a non-transacted session. The second parameter decided the delivery mode, which is never used for sending applications.

  6. Create a topic publisher for topic0 and create a message.

  7. Publish the "Hello World" message to topic0.

  8. Finally, close the topic connection. This will in turn close both the session and the TopicPublisher.

The source code for the Publisher class is shown below:

package pubSub;
                                                                           
import javax.naming.InitialContext;
                                                                           
import javax.jms.Topic;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.TopicPublisher;
import javax.jms.DeliveryMode;
import javax.jms.TopicSession;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
                                                                           
public class Publisher
{
    public static void main(String[] args) throws Exception
    {
    |   // get the initial context
    |   InitialContext ctx = new InitialContext();
    |                                                                      
    |   // lookup the topic object
    |   Topic topic = (Topic) ctx.lookup("topic/topic0");
    |                                                                      
    |   // lookup the topic connection factory
    |   TopicConnectionFactory connFactory = (TopicConnectionFactory) ctx.
    |       lookup("topic/connectionFactory");
    |                                                                      
    |   // create a topic connection
    |   TopicConnection topicConn = connFactory.createTopicConnection();
    |                                                                      
    |   // create a topic session
    |   TopicSession topicSession = topicConn.createTopicSession(false, 
    |       Session.AUTO_ACKNOWLEDGE);
    |                                                                      
    |   // create a topic publisher
    |   TopicPublisher topicPublisher = topicSession.createPublisher(topic);
    |   topicPublisher.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
    |                                                                      
    |   // create the "Hello World" message
    |   TextMessage message = topicSession.createTextMessage();
    |   message.setText("Hello World");
    |                                                                      
    |   // publish the messages
    |   topicPublisher.publish(message);
    |                                                                      
    |   // print what we did
    |   System.out.println("published: " + message.getText());
    |                                                                      
    |   // close the topic connection
    |   topicConn.close();
    }
}

Note that although the message is sent with default delivery mode set to PERSISTENT, the JMS server will only persist topic messages when a topic has durable subscribers. In pub/sub messaging, persistent messages only make sense with durable subscribers because transient subscribers are lost if the server or subscriber crashes.

Synchronous Topic Subscriber

As described in the P2P Hello example, a synchronous receiver must actively retrieve messages by using on of the receive methods. The receive method blocks until the connection has been started and a message is available at the topic.

A topic subscriber performs the same initial steps as the topic publisher listed above to get a session. Then it creates a topic receiver and starts the connection. Finally, a message is consumer from the topic after which the connection is closed:

package pubSub;
                                                                           
import javax.naming.InitialContext;
                                                                           
import javax.jms.Topic;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
                                                                           
public class Subscriber
{
    public static void main(String[] args) throws Exception
    {
    |   // get the initial context
    |   InitialContext ctx = new InitialContext();
    |                                                                      
    |   // lookup the topic object
    |   Topic topic = (Topic) ctx.lookup("topic/topic0");
    |                                                                      
    |   // lookup the topic connection factory
    |   TopicConnectionFactory connFactory = (TopicConnectionFactory) ctx.
    |       lookup("topic/connectionFactory");
    |                                                                      
    |   // create a topic connection
    |   TopicConnection topicConn = connFactory.createTopicConnection();
    |                                                                      
    |   // create a topic session
    |   TopicSession topicSession = topicConn.createTopicSession(false,
    |       Session.AUTO_ACKNOWLEDGE);
    |                                                                      
    |   // create a topic subscriber
    |   TopicSubscriber topicSubscriber = topicSession.createSubscriber(topic);
    |                                                                      
    |   // start the connection
    |   topicConn.start();
    |                                                                      
    |   // receive the message
    |   TextMessage message = (TextMessage) topicSubscriber.receive();
    |                                                                      
    |   // print the message
    |   System.out.println("received: " + message.getText());
    |                                                                      
    |   // close the topic connection
    |   topicConn.close();
    }
}

Note that if you run the Subscriber application after running the Publisher application, the subscriber will not receive a message. This happens because topic subscribers will only receive messages that were sent to the topic after the subscription was made.

Asynchronous Topic Subscriber

An asynchronous topic subscriber is very similar to an asynchronous queue receiver. It registers a message listener, which will be invoked automatically and asynchronously by the JMS provider as and when messages arrive at the subscribed topic.

As described earlier, asynchronous message listener are encouraged to also register an exception listener with the connection to be able to receive a notification if an exception occurs while JMS processes the message. The exception listener is this example merely prints out the exception.

package pubSub;
                                                                           
import javax.naming.InitialContext;
                                                                           
import javax.jms.Topic;
import javax.jms.Session;
import javax.jms.Message;
import javax.jms.TextMessage;
import javax.jms.MessageListener;
import javax.jms.JMSException;
import javax.jms.ExceptionListener;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
                                                                           
public class AsyncSubscriber implements MessageListener, ExceptionListener
{
    public static void main(String[] args) throws Exception
    {
    |   // get the initial context
    |   InitialContext ctx = new InitialContext();
    |                                                                      
    |   // lookup the topic object
    |   Topic topic = (Topic) ctx.lookup("topic/topic0");
    |                                                                      
    |   // lookup the topic connection factory
    |   TopicConnectionFactory connFactory = (TopicConnectionFactory) ctx.
    |       lookup("topic/connectionFactory");
    |                                                                      
    |   // create a topic connection
    |   TopicConnection topicConn = connFactory.createTopicConnection();
    |                                                                      
    |   // create a topic session
    |   TopicSession topicSession = topicConn.createTopicSession(false,
    |       Session.AUTO_ACKNOWLEDGE);
    |                                                                      
    |   // create a topic subscriber
    |   TopicSubscriber topicSubscriber = topicSession.createSubscriber(topic);
    |                                                                      
    |   // set an asynchronous message listener
    |   AsyncSubscriber asyncSubscriber = new AsyncSubscriber();
    |   topicSubscriber.setMessageListener(asyncSubscriber);
    |                                                                      
    |   // set an asynchronous exception listener on the connection
    |   topicConn.setExceptionListener(asyncSubscriber);
    |                                                                      
    |   // start the connection
    |   topicConn.start();
    |                                                                      
    |   // wait for messages
    |   System.out.print("waiting for messages");
    |   for (int i = 0; i < 10; i++) {
    |   |   Thread.sleep(1000);
    |   |   System.out.print(".");
    |   }
    |   System.out.println();
    |                                                                      
    |   // close the topic connection
    |   topicConn.close();
    }
                                                                           
    /**
       This method is called asynchronously by JMS when a message arrives
       at the topic. Client applications must not throw any exceptions in
       the onMessage method.
       @param message A JMS message.
     */
    public void onMessage(Message message)
    {
    |   TextMessage msg = (TextMessage) message;
    |   try {
    |   |   System.out.println("received: " + msg.getText());
    |   } catch (JMSException ex) {
    |   |   ex.printStackTrace();
    |   }
    }
                                                                           
    /**
       This method is called asynchronously by JMS when some error occurs.
       When using an asynchronous message listener it is recommended to use
       an exception listener also since JMS have no way to report errors
       otherwise.
       @param exception A JMS exception.
     */
    public void onException(JMSException exception)
    {
    |   System.err.println("something bad happended: " + exception);
    }
}

This example uses automatic acknowledge, which means that JMS will acknowledge the message right after onMessage successfully returns. If a subscriber uses CLIENT_ACKNOWLEDGE, it must acknowledge messages manually during the onMessage method.

Although messages are not required to be acknowledged each time onMessage is called with CLIENT_ACKNOWLEDGE, it is recommended that applications acknowledge messages as quickly as possible to avoid a large build-up of un-acknowledged messages on the client.



Copyright © 2003, 2004 Novell, Inc. All rights reserved. Copyright © 2001, 2002, 2003 SilverStream Software, LLC. All rights reserved.