Implementing Command Handlers

Since 3.4

Overview

A Talon XVM has the ability to discover annotated 'Command' methods provided by an application. Such commands can be invoked remotely by tools in an out of band fashion with an application's message driven event handlers to perform administrative functions. The command framework is designed to work in the context of command line tools, guis or for administrative applications. A command method is identified by annotating it with a @Command annotation, and its parameters are exposed by annotating its parameters with either @Option or @Argument annotations which allows commands to be invoked by passing the arguments in a command line format.

@Command(name = "resetOrderStats",
         description="Resets the number of orders processed")
public String resetOrderStats(@Option(shortForm = 'v', longForm="verbose", defaultValue="false")
                         boolean verbose,
                         @Argument(name = "newOrderReceivedCount"), position=1)
                         long newNumOrdersReceived,
                         @Argument(name = "newOrderProcessingCount", position=2)
                         long newNumOrdersProcessed) { ... }

Annotating Command methods

At its simplest, a method that is composed of primitive arguments needs only to be annotated with a Command annotation to expose it as a command that can be invoked remotely.

Command Example:

@App
public void MyApp {
  @AppStat(name = "Orders Processed")
  private volatile long numOrdersProcessed = 0;

  /**
   * Resets the number of orders processed
   *
   * @param newNumOrdersProcessed The new number of orders processed
   * @return The previous number of orders
   */
  @Command
  public int resetOrdersProcessed(long newNumOrdersProcessed,
                                  boolean verbose) {
    long prevNumOrdersProcessed = numOrdersProcessed;
    numOrdersProcessed = numOrdersProcessed;
    String result = "Reset Orders Processed: " + prevNumOrdersProcessed + "->" + numOrdersProcessed;

    if(verbose) {
      System.out.println(result);
    }

    return result;
  }

  /**
   * Handles a new order.
   */
  @EventHandler
  public final void onOrder(NewOrderMessage newOrder) {
    numOrdersReceived++;

    // ... do some processing

    numOrdersProcessed++
  }
}

The above method can then be invoked via the Admin Tool in interactive mode:

... the command name is identified by the name of the method and each parameter in the signature is treated as an argument to the command.

@Command

Above we gave a simple example of using the Command annotation to identify a command. The command can be further described by using the following command annotation elements:

Parameter
Type
Description
Default

aliases

String []

Returns the aliases used to invoke this command. This can be useful in cases where a command's name has change and there is a need to support backwards compatibliity.

none

description

String

A description of the command. This is used by tools to expose usage information for the command. It is a good idea to provide a description on commands as it provides tools with the ability to provide usage information.

none

name

String

Returns the name of the command. If this parameter is omitted on an annotated Method then the name will default to the method name.

none

parseOptions

boolean

Whether or not the command parser should attempt to parse options or if this command is only comprised of arguments. This can be useful to avoid needing to escape argument values that may start with a '-' character.

true

@Argument

The @Argument annotation can be applied to method parameters to describe and constrain arguments.

Parameter
Type
Description
Default

name

String

A short name for the argument. This is used to identify the argument when displaying command line usage.

none

description

String

A brief description desribing what should be supplied for this argument. This is used to describe the argument when displaying command line usage

none

defaultValue

String

The argument's default value (if not a required argument. This value is converted from the String supplied to the argument's type.

null

required

boolean

Whether or not the argument is required. It is illegal to position a required argument after an optional one ... optional arguments.

true

position

int

The position of the argument on the command line. The 1 based position of the argument for command line invocation.

none

validOptions

String []

Indicates the set of permissible values for the argument.

NULL

Below is an example of how an Argument annotation may be used:

@Option

The @Option annotation can be applied to method parameters. An Option differs from an argument in that it is invoked using a command line switch. Options are useful in cases where a command method signature needs to be changed as scripts written against the old command signature will continue to function.

Parameter
Type
Description
Default

shortForm

char

The short (switch e.g. -o) form for the option.

none

longForm

String

The long form for the argument (e.g. --option)).

none

description

String

A brief description of the Option.

defaultValue

String

The option's default value. When the option is not specified the option will be set to this value.

null

required

boolean

Whether or not the option is required. If the option is not specified but there is a default value, then the default will be used, otherwise it is an error.

true

validOptions

String []

Indicates the set of permissible values for the option.

NULL

Below is an example of how an Argument annotation may be used:

Supported Types for Options, Arguments And Return values:

The following types are returned when describing the command usage. In Json they are represented as the name from the enumeration below. The expectation is that tools will use this options in forms.

Valid Arguments and Options types:

  • boolean or Boolean

  • byte or Byte

  • char or Char

  • short or Short

  • int or Integer

  • long or Long

  • float or Float

  • double or Double

  • date or Date

  • String

  • Enumerations (converted to/from a String when sent over the wire).

Valid return types

All of the support argument types above and void.

Registering Command Handlers with the runtime.

@AppCommandHandlerContainersAccessor

Any @Command annotated method in the main application class will be discovered by a Talon XVM. If additional classes in your application contain @Command methods, they can be exposed to the Talon XVM using the @AppCommandHandlerContainersAccessor annotation which should add all objects that should be introspected for command handlers.

Example:

Configuration Discovery in Hornet

For Topic Oriented Applications, any @Managed object will be introspected for @Command methods. See ManagedObjectLocator. The DefaultManagedObjectLocator for Hornet calls TopicOrientedApplication.addAppCommandHandlerContainers(Set), so unless your application provides its own managed object locator, additional configured containers can be added by overriding addConfiguredContainers():

Invoking Annotated Commands

Annotated command handlers can be discovered and invoked by deployment and administrative tools via admin connections made to the XVM in which the application is running.

Examples / Appendix

A Fully Annotated Command

The below command handler exercises all of the annotation features:

Usage as Printed By SrvMonUtil

Json Command Description:

Next Steps

  1. Define command handlers for your application

  2. Annotate methods with @Command, @Argument, and @Option

  3. Register command handler containers if needed

  4. Test commands using the Admin Tool or administrative tools

  5. Document available commands for operators

Last updated