Uploaded image for project: 'Commons CLI'
  1. Commons CLI
  2. CLI-196

Annotation based option specification



    • Type: New Feature
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: CLI-1.x
    • Labels:


      This is a proposal for an alternative way of specifying command line options, using annotations. It's implementation wraps Commons CLI code and uses reflection.

      From a user perspective, the following is a example of a mythical program that takes three arguments:

      -utc, reports the date in terms of UTC.
      -offset <integer>, adds an offset to the reference date.
      -reference <amount>, the reference amount (whatever that is).

      The Java code for the options is as follows:

      public class XyzOptions {
        private boolean utc;
        private int offset;
        private BigDecimal reference;
        @Option (name="utc", description="Reports the date in terms of UTC")
        void setUTC (boolean utc) {
          this.utc = utc;
        @Option (name="offset", description="Adds an offset to the reference date")
        void setOffset (int offset) {
          this.offset = offset;
        @Option (name="reference", required=true, description="The reference amount")
        void setReferenceAmount (BigDecimal amount) {
          this.reference = amount;
        // get methods omitted

      @Option is an annotation that provides CLI option details. The @Option annotates set methods of the options class.

      The Java code that uses these options is as follows:

      public static void main (String[] args) {
        XyzOptions options = CommandLine.parse(args, XyzOptions.class, "dateCommand");
        // the program options can then be accessed using get methods or field access on the options object.

      The "CommandLine" class is the class that builds the CLI Options instance using the @Option annotations and reflection.

      The @Option annotation allows the following to be specified:

      • name. The short name of the option.
      • longForm. The long form of the option.
      • description. The description of the option. This is the description that appears in the help text.
      • required. true if this option is required. This defaults to false, meaning the option is optional.
      • argOptional. true if the option argument is optional. This defaults to false, meaning the option argument is mandatory.

      The remaining information is obtained by reflection on the set method parameter.

      • If the set method parameter is boolean or Boolean, the option is assumed to take no argument. It is a simple switch.
      • If the set method parameter takes any other type, the option is assumed to take an argument of that type.
        • If the parameter type is String, the option argument is used as-is.
        • If the parameter type is a primitive type (or the class equivalent), the option argument is converted to that type and passed to the set method.
        • If the parameter type is something else (such as BigDecimal), the command line parser looks for a class constructor that takes a String argument. If this is found, and instance of the object is created an passed to the set method. Any class that has a constructor that takes a single String argument can be used.

      Option arguments can be validated in the set methods. For example, if a File needs to be a directory, the set method could be as follows:

        @Option (name="dir", description="The output directory")
        void setOutputDir (File file) {
          if (!file.isDirectory()) {
            throw new IllegalArgumentException ("'dir' option must specify a directory");
          this.file = file;

      The code for what is described here is available if anyone wants it.

      This is the idea. There are some issues to resolve, but the first question is: does anyone think it worth pursuing this?




            • Assignee:
              kevin-au Kevin Holloway
            • Votes:
              1 Vote for this issue
              2 Start watching this issue


              • Created: