Chapter 4. Running the Examples

Since JBoss Messaging is a full JMS provider, it supports all JMS APIs. So, all JMS applications should work without modification. Integrated inside a JBoss AS, we should also access the JMS system from EJBs and write message-driven beans against JMS destinations.

In the following sections, we will look at examples of the various JMS messaging models and message-driven beans. They make use of pre-configured JMS destinations and connection factories that come default with the server. So, no extra configuration is needed to run those examples. Just set JBOSS_HOME and run ANT in each example directory, as we described in Section 5.3, “Installation Validation”. The example source directories are located in the distribution under docs/examples.

4.1. Sending messages to a queue

Open an new command line. Set the JBOSS_HOME environment variable to point at a JBossAS 4.x installation. Navigate to the folder where you exploded the main archive and drill down to /examples/queue. You need to use Apache Ant to execute the build.xml file. Make sure the JBoss server reference by the JBOSS_HOME is started.

public class QueueExample extends ExampleSupport
{

   public void example() throws Exception
   {
      String destinationName = getDestinationJNDIName();

       InitialContext ic = null;
       ConnectionFactory cf = null;
       Connection connection =  null;
       Connection connection2 =  null;

       try {

           ic = new InitialContext();

           cf = (ConnectionFactory)ic.lookup("/ConnectionFactory");
           Queue queue = (Queue)ic.lookup(destinationName);
           log("Queue " + destinationName + " exists");

           connection = cf.createConnection();
           Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
           MessageProducer sender = session.createProducer(queue);

           TextMessage message = session.createTextMessage("Hello!");
           sender.send(message);
           log("The message was successfully sent to the " + queue.getQueueName() + " queue");

           connection2 = cf.createConnection();
           Session session2 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
           MessageConsumer consumer =  session2.createConsumer(queue);

           connection2.start();

           message = (TextMessage)consumer.receive(2000);
           log("Received message: " + message.getText());
           assertEquals("Hello!", message.getText());

           displayProviderInfo(connection2.getMetaData());

       }catch(NamingException ne){
           ne.printStackTrace();

       }catch(JMSException jmse){
           jmse.printStackTrace();

       }catch(Exception e){
           e.printStackTrace();

       }finally{

           if(ic != null) {
               try {
                   ic.close();
               }catch(Exception ignore){ }
           }

           closeConnection(connection);

           closeConnection(connection2);
       }

   }

   private void closeConnection(Connection con){

       try {
           if (con != null) {
              con.close();
           }

       }catch(JMSException jmse) {
           log("Could not close connection " + con +" exception was " +jmse);
       }
   }


   protected boolean isQueueExample()
   {
      return true;
   }

   public static void main(String[] args)
   {
      new QueueExample().run();
   }

}
    

4.2. Sending messages to a topic

In this example, a standalone Java client publishes a text-based JMS message to a topic and a single subscriber pulls the message off the queue.

Open an new command line. Set the JBOSS_HOME environment variable to point at a JBossAS 4.x installation. Navigate to the folder where you exploded the main archive and drill down to /examples/queue. You need to use Apache Ant to execute the build.xml file Make sure the JBoss server reference by the JBOSS_HOME is started.

public class TopicExample extends ExampleSupport
{
   public void example() throws Exception
   {
      String destinationName = getDestinationJNDIName();

       InitialContext ic = null;
       Connection connection = null;

       try {

           ic = new InitialContext();

           ConnectionFactory cf = (ConnectionFactory)ic.lookup("/ConnectionFactory");
           Topic topic = (Topic)ic.lookup(destinationName);
           log("Topic " + destinationName + " exists");

           connection = cf.createConnection();
           Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
           MessageProducer publisher = session.createProducer(topic);
           MessageConsumer subscriber = session.createConsumer(topic);

           ExampleListener messageListener = new ExampleListener();
           subscriber.setMessageListener(messageListener);
           connection.start();

           TextMessage message = session.createTextMessage("Hello!");
           publisher.send(message);
           log("The message was successfully published on the topic");

           messageListener.waitForMessage();

           message = (TextMessage)messageListener.getMessage();
           log("Received message: " + message.getText());
           assertEquals("Hello!", message.getText());

           displayProviderInfo(connection.getMetaData());

       }finally{

           if(ic != null) {
               try {
                   ic.close();
               }catch(Exception e){
                   throw e;
               }
           }

           //ALWAYS close your connection in a finally block to avoid leaks
           //Closing connection also takes care of closing its related objects e.g. sessions
           closeConnection(connection);
       }
   }

   private void closeConnection(Connection con) throws JMSException {

       try {
           if (con != null) {
              con.close();
           }

       }catch(JMSException jmse) {
           log("Could not close connection " + con +" exception was " +jmse);
           throw jmse;
       }
   }


   protected boolean isQueueExample()
   {
      return false;
   }

   public static void main(String[] args)
   {
      new TopicExample().run();
   }

}
   

4.3. Using JMS from an EJB

This example deploys a simple Stateless Session Bean that is used as a proxy to send and receive JMS messages in a managed environment.

public class StatelessSessionExampleBean implements SessionBean
{

   private SessionContext ctx;

    private ConnectionFactory cf = null;

   public void drain(String queueName) throws Exception
   {
      InitialContext ic = new InitialContext();
      Queue queue = (Queue)ic.lookup(queueName);
      ic.close();

      Session session = null;
      Connection conn = null;

      try
      {
         conn = getConnection();
         session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageConsumer consumer = session.createConsumer(queue);
         Message m = null;
         do
         {
            m = consumer.receiveNoWait();
         }
         while(m != null);
      }
      finally
      {
         closeConnection(conn);
      }
   }

   public void send(String txt, String queueName) throws Exception
   {
      InitialContext ic = new InitialContext();
      Queue queue = (Queue)ic.lookup(queueName);
      ic.close();

      Session session = null;
      Connection conn = null;

       try
      {
         conn = getConnection();
         session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);

         MessageProducer producer = session.createProducer(queue);

         TextMessage tm = session.createTextMessage(txt);

         producer.send(tm);
         System.out.println("message " + txt + " sent to " + queueName);

      }
      finally
      {
         closeConnection(conn);
      }
   }

   public List browse(String queueName) throws Exception
   {
      InitialContext ic = new InitialContext();
      Queue queue = (Queue)ic.lookup(queueName);
      ic.close();

      Session session = null;
      Connection conn = null;

      try
      {
         conn = getConnection();
         session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         QueueBrowser browser = session.createBrowser(queue);

         ArrayList list = new ArrayList();
         for(Enumeration e = browser.getEnumeration(); e.hasMoreElements(); )
         {
            list.add(e.nextElement());
         }

         return list;
      }
      finally
      {
         closeConnection(conn);
      }
   }

   public String receive(String queueName) throws Exception
   {
      InitialContext ic = new InitialContext();
      Queue queue = (Queue)ic.lookup(queueName);
      ic.close();

      Session session = null;
      Connection conn = null;

      try
      {
         conn = getConnection();
         session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);

         MessageConsumer consumer = session.createConsumer(queue);

         System.out.println("blocking to receive message from queue " + queueName + " ...");
         TextMessage tm = (TextMessage)consumer.receive(5000);

         if (tm == null)
         {
            throw new Exception("No message!");
         }

         System.out.println("Message " + tm.getText() + " received");

         return tm.getText();

      }
      finally
      {
         closeConnection(conn);
      }
   }

    public Connection getConnection() throws Exception {

        Connection connection = null;

        try {
            connection = cf.createConnection();
            connection.start();

        }catch(Exception e ){
           if(connection != null)
               closeConnection(connection);
           System.out.println("Failed to get connection...exception is " +e);
           throw e;
        }

        return connection;
    }

    public void closeConnection(Connection con) throws Exception {

       try {
           if (con != null) {
               con.close();
           }

       }catch(JMSException jmse) {
           System.out.println("Could not close connection " + con +" exception was " +jmse);
           throw jmse;

       }
    }

   .......
    

4.4. Using EJB2.1 Message Driven Beans

This example deploys a simple Message Driven Bean that processes messages sent to a test queue. Once it receives a message and "processes" it, the MDB sends an acknowledgment message to a temporary destination created by the sender for this purpose. The example is considered successful if the sender receives the acknowledgment message.

The MDB ejb-jar.xml descriptor

<ejb-jar>
  <enterprise-beans>
    <message-driven>
      <ejb-name>MDBExample</ejb-name>
      <ejb-class>org.jboss.example.jms.mdb.MDBExample</ejb-class>
      <transaction-type>Container</transaction-type>
    </message-driven>
  </enterprise-beans>
</ejb-jar>
    

The MDB jboss.xml descriptor

<enterprise-beans>
  <message-driven>
    <ejb-name>MDBExample</ejb-name>
    <destination-jndi-name>queue/@QUEUE_NAME@</destination-jndi-name>
  </message-driven>
</enterprise-beans>
    
public class MDBExample implements MessageDrivenBean, MessageListener
{

   private MessageDrivenContext ctx;

   private ConnectionFactory cf = null;

   public void onMessage(Message m)
   {
      Session session = null;
      Connection conn = null;

      try
      {
         TextMessage tm = (TextMessage)m;

         String text = tm.getText();
         System.out.println("message " + text + " received");
         String result = process(text);
         System.out.println("message processed, result: " + result);

         conn = getConnection();
         session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);

         Destination replyTo = m.getJMSReplyTo();
         MessageProducer producer = session.createProducer(replyTo);
         TextMessage reply = session.createTextMessage(result);

         producer.send(reply);
         producer.close();

      }
      catch(Exception e)
      {
         ctx.setRollbackOnly();
         e.printStackTrace();
         System.out.println("The Message Driven Bean failed!");
      }
      finally
      {
         if (conn != null)
         {
            try {
                closeConnection(conn);
            }catch(Exception e){
                System.out.println("Could not close the connection!" +e);
            }
         }
      }
   }

   private String process(String text)
   {
      // flip the string

      String result = ";

      for(int i = 0; i < text.length(); i++)
      {
         result = text.charAt(i) + result;
      }
      return result;
   }

   public Connection getConnection() throws Exception {

        Connection connection = null;

        try {
            connection = cf.createConnection();
            connection.start();

        }catch(Exception e ){
           if(connection != null)
               closeConnection(connection);
           System.out.println("Failed to get connection...exception is " +e);
           throw e;
        }

        return connection;
    }

    public void closeConnection(Connection con) throws Exception {

       try {
           if (con = null) {
               con.close();
           }

       }catch(JMSException jmse) {
           System.out.println("Could not close connection " + con +" exception was " +jmse);
           throw jmse;
       }
    }

   ......
   

4.5. Using EJB3 Message Driven Beans

This example deploys a simple EJB3 Message Driven Bean that processes messages sent to a test queue. Once it receives a message and "processes" it, the MDB sends an acknowledgment message to a temporary destination created by the sender for this purpose. The example is considered successful if the sender receives the acknowledgment message.

This example relies on having access to a running JBoss Messaging instance. The JBoss Messaging instance must be installed and started according to the "Installation" chapter of this document. The example will automatically deploy its own queue, unless a queue with the same name is already deployed.

This example also relies on having access to the jboss-messaging-client.jar archive that comes with the release bundle. If you run this example from an unzipped installation bundle, the example run script is correctly configured to find the client jar. Otherwise, you must modify example's build.xml accordingly.

The example was designed to deploy its server-side artifacts under a JBoss' messaging configuration. If you intend to use the script with a JBoss configuration that is named differently, please modify the example's build.xml accordingly.

Important

The JBoss instance that runs the Messaging server must also have EJB3 support previously installed. If the EJB3 support is not installed, the example will fail with an error message similar to:
C:\work\src\cvs\jboss-head\jms\docs\examples\ejb3mdb\build.xml:60: EJB3 does not seem to be installed in C:\work\src\jboss-4.0.3-src\build\output\jboss-4.0.3/server/messaging! Install it and try again.
         

For instructions on how to install EJB3 support, please go to JBoss EJB3 documentation page or use the JBoss Installer.

The EJB3 Message Driven Bean source code:

        @MessageDriven(activateConfig =
        {
              @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
              @ActivationConfigProperty(propertyName="destination", propertyValue="queue/testQueue")
        })
        public class EJB3MDBExample implements MessageListener
        {
           public void onMessage(Message m)
           {
              businessLogic(m);
           }


           private void businessLogic(Message m)
           {
              Connection conn = null;
              Session session = null;

              try
              {
                 TextMessage tm = (TextMessage)m;

                 String text = tm.getText();
                 System.out.println("message " + text + " received");

                 // flip the string
                 String result = "";
                 for(int i = 0; i < text.length(); i++)
                 {
                    result = text.charAt(i) + result;
                 }

                 System.out.println("message processed, result: " + result);


                 InitialContext ic = new InitialContext();
                 ConnectionFactory cf = (ConnectionFactory)ic.lookup("java:/JmsXA");
                 ic.close();

                 conn = cf.createConnection();
                 conn.start();
                 session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);

                 Destination replyTo = m.getJMSReplyTo();
                 MessageProducer producer = session.createProducer(replyTo);
                 TextMessage reply = session.createTextMessage(result);

                 producer.send(reply);
                 producer.close();

              }
              catch(Exception e)
              {
                 e.printStackTrace();
                 System.out.println("The Message Driven Bean failed!");
              }
              finally
              {
                 if (conn != null)
                 {
                    try
                    {
                       conn.close();
                    }
                    catch(Exception e)
                    {
                       System.out.println("Could not close the connection!" +e);
                    }
                 }
              }
           }
        }
     

The basic test examples in this chapter serve as the sanity check for your JBoss Messaging installation. They also provide basic programming examples. To develop your own JMS services, you probably need to configure JBoss Messaging to setup your own destinations and connection factories etc. In Chapter 6, Configuration, we will discuss JBoss Messaging configuration files and options.