In This Section

Work in Progress

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 allow commands to be invoked by passing the arguments in a command line:

 

  @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)

 

Command Annotations

TODO Describe @Command, @Option, @Argument, and @RemainingArgs

@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++
  }
} 
@Command(name = "resetOrderStats", 
         description="Resets the number of orders processed")
public int resetOrdersProcessed(@Option(shortForm = 'v', longForm ="verbose", defaultValue="false")
                                boolean verbose,
                                @Argument(name = "newOrderProcessingCount", position=1)
                                long newNumOrdersProcessed)

Command Invocation

Robin API

The command above can be invoked programmatically using a Robin Controller:

Controller controller = new Controller();
Server server = Controller.getModel().getServer("MyVM");
App orderProcessingApp = server.getApp("OrderProcessing");
System.out.println(app.invokeCommand("resetOrdersProcessed -v true 0"));

Robin Script

instruct the OrderProcessing app in the MyVM xvm to resetOrdersProcessed with -v true 0

Robin Command Line Tool

>invoke MyVM OrderProcessing resetOrdersProcessed -v true 0
SUCCESS: 10000 

Escaping

Commands are invoked on the server using a command line style interface in which parameters are passed to the command being executing as option or argument token separated by one or more whitespace characters. The rules for escaping are straightforward:

The following simple command serves to demonstrate when escaping is necessary. This command prints a given line to either System.err or System.out:

