JCommander Documentation

repository·master·Indexed 24 days ago

https://github.com/cbeust/jcommander

An annotation-based parameter parsing framework for Java that maps command-line arguments directly to Java object fields. It supports standard parameters via @Parameter, key-value pairs via @DynamicParameter, sub-commands, custom type converters using IStringConverter, and parameter validation through IParameterValidator and IParametersValidator. Features include secure password handling, default value providers, and automatic usage documentation generation.

Tokens
2.7K
Snippets
8
Records
14
Agent score
34%

What's inside JCommander

  1. Define parameters with @Parameter and @DynamicParameter

    master

    JCommander uses annotations to map command-line arguments to class fields:

    • @Parameter: Used for standard arguments.
      • names: An array of strings or a single string representing the flag (e.g., names = { "-log", "-verbose" } or names = "-groups").
      • description: A string describing the parameter.
      • placeholder: A string used in help documentation to show the expected format.
      • Unnamed @Parameter fields capture remaining positional arguments into a List.
    • @DynamicParameter: Used for key-value pairs where the key is provided at runtime (e.g., -Dkey=value). This typically maps to a Map<String, String>.
  2. Configure Boolean parameters

    master

    JCommander handles boolean types in two ways based on the arity attribute:

    1. Arity 0 (Default): If the field is boolean or Boolean, it acts as a flag. If the option is present on the command line, the field is set to true. No additional value is required.
    2. Arity 1: If you set arity = 1, the user must explicitly provide a value (e.g., true or false).
    // Arity 0: Flag style
    @Parameter(names = "-debug", description = "Debug mode")
    private boolean debug = false;
    
    // Arity 1: Explicit value required
    @Parameter(names = "-debug", description = "Debug mode", arity = 1)
    private boolean debug = true;
  3. Parse command line parameters with JCommander

    master

    JCommander allows you to parse command line arguments by annotating fields in a Java class with @Parameter. You then use the JCommander.newBuilder() to register your object and call .parse(argv).

    Basic usage pattern:

    1. Define a class with fields annotated with @Parameter.
    2. Instantiate the class.
    3. Use JCommander.newBuilder().addObject(yourObject).build().parse(args) to populate the fields.
    import com.beust.jcommander.Parameter;
    import com.beust.jcommander.JCommander;
    import java.util.ArrayList;
    import java.util.List;
    
    public class Args {
      @Parameter
      private List<String> parameters = new ArrayList<>();
    
      @Parameter(names = { "-log", "-verbose" }, description = "Level of verbosity")
      private Integer verbose = 1;
    }
    
    // Usage
    Args args = new Args();
    String[] argv = { "-log", "2" };
    JCommander.newBuilder()
      .addObject(args)
      .build()
      .parse(argv);
  4. Use JCommander for annotation-based parameter parsing

    master

    JCommander is a framework for parsing command-line arguments into Java objects using annotations. You define your command-line options as fields within a class and annotate them with @Parameter or @DynamicParameter.

    To use it:

    1. Create a class containing fields annotated with @Parameter (for fixed options) or @DynamicParameter (for key-value pairs).
    2. Use JCommander.newBuilder() to register your object via .addObject(yourObject).
    3. Call .build().parse(argv) where argv is your command-line string array.
    public class JCommanderTest {
        @Parameter
        public List<String> parameters = Lists.newArrayList();
     
        @Parameter(names = { "-log", "-verbose" }, description = "Level of verbosity")
        public Integer verbose = 1;
     
        @Parameter(names = "-groups", description = "Comma-separated list of group names to be run",
                        placeholder = "<group1>,<group2>...")
        public String groups;
     
        @Parameter(names = "-debug", description = "Debug mode")
        public boolean debug = false;
    
        @DynamicParameter(names = "-D", description = "Dynamic parameters go here")
        public Map<String, String> dynamicParams = new HashMap<String, String>();
    }
    
    // Usage:
    JCommanderTest jct = new JCommanderTest();
    String[] argv = { "-log", "2", "-groups", "unit1,unit2,unit3",
                        "-debug", "-Doption=value", "a", "b", "c" };
    JCommander.newBuilder()
      .addObject(jct)
      .build()
      .parse(argv);
  5. Securely handle passwords

    master

    To prevent passwords from appearing in command line history, use the password = true attribute. This causes JCommander to prompt the user for the value in the console during execution.

    By default, input is not echoed (hidden). You can enable echoing by setting echoInput = true.

    @Parameter(names = "-password", description = "Connection password", password = true, echoInput = true)
    private String password;
  6. Use IStringConverterFactory for global type mapping

    master

    If you use a custom type frequently, implement IStringConverterFactory to map types to converters globally. This avoids repeating the converter attribute on every @Parameter annotation.

    Register the factory using .addConverterFactory(factory) when building the JCommander instance.

    public class Factory implements IStringConverterFactory {
      public Class<? extends IStringConverter<?>> getConverter(Class<T> forType) {
        if (forType.equals(HostPort.class)) return HostPortConverter.class;
        else return null;
      }
    }
    
    // Usage
    JCommander jc = JCommander.newBuilder()
        .addObject(args)
        .addConverterFactory(new Factory())
        .build();
  7. Configure default values with IDefaultProvider

    master

    While you can set defaults by initializing fields, you can use IDefaultProvider for centralized or dynamic defaults.

    JCommander provides built-in providers:

    • PropertyFileDefaultProvider: Reads from jcommander.properties.
    • EnvironmentVariableDefaultProvider: Reads from JCOMMANDER_OPTS.

    You can chain providers using IDefaultProvider.sequenceOf(...).

    private static final IDefaultProvider DEFAULT_PROVIDER = new IDefaultProvider() {
      @Override
      public String getDefaultValueFor(String optionName) {
        return "-debug".equals(optionName) ? "false" : "42";
      }
    };
    
    JCommander jc = JCommander.newBuilder()
        .addObject(new Args())
        .defaultProvider(DEFAULT_PROVIDER)
        .build();
  8. Implement parameter validation

    master

    Validation can be performed at two levels:

    1. Individual Parameter Validation: Implement IParameterValidator to validate a single parameter's value. Use the validateWith attribute in @Parameter.
    2. Global Parameter Validation: Implement IParametersValidator to validate the entire set of parsed parameters (e.g., checking for mutual exclusivity). Use the parametersValidators attribute in @Parameters.