High Quality JMS & AMQP Messaging.

Introduction

CLI may be activated out of a Java program for programmatic administration. This administration API offers a simple but powerful instrument to the administration of SwiftMQ router networks. The administration takes place by performing any CLI command via an executeCommand method of CLI. All property values and entities of routers of the network may be inquired by the API. Furthermore it is possible to wait for the availability of certain routers or to receive notification events.

Preparation

The following import needs to exist to use the CLI Admin API:

    import com.swiftmq.admin.cli.*;

If router events should be received, the following further import statement is needed:

    import com.swiftmq.admin.cli.event.*;

CLI requires a QueueConnection in stopped mode (default on creation). The user of this QueueConnection needs to have full administration rights of the routers to be administered. This is the case when placing send/receive grants to the queue swiftmqmgmt of the respective routers.

Creation of a QueueConnection:

    QueueConnection connection = null;
    try {
      Hashtable env = new Hashtable();
      env.put(Context.INITIAL_CONTEXT_FACTORY,"com.swiftmq.jndi.InitialContextFactoryImpl");
      env.put(Context.PROVIDER_URL,"smqp://localhost:4001/timeout=10000");
      InitialContext ctx = new InitialContext(env);
      QueueConnectionFactory connectionFactory =
                            (QueueConnectionFactory)ctx.lookup("QueueConnectionFactory");
      connection = connectionFactory.createQueueConnection();
      ctx.close();
    } catch (Exception e)
    {
      System.out.println(e);
      System.exit(-1);
    }

After that CLI may be created:

    CLI cli = null;
    try {
      cli = new CLI(connection);
    } catch (Exception e)
    {
      System.out.println(e);
      System.exit(-1);
    }

At construction, CLI produces several sessions and starts the connection.

Waiting for Routers

After creating CLI it receives asynchronous availability notifications by the network routers. A router may not be administered until he is available. One can wait for the availability to administer a specific router. This is done by calling the method waitForRouter. This method exists in two versions, one without and one with timeout. The one without timeout waits until the router is available. The one with timeout waits until the availability or until timeout. If the router is already available at call of the method, it returns straight away.

Example without timeout:

    cli.waitForRouter("router1");

Example with timeout:

    cli.waitForRouter("router1", 20000); // max 20 secs

Router Listener

Beside the synchronous waitForRouter methods a RouterListener may also be registered. In this case, CLI informs these listeners asynchronous by router availabilities.

Example:

    cli.addRouterListener(new RouterListener()
    {
      public void onRouterEvent(String routerName, boolean available)
      {
        System.out.println("Router '"+routerName+"' is "+(available?"AVAILABLE":"UNAVAILABLE"));
      }
    });

Getting available Routers

CLI may be requested at any time, which routers are currently available. This is done by the method getAvailableRouters. The method returns a string array with router names.

Example:

    String[] availableRouters = cli.getAvailableRouters();

Getting the actual Router

The router, mentioned at the last "sr" command is the current one. It may be requested by getActRouter. If no "sr" command has been set, null is passed back.

Example:

    System.out.println("Act Router: "+cli.getActRouter());

Getting the actual Context

The context, given at the last "cc" command, is the current one. It may be requested by getActContext. If no "cc" command has been set, null is passed back. After a "sr" command, "/" is the current context.

Example:

    System.out.println("Act Context: "+cli.getActContext());

Getting Context Entities

After setting the actual context with 'cc', it is possible to get the actual entity names defined whithin this context.

Example:

    cli.executeCommand("sr router1");
    // getting all defined queues
    cli.executeCommand("cc /sys$queuemanager/queues");
    String[] allQueueNames = cli.getContextEntities();
    // getting all defined users
    cli.executeCommand("cc /sys$authentication/users");
    String[] allUserNames = cli.getContextEntities();

Executing CLI Commands

The execution of CLI commands takes place by the method executeCommand, which has the corresponding CLI command as parameter. Here it is to be taken into account that the command mustn't deliver a result, otherwise a CLIException is thrown. Thus, commands like "lc", "ar", "show template" are unauthorized.

Example:

    cli.waitForRouter("router1");
    try {
      cli.executeCommand("sr router1");
      cli.executeCommand("cc /sys$queuemanager/queues");
      cli.executeCommand("new mynewqueue cache.size 1000");
      cli.executeCommand("save");
    } catch (CLIException e)
    {
      processError(e);
    }

This example creates a new queue and saves the configuration.

Getting Property Values

After setting oneself in a context by "cc", any property in this context may be read out. This is done by the method getContextProperty. The name of the property is given as parameter. The current value is given back as String type. If the property is unknown within the current context, a CLIException is thrown. If the property value is null, null will be passed back.

Example:

    cli.executeCommand("sr router1");
    cli.executeCommand("cc /sys$queuemanager/queues/mynewqueue");
    int cacheSize = Integer.parseInt(cli.getContextProperty("cache.size"));

Closing CLI

With completion of the use of CLI Admin API, it should be closed by close(). Hereby, all resources used by CLI are released. The QueueConnection given with the construction is not closed and remains in the started mode.

Example:

    cli.close();

Exception Listener

In order to recognize if the QueueConnection committed to CLI got lost, a JMS ExceptionListener needs to be registered at the QueueConnection and it needs to be responded accordingly.

Transparent Reconnect

Since SwiftMQ 6.0 it is possible to configure JMS connection factories to automatically and transparent reconnect to the same or (in case SwiftMQ HA Router is used) to another router instance. If CLI is created with a connection from a connection factory configured for transparent reconnect, CLI will reconnect as well and will restore its internal state. However, it does not restore the router, set with the last "sr" command nor the last CLI context, set with a "cc" command. This is the responsibility of the application that uses CLI admin API.

The CLI methods throw a CLIReconnectedException (extends CLIException) if a command failes and a reconnect happend in the meantime (so the reason for the exception is actually a reconnect). An application must catch CLIReconnectedException and must restore the last router and context by issuing the appropriate "sr" and "cc" commands (a call to "waitForRouter" may also be required). Thereafter it must issue the failed command again.

The following example polls the free and total memory properties of the management tree and acts on a CLIReconnectedException:

    // Setup the CLI context
    private static void setUp()
    {
      try
      {
        cli.waitForRouter("router1");
        cli.executeCommand("sr router1");
        cli.executeCommand("cc .env/router-memory-list/router1");
      } catch (CLIException e)
      {
      }
    }

    // Get a value from a property
    private static String getValue(String propName)
    {
      for (;;)
      {
        try
        {
          return cli.getContextProperty(propName);
        } catch (CLIReconnectedException e)
        {
          setUp();
        } catch (CLIException e)
        {
          e.printStackTrace();
        }
      }
    }

    // And here's the main loop...
    public static void main(String[] args)
    {
      // Lookup connection factory, create connection, create CLI
      // (excluded here)

      // First time context set up
      setUp();

      // Continuously poll and print memory status of the router
      for (; ;)
      {
        System.out.println("Free: " + getValue("free-memory") + " Total: " + getValue("total-memory"));
        try
        {
          Thread.sleep(1000);
        } catch (InterruptedException e)
        {
        }
      }
    }

Example

The SwiftMQ distribution contains an example "AdminClient.java" within the directory "samples/cli". This is an easy administration client, that reads CLI commands by System.in and executes them.

Javadoc

Click on the link below to look at the CLI javadoc.

CLI javadoc.