@Command
public println(@Argument(position= 1, name="text") String line, 
               @Argument(position= 2, name="errorCode", required=false) int errorCode, 
               @Option(shortForm ='e', longForm="error", boolean err) {
  if(err) {
	System.err.println("ERROR [" + errorCode + "]:" + line);
  }
  else {
	System.out.println(line);
  }
}

Passing A String with Spaces 
 

invoke myVM myApp println "My String"
instruct the myApp app in the myVM xvm to println with "My String"
app.invoke("println \"My String\")

The above will result in the following being printed to System.out in the App:

My String

Passing A String with Quotes 

Note that below we escape the quote characters within the quoted string:

invoke myVM myApp println -e "\"My Error\""
instruct the myApp app in the myVM xvm to println with -e "\"My Error\""
app.invoke("println -e \"\\"My String\\"\")

All of the above will result in the following being printed to System.error in the App (with the quotes preserved). Not that in the java case that the extra escapes are needed to escape the '\' character. 

ERROR [0]: "My Error"

Passing Argument Starting With A Dash

Note that below we escape the quote characters within the quoted string:

invoke myVM myApp println -e \--BAD_TIMES-- \-10
instruct the myApp app in the myVM xvm to println with -e \--BAD_TIMES-- \-10
app.invoke("println -e \--BAD_TIMES-- \-10)

All of the above will result in the following being printed to System.error in the App (with the quotes preserved)

ERROR[-10]: --BAD_TIMES--

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. 

      <enum name="SrvMonArgumentType" type="int">
        <documentation>Enumerates the valid types for command arguments</documentation>
        <const name="BOOLEAN" value="1" />
        <const name="BYTE" value="2" />
        <const name="CHAR" value="3" />
        <const name="SHORT" value="4" />
        <const name="INT" value="5" />
        <const name="LONG" value="6" />
        <const name="FLOAT" value="7" />
        <const name="DOUBLE" value="8" />
        <const name="DATE" value="9" />
        <const name="STRING" value="10" />
      </enum>
      <enum name="SrvMonOptionType" type="int">
        <documentation>Enumerates the valid types for command options</documentation>
        <const name="BOOLEAN" value="1" />
        <const name="BYTE" value="2" />
        <const name="CHAR" value="3" />
        <const name="SHORT" value="4" />
        <const name="INT" value="5" />
        <const name="LONG" value="6" />
        <const name="FLOAT" value="7" />
        <const name="DOUBLE" value="8" />
        <const name="DATE" value="9" />
        <const name="STRING" value="10" />
      </enum>
      <enum name="SrvMonReturnType" type="int">
        <documentation>Enumerates the valid types for command return values</documentation>
        <const name="BOOLEAN" value="1" />
        <const name="BYTE" value="2" />
        <const name="CHAR" value="3" />
        <const name="SHORT" value="4" />
        <const name="INT" value="5" />
        <const name="LONG" value="6" />
        <const name="FLOAT" value="7" />
        <const name="DOUBLE" value="8" />
        <const name="DATE" value="9" />
        <const name="STRING" value="10" />
      </enum>

Examples

A Fully Annotated Command

    @Command(name = "testCommand", aliases = { "TestCommandAlias" }, description = "A command that exercises all of the invocation APIs")
    public String testCommand(@Option(shortForm = 'b', longForm = "byteOption", required = true, description = "Tests a byte Option", validOptions = { "0,", "1" }, defaultValue = "0") byte aByteOption,
                              @Option(shortForm = 'c', longForm = "charOption", required = true, description = "Tests a char Option", validOptions = { "a,", "b", "c" }, defaultValue = "b") char aCharOption,
                              @Option(shortForm = 'n', longForm = "shortOption", required = true, description = "Tests a short Option", validOptions = { "399,", "300" }, defaultValue = "399") short aShortOption,
                              @Option(shortForm = 'i', longForm = "intOption", required = true, description = "Tests a int Option", validOptions = { "20000,", "200000" }, defaultValue = "200000") int aIntOption,
                              @Option(shortForm = 'l', longForm = "longOption", required = true, description = "Tests a long Option", validOptions = { "100000000,", "2000000000" }, defaultValue = "100000000") long aLongOption,
                              @Option(shortForm = 'f', longForm = "floatOption", required = true, description = "Tests a float Option", validOptions = { "0.0,", "-2.0" }, defaultValue = "0.0") float aFloatOption,
                              @Option(shortForm = 'd', longForm = "doubleOption", required = true, description = "Tests a double Option", validOptions = { "0.0,", "1.2" }, defaultValue = "1.2") double aDoubleOption,
                              @Option(shortForm = 's', longForm = "stringOption", required = true, description = "Tests a String Option", validOptions = { "Foo,", "Bar" }, defaultValue = "Foo") String aStringOption,
                              @Option(shortForm = 'm', longForm = "currencyOption", required = true, description = "Tests a Currency Option", validOptions = { "USD,", "JPY" }, defaultValue = "JPY") Currency aCurrencyOption,
                              @Option(shortForm = 'e', longForm = "enumOption", required = true, description = "Tests a Enum Option", defaultValue = "PrettyPrint") JsonPrettyPrintStyle aEnumOption,
                              @Argument(position = 1, required = true, name = "aByteArgument", description = "Tests a byte Arguement", validOptions = { "0,", "1" }, defaultValue = "0") byte aByteArgument,
                              @Argument(position = 2, required = true, name = "aCharArgument", description = "Tests a char Arguement", validOptions = { "a,", "b", "c" }, defaultValue = "a") char aCharArgument,
                              @Argument(position = 3, required = true, name = "aShortArgument", description = "Tests a short Arguement", validOptions = { "399,", "300" }, defaultValue = "300") short aShortArgument,
                              @Argument(position = 4, required = true, name = "aIntArgument", description = "Tests a int Arguement", validOptions = { "20000,", "200000" }, defaultValue = "200000") int aIntArgument,
                              @Argument(position = 5, required = true, name = "aLongArgument", description = "Tests a long Arguement", validOptions = { "100000000,", "2000000000" }, defaultValue = "100000000") long aLongArgument,
                              @Argument(position = 6, required = true, name = "aFloatArgument", description = "Tests a float Arguement", validOptions = { "0.0,", "-2.01" }, defaultValue = "-2.01") float aFloatArgument,
                              @Argument(position = 7, required = true, name = "aDoubleArgument", description = "Tests a double Arguement", validOptions = { "0.0,", "1.2" }, defaultValue = "0.0") double aDoubleArgument,
                              @Argument(position = 8, required = true, name = "aStringArgument", description = "Tests a String Arguement", validOptions = { "Foo,", "Bar" }, defaultValue = "Foo") String aStringArgument,
                              @Argument(position = 9, required = true, name = "aCurrencyArgument", description = "Tests a Currency Arguement", validOptions = { "USD,", "JPY" }, defaultValue = "USD") Currency aCurrencyArgument,
                              @Argument(position = 10, required = true, name = "aEnumArgument", description = "Tests a Enum Arguement", defaultValue = "Minimal") JsonPrettyPrintStyle aEnumArgument) throws Exception {
        return "Received Arguments: " + Arrays.asList(new Object[] {
                                                                    aByteOption,
                                                                    aCharOption,
                                                                    aShortOption,
                                                                    aIntOption,
                                                                    aLongOption,
                                                                    aFloatOption,
                                                                    aDoubleOption,
                                                                    aStringOption,
                                                                    aCurrencyOption,
                                                                    aEnumOption,
                                                                    aByteArgument,
                                                                    aCharArgument,
                                                                    aShortArgument,
                                                                    aIntArgument,
                                                                    aLongArgument,
                                                                    aFloatArgument,
                                                                    aDoubleArgument,
                                                                    aStringArgument,
                                                                    aCurrencyArgument,
                                                                    aEnumArgument }).toString();
    }

 

Usage as Printed By SrvMonUtil

testCommand
A command that exercises all of the invocation APIs
 Usage:
  testCommand -b -c -n -i -l -f -d -s -m -e <aByteArgument> <aCharArgument> <aShortArgument> <aIntArgument> <aLongArgument> <aFloatArgument> <aDoubleArgument> <aStringArgument> <aCurrencyArgument> <aEnumArgument> 
       <-b|--byteOption> <1|0,> Tests a byte Option default='0'
       <-c|--charOption> <a,|b|c> Tests a char Option default='b'
       <-n|--shortOption> <300|399,> Tests a short Option default='399'
       <-i|--intOption> <200000|20000,> Tests a int Option default='200000'
       <-l|--longOption> <100000000,|2000000000> Tests a long Option
           default='100000000'
       <-f|--floatOption> <0.0,|-2.0> Tests a float Option default='0.0'
       <-d|--doubleOption> <0.0,|1.2> Tests a double Option default='1.2'
       <-s|--stringOption> <Bar|Foo,> Tests a String Option default='Foo'
       <-m|--currencyOption> <JPY|USD,> Tests a Currency Option
           default='JPY'
       <-e|--enumOption> Tests a Enum Option default='PrettyPrint'
       [aByteArgument: <1|0,> Tests a byte Arguement default='0']
       [aCharArgument: <a,|b|c> Tests a char Arguement default='a']
       [aShortArgument: <300|399,> Tests a short Arguement default='300']
       [aIntArgument: <200000|20000,> Tests a int Arguement
           default='200000']
       [aLongArgument: <100000000,|2000000000> Tests a long Arguement
           default='100000000']
       [aFloatArgument: <0.0,|-2.01> Tests a float Arguement
           default='-2.01']
       [aDoubleArgument: <0.0,|1.2> Tests a double Arguement default='0.0']
       [aStringArgument: <Bar|Foo,> Tests a String Arguement default='Foo']
       [aCurrencyArgument: <JPY|USD,> Tests a Currency Arguement
           default='USD']
       [aEnumArgument: Tests a Enum Arguement default='Minimal']

Json Command Description:

      "name": "testCommand",
      "aliases": [
        "TestCommandAlias"
      ],
      "description": "A command that exercises all of the invocation APIs",
      "arguments": [
        {
          "position": 1,
          "required": true,
          "type": "BYTE",
          "name": "aByteArgument",
          "defaultValue": "0",
          "validValues": [
            "1",
            "0,"
          ],
          "description": "Tests a byte Arguement",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "position": 2,
          "required": true,
          "type": "CHAR",
          "name": "aCharArgument",
          "defaultValue": "a",
          "validValues": [
            "a,",
            "b",
            "c"
          ],
          "description": "Tests a char Arguement",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "position": 3,
          "required": true,
          "type": "SHORT",
          "name": "aShortArgument",
          "defaultValue": "300",
          "validValues": [
            "300",
            "399,"
          ],
          "description": "Tests a short Arguement",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "position": 4,
          "required": true,
          "type": "INT",
          "name": "aIntArgument",
          "defaultValue": "200000",
          "validValues": [
            "200000",
            "20000,"
          ],
          "description": "Tests a int Arguement",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "position": 5,
          "required": true,
          "type": "LONG",
          "name": "aLongArgument",
          "defaultValue": "100000000",
          "validValues": [
            "100000000,",
            "2000000000"
          ],
          "description": "Tests a long Arguement",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "position": 6,
          "required": true,
          "type": "FLOAT",
          "name": "aFloatArgument",
          "defaultValue": "-2.01",
          "validValues": [
            "0.0,",
            "-2.01"
          ],
          "description": "Tests a float Arguement",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "position": 7,
          "required": true,
          "type": "DOUBLE",
          "name": "aDoubleArgument",
          "defaultValue": "0.0",
          "validValues": [
            "0.0,",
            "1.2"
          ],
          "description": "Tests a double Arguement",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "position": 8,
          "required": true,
          "type": "STRING",
          "name": "aStringArgument",
          "defaultValue": "Foo",
          "validValues": [
            "Bar",
            "Foo,"
          ],
          "description": "Tests a String Arguement",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "position": 9,
          "required": true,
          "type": "STRING",
          "name": "aCurrencyArgument",
          "defaultValue": "USD",
          "validValues": [
            "JPY",
            "USD,"
          ],
          "description": "Tests a Currency Arguement",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "position": 10,
          "required": true,
          "type": "STRING",
          "name": "aEnumArgument",
          "defaultValue": "Minimal",
          "description": "Tests a Enum Arguement",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        }
      ],
      "options": [
        {
          "shortForm": "b",
          "required": true,
          "type": "BYTE",
          "longForm": "byteOption",
          "defaultValue": "0",
          "validValues": [
            "1",
            "0,"
          ],
          "description": "Tests a byte Option",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "shortForm": "c",
          "required": true,
          "type": "CHAR",
          "longForm": "charOption",
          "defaultValue": "b",
          "validValues": [
            "a,",
            "b",
            "c"
          ],
          "description": "Tests a char Option",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "shortForm": "n",
          "required": true,
          "type": "SHORT",
          "longForm": "shortOption",
          "defaultValue": "399",
          "validValues": [
            "300",
            "399,"
          ],
          "description": "Tests a short Option",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "shortForm": "i",
          "required": true,
          "type": "INT",
          "longForm": "intOption",
          "defaultValue": "200000",
          "validValues": [
            "200000",
            "20000,"
          ],
          "description": "Tests a int Option",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "shortForm": "l",
          "required": true,
          "type": "LONG",
          "longForm": "longOption",
          "defaultValue": "100000000",
          "validValues": [
            "100000000,",
            "2000000000"
          ],
          "description": "Tests a long Option",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "shortForm": "f",
          "required": true,
          "type": "FLOAT",
          "longForm": "floatOption",
          "defaultValue": "0.0",
          "validValues": [
            "0.0,",
            "-2.0"
          ],
          "description": "Tests a float Option",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "shortForm": "d",
          "required": true,
          "type": "DOUBLE",
          "longForm": "doubleOption",
          "defaultValue": "1.2",
          "validValues": [
            "0.0,",
            "1.2"
          ],
          "description": "Tests a double Option",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "shortForm": "s",
          "required": true,
          "type": "STRING",
          "longForm": "stringOption",
          "defaultValue": "Foo",
          "validValues": [
            "Bar",
            "Foo,"
          ],
          "description": "Tests a String Option",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "shortForm": "m",
          "required": true,
          "type": "STRING",
          "longForm": "currencyOption",
          "defaultValue": "JPY",
          "validValues": [
            "JPY",
            "USD,"
          ],
          "description": "Tests a Currency Option",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        },
        {
          "shortForm": "e",
          "required": true,
          "type": "STRING",
          "longForm": "enumOption",
          "defaultValue": "PrettyPrint",
          "description": "Tests a Enum Option",
          "_xFieldBitmask_": [
            0
          ],
          "xRogType": 0
        }
      ],
      "_xFieldBitmask_": [
        0
      ],
      "xRogType": 0
    }