Introduction

CLI may be activated out of a Java program for programmatic administration. This administration API offers a simple but powerful instrument for 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 can be retrieved. 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.*;
JAVA

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

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

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);
    }
JAVA

After that CLI may be created:

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

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

Waiting for Routers

After creating CLI it receives asynchronous availability notifications from the network routers. A router may not be administered until it 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 a 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 the call of the method, it returns straight away.

Example without timeout:

    cli.waitForRouter("router1");
JAVA

Example with timeout:

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

Router Listener

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

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();
JAVA

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());
JAVA

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 an sr command, / is the current context.

Example:

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

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();
JAVA

Executing CLI Commands

The execution of CLI commands takes place by the method executeCommand, which has the corresponding CLI command as a 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);
    }
JAVA

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 readout. This is done by the method getContextProperty. The name of the property is given as a 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"));
JAVA

Closing CLI

With the 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();
JAVA

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 to accordingly.

Transparent Reconnect

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 fails and a reconnect happened 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)
        {
        }
      }
    }
JAVA

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.