ActiveMQ Artemis Management Notification Example

# Management Notification Example

    To run the example, simply type mvn verify from this directory,
    or mvn -PnoServer verify if you want to start and create the server manually.

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

x

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

                InitialContext initialContext = getContext(0);

2. We look up the JMS queue object from JNDI

                Queue queue = (Queue) initialContext.lookup("/queue/exampleQueue");

3. We look up the JMS connection factory object from JNDI

                ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("/ConnectionFactory");

4. We create a JMS connection, a session and a message producer for the example queue

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

5. We look up the JMS Topic used to receive the notifications from JNDI

                Topic notificationsTopic = (Topic) initialContext.lookup("/topic/notificationsTopic");

6. 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

               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("------------------------");
                  }
               });

7. We start the connection to receive messages

                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

8. We create a JMS message consumer on the example queue

                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

9. We close this consumer

                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

10. As a last example, we will create a connection with invalid user credentials

                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.

11. 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

               finally
               {
                  if (initialContext != null)
                  {
                    initialContext.close();
                  }
                  if (connection != null)
                  {
                     connection.close();
                  }
               }

## More information

- User Manual's Management Notifications chapter