JMS Message Counter Example

This example shows you how to use message counters to obtain message information for a JMS queue.

The example will show how to configure sampling of message counters.
We will produce and consume 1 message from a queue. Interleaved with the JMS operation, we will retrieve the queue's message counters at different times to display the metrics on the queue.

Example setup

Message counter is configured in the server configuration file broker.xml:

         <message-counter-enabled>true</message-counter-enabled>
         <message-counter-sample-period>2000</message-counter-sample-period>
         <message-counter-max-day-history>2</message-counter-max-day-history>
     

By default, Message counter is not enabled (for performance reason). To enable them, set message-counter-enabled to true.
Queues are sampled every 10 seconds by default. For this example we will reduce it to 2 seconds by setting message-counter-sample-period to 2000.
ActiveMQ Artemis holds in memory the message counters' history for a maximum number of days (10 by default). We can change the number of days the history is kept by setting the message-counter-max-day-history parameter.

The sample period and the max day history parameters have an small impact on the performance of ActiveMQ Artemis (the resources taken to sample a queue are not available to the system's normal use). You should set these parameters accordingly to the use and throughput of your messages.

Example step-by-step

To run the example, simply type mvn verify -Pexample from this directory

  1. First we need to get an initial context so we can look-up the JMS connection factory and destination objects from JNDI. This initial context will get it's properties from the client-jndi.properties file in the directory ../common/config
  2.            InitialContext initialContext = getContext();
            
  3. We look up the JMS queue object from JNDI
  4.            Queue queue = (Queue) initialContext.lookup("/queue/exampleQueue");
            
  5. We look up the JMS connection factory object from JNDI
  6.            ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("/ConnectionFactory");
            
  7. We create a JMS connection, session and producer for the queue
  8.             connection = cf.createQueueConnection();
                QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
                MessageProducer producer = session.createProducer(queue);
           
  9. We create and send a JMS text message
  10.             TextMessage message = session.createTextMessage("This is a text message");
                producer.send(message);
                System.out.println("Sent message: " + message.getText());
            
  11. We will now sleep a little bit to be sure the queue is sample. Since we have configure the sample period to be 2 seconds, we will sleep for 3 seconds to be sure that a sample is taken
  12.             System.out.println("Sleep a little bit to have the queue sampled...");
                Thread.sleep(3000);
            

    We now need to retrieve the message counters. They're available from the JMS Queue management resource. In this example, we will retrieve them using JMX (see the JMX example for a more complete description). You can also use JMS message to retrieve them (see the Management example to learn about managing ActiveMQ Artemis using JMS messages).

  13. We retrieve the JMX MBean used to manage the JMS queue
  14.             ObjectName on = ObjectNameBuilder.DEFAULT.getJMSQueueObjectName(queue.getQueueName());
                JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(JMX_URL), new HashMap());
                MBeanServerConnection mbsc = connector.getMBeanServerConnection();
                JMSQueueControl queueControl = (JMSQueueControl)MBeanServerInvocationHandler.newProxyInstance(mbsc,
                                                                                                  on,
                                                                                                  JMSQueueControl.class,
                                                                                                  false);
            
  15. We retrieve the message counter and display them. MessageCounters are retrieved as JSON Strings for portability reason (whether JMX is used for management or JMS messages). To make it simpler to use them in the code, there is a MessageCounterInfo data structure.
  16.             String counters = queueControl.listMessageCounter();
                MessageCounterInfo messageCounter = MessageCounterInfo.fromJSON(counters);>
            
  17. We display the message counters
  18.             displayMessageCounter(messageCounter);
            

    The message counter contains a variety of metrics on the queue which is sampled (total messages added to the queue, current depth of the queue, deltas since the last sample, timestamp of the last message added, timestamp of the last sample, etc.)

                
                private void displayMessageCounter(MessageCounterInfo counter)
                {
                   System.out.format("%s (sample updated at %s)\n",  counter.getName(), counter.getUdpateTimestamp());
                   System.out.format("   %s message(s) added to the queue (since last sample: %s)\n", counter.getCount(), 
                                                                                                      counter.getCountDelta());
                   System.out.format("   %s message(s) in the queue (since last sample: %s)\n", counter.getDepth(),
                                                                                                counter.getDepthDelta());
                   System.out.format("   last message added at %s\n\n", counter.getLastAddTimestamp());
                }
            
  19. We sleep again to have the queue sampled
  20.             System.out.println("Sleep a little bit again...");
                Thread.sleep(3000);
            
  21. We list the message counters again
  22.             counters = queueControl.listMessageCounter();
                messageCounter = MessageCounterInfo.fromJSON(counters);
                displayMessageCounter(messageCounter);
            

    We will now consume a message from the queue before listing a last time the message counters

  23. We create a consumer for the queue
  24.             MessageConsumer consumer = session.createConsumer(queue);
            
  25. We start the connection to receive messages on the consumer
  26.            connection.start();
            
  27. We receive a message from the queue
  28.            TextMessage messageReceived = (TextMessage)consumer.receive(5000);
               System.out.format("Received message: %s\n\n", messageReceived.getText());
            
  29. We sleep one last time to have the queue sampled
  30.             System.out.println("Sleep a little bit one last time...");
                Thread.sleep(3000);
            
  31. We list the message counters a final time (this time with no message in the queue)
  32.             counters = queueControl.listMessageCounter();
                messageCounter = MessageCounterInfo.fromJSON(counters);
                displayMessageCounter(messageCounter);
            

  33. And finally, always remember to close your JMS connections and resources after use, in a finally block. Closing a JMS connection will automatically close all of its sessions, consumers, producer and browser objects
  34.            finally
               {
                  if (initialContext != null)
                  {
                    initialContext.close();
                  }
                  if (connection != null)
                  {
                     connection.close();
                  }
               }
            
  • User Manual's Message Counters chapter
  • MessageCounterInfo is a helper class used to create a MessageCounterInfo object from the JSON String which represents message counters