Chapter 5. Examples

This chapter demonstrates the use of AMQ JMS through example programs.

For more examples, see the JMS example suite.

5.1. Configuring the JNDI context

Applications using JMS typically use JNDI to obtain the ConnectionFactory and Destination objects used by the application. This keeps the configuration separate from the program and insulates it from the particular client implementation.

For the purpose of using these examples, a file named jndi.properties should be placed on the classpath to configure the JNDI context, as detailed previously.

The contents of the jndi.properties file should match what is shown below, which establishes that the client’s InitialContextFactory implementation should be used, configures a ConnectionFactory to connect to a local server, and defines a destination queue named queue.

# Configure the InitialContextFactory class to use
java.naming.factory.initial = org.apache.qpid.jms.jndi.JmsInitialContextFactory

# Configure the ConnectionFactory
connectionfactory.myFactoryLookup = amqp://localhost:5672

# Configure the destination
queue.myDestinationLookup = queue

5.2. Sending messages

This example first creates a JNDI Context, uses it to look up a ConnectionFactory and Destination, creates and starts a Connection using the factory, and then creates a Session. Then a MessageProducer is created to the Destination, and a message is sent using it. The Connection is then closed, and the program exits.

A runnable variant of this Sender example is in the <install-dir>/examples directory, along with the Hello World example covered previously in Chapter 3, Getting started.

Example: Sending messages

package org.jboss.amq.example;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;

public class Sender {
  public static void main(String[] args) throws Exception {
    try {
      Context context = new InitialContext(); 1

      ConnectionFactory factory = (ConnectionFactory) context.lookup("myFactoryLookup");
      Destination destination = (Destination) context.lookup("myDestinationLookup"); 2

      Connection connection = factory.createConnection("<username>", "<password>");
      connection.setExceptionListener(new MyExceptionListener());
      connection.start(); 3

      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 4

      MessageProducer messageProducer = session.createProducer(destination); 5

      TextMessage message = session.createTextMessage("Message Text!"); 6
      messageProducer.send(message, DeliveryMode.NON_PERSISTENT,
                           Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE); 7

      connection.close(); 8
    } catch (Exception exp) {
      System.out.println("Caught exception, exiting.");
      exp.printStackTrace(System.out);
      System.exit(1);
    }
  }

  private static class MyExceptionListener implements ExceptionListener {
    @Override
    public void onException(JMSException exception) {
      System.out.println("Connection ExceptionListener fired, exiting.");
      exception.printStackTrace(System.out);
      System.exit(1);
    }
  }
}

1
Creates the JNDI Context to look up ConnectionFactory and Destination objects. The configuration is picked up from the jndi.properties file as detailed earlier.
2
The ConnectionFactory and Destination objects are retrieved from the JNDI Context using their lookup names.
3
The factory is used to create the Connection, which then has an ExceptionListener registered and is then started. The credentials given when creating the connection will typically be taken from an appropriate external configuration source, ensuring they remain separate from the application itself and can be updated independently.
4
A non-transacted, auto-acknowledge Session is created on the Connection.
5
The MessageProducer is created to send messages to the Destination.
6
A TextMessage is created with the given content.
7
The TextMessage is sent. It is sent non-persistent, with default priority and no expiration.
8
The Connection is closed. The Session and MessageProducer are closed implicitly.

Note that this is only an example. A real-world application would typically use a long-lived MessageProducer and send many messages using it over time. Opening and then closing a Connection, Session, and MessageProducer per message is generally not efficient.

5.3. Receiving messages

This example starts by creating a JNDI Context, using it to look up a ConnectionFactory and Destination, creating and starting a Connection using the factory, and then creates a Session. Then a MessageConsumer is created for the Destination, a message is received using it, and its contents are printed to the console. The Connection is then closed and the program exits. The same JNDI configuration is used as in the sending example.

An executable variant of this Receiver example is contained within the examples directory of the client distribution, along with the Hello World example covered previously in Chapter 3, Getting started.

Example: Receiving messages

package org.jboss.amq.example;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;

public class Receiver {
  public static void main(String[] args) throws Exception {
    try {
      Context context = new InitialContext(); 1

      ConnectionFactory factory = (ConnectionFactory) context.lookup("myFactoryLookup");
      Destination destination = (Destination) context.lookup("myDestinationLookup"); 2

      Connection connection = factory.createConnection("<username>", "<password>");
      connection.setExceptionListener(new MyExceptionListener());
      connection.start(); 3

      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); 4

      MessageConsumer messageConsumer = session.createConsumer(destination); 5

      Message message = messageConsumer.receive(5000); 6

      if (message == null) { 7
        System.out.println("A message was not received within given time.");
      } else {
        System.out.println("Received message: " + ((TextMessage) message).getText());
      }

      connection.close(); 8
    } catch (Exception exp) {
      System.out.println("Caught exception, exiting.");
      exp.printStackTrace(System.out);
      System.exit(1);
    }
 }

  private static class MyExceptionListener implements ExceptionListener {
    @Override
    public void onException(JMSException exception) {
      System.out.println("Connection ExceptionListener fired, exiting.");
      exception.printStackTrace(System.out);
      System.exit(1);
    }
  }
}

1
Creates the JNDI Context to look up ConnectionFactory and Destination objects. The configuration is picked up from the jndi.properties file as detailed earlier.
2
The ConnectionFactory and Destination objects are retrieved from the JNDI Context using their lookup names.
3
The factory is used to create the Connection, which then has an ExceptionListener registered and is then started. The credentials given when creating the connection will typically be taken from an appropriate external configuration source, ensuring they remain separate from the application itself and can be updated independently.
4
A non-transacted, auto-acknowledge Session is created on the Connection.
5
The MessageConsumer is created to receive messages from the Destination.
6
A call to receive a message is made with a five second timeout.
7
The result is checked, and if a message was received, its contents are printed, or notice that no message was received. The result is cast explicitly to TextMessage as this is what we know the Sender sent.
8
The Connection is closed. The Session and MessageConsumer are closed implicitly.

Note that this is only an example. A real-world application would typically use a long-lived MessageConsumer and receive many messages using it over time. Opening and then closing a Connection, Session, and MessageConsumer for each message is generally not efficient.