Management Notification Example

This example shows how to receive management notifications from ActiveMQ Artemis using JMS Messages.

ActiveMQ Artemis servers emit management notifications when events of interest occur (consumers are created or closed, destinations are created or deleted, security authentication fails, etc.).
These notifications can be received either by using JMX (see JMX example) or by receiving JMS Messages from a well-known destination.

This example will setup a JMS MessageListener to receive management notifications. We will also perform normal JMS operations to see the kind of notifications they trigger.

Example configuration

ActiveMQ Artemis can configured to send JMS messages when management notifications are emitted on the server.

By default, the management name is called activemq.notifications but this can be configured in broker.xml. For this example, we will set it to jms.topic.notificationsTopic to be able to receive notifications from a JMS Topic.

         <management-notification-address>jms.topic.notificationsTopic</management-notification-address>
     

Since we want to lookup the notifications topic using JNDI, we also declare it in activemq-jms.xml

         <topic name="notificationsTopic">
            <entry name="/topic/notificationsTopic"/>
         </topic>
     

The notification queue requires permission to create/delete temporary queues and consume messages. This is also configured in broker.xml

         
         <security-setting match="jms.topic.notificationsTopic">
            <permission type="consume" roles="guest"/>
            <permission type="createNonDurableQueue" roles="guest"/>
            <permission type="deleteNonDurableQueue" roles="guest"/>
         </security-setting>
     

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 its properties from client-jndi.properties
  2.             InitialContext initialContext = getContext(0);
            
  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, a session and a message producer for the example queue
  8.             connection = cf.createConnection();
                Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                MessageProducer producer = session.createProducer(queue);
            
  9. We look up the JMS Topic used to receive the notifications from JNDI
  10.             Topic notificationsTopic = (Topic) initialContext.lookup("/topic/notificationsTopic");
            
  11. We create a MessageConsumer for the notification queue and set its MessageListener. When a notification is received, we will simply display all the message properties
  12.            MessageConsumer notificationConsumer = session.createConsumer(notificationsTopic);
               notificationConsumer.setMessageListener(new MessageListener()
               {
                  public void onMessage(Message notif)
                  {
                     System.out.println("------------------------");
                     System.out.println("Received notification:");
                     try
                     {
                        Enumeration propertyNames = notif.getPropertyNames();
                        while (propertyNames.hasMoreElements())
                        {
                           String propertyName = (String)propertyNames.nextElement();
                           System.out.format("  %s: %s\n", propertyName, notif.getObjectProperty(propertyName));
                        }
                     }
                     catch (JMSException e)
                     {
                     }
                     System.out.println("------------------------");
                  }            
               });
            
  13. We start the connection to receive messages
  14.             connection.start();
            

    Now that a message listener is setup to receive management notifications, we will perform regular JMS operations to see what kind of notifications are triggered

  15. We create a JMS message consumer on the example queue
  16.             MessageConsumer consumer = session.createConsumer(queue);
            

    This will generate a CONSUMER_CREATED notification:

                ------------------------
                Received notification:
                  _AMQ_RoutingName: jms.queue.exampleQueue
                  _AMQ_Address: jms.queue.exampleQueue
                  ...
                  _AMQ_ConsumerCount: 1
                  ...
                  _AMQ_NotifType: CONSUMER_CREATED
                ------------------------
            

    The notification tells us that a consumer was created for the JMS queue exampleQueue. When the notification was emitted, this consumer was the only one for the queue

  17. We close this consumer
  18.             consumer.close();
            

    This will generate a CONSUMER_CLOSED notification:

                ------------------------
                Received notification:
                  _AMQ_RoutingName: jms.queue.exampleQueue
                  _AMQ_Address: jms.queue.exampleQueue
                  ...
                  _AMQ_ConsumerCount: 0
                  ...
                  _AMQ_NotifType: CONSUMER_CLOSED
                ------------------------
            

    The notification tells us that a consumer was closed for the JMS queue exampleQueue. When the notification was emitted, there were no other consumers on the queue

  19. As a last example, we will create a connection with invalid user credentials
  20.             try
                {
                   cf.createConnection("not.a.valid.user", "not.a.valid.password");
                } catch (JMSException e)
                {            
                }
            

    This will generate a SECURITY_AUTHENTICATION_VIOLATION notification:

                ------------------------
                Received notification:
                  _AMQ_User: not.a.valid.user
                  ...
                  _AMQ_NotifType: SECURITY_AUTHENTICATION_VIOLATION
                ------------------------
                
            

    The notification tells us that a user named not.a.valid.user failed to authenticate when creating a connection to ActiveMQ Artemis.

  21. 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
  22.            finally
               {
                  if (initialContext != null)
                  {
                    initialContext.close();
                  }
                  if (connection != null)
                  {
                     connection.close();
                  }
               }
            

More information