Argumentos de línea de comandos con JCommander en una aplicación Java

Escrito por el .
java planeta-codigo
Enlace permanente Comentarios

Java

En Java la librería JCommander simplifica procesar los argumentos de línea de comandos complejas. Los argumentos de un programa de línea de comandos pueden ser requeridos, opcionales, con múltiples valores y las opciones escribirse de forma abreviada o de forma larga, además de emitir una pequeña guía de uso del comando con esta información y descripciones.

Otras posibilidades que ofrece JCommander son convertir los argumentos a un tipo determinado, especificar el separador para los valores, validaciones personalizadas, cambiar el separador entre el nombre del argumento y los valores, internacionalización, parámetros dinámicos, sintaxis complejas donde varios comandos tengas su propia lista de argumentos. En la documentación de JCommander están explicadas con ejemplos.

JCommander es muy útil en una aplicación Java que reciba por línea de comandos argumentos y valores, más si esa línea de comandos es compleja o es necesaria alguna de las funcionalidades que proporciona.

JCommander necesita de una clase que contenga la definición de los argumentos, esta misma clase sirve para recoger los valores indicados. Las propiedades se anotan con la anotación @Parameter, en sus atributos se indica si el argumento es requerido, tiene múltiples valores con varaibleArtity o un número determinado con arity.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package io.github.picodotdev.blogbitix.jcommander;

import com.beust.jcommander.Parameter;

import java.util.ArrayList;
import java.util.List;

public class Arguments {

    @Parameter
    private List<String> parameters = new ArrayList<>();

    @Parameter(names = { "--required", "-r" }, required = true, description = "Required parameter")
    private boolean required;

    @Parameter(names = { "--optional", "-o" }, description = "Optional parameter")
    private boolean optional = false;

    @Parameter(names = { "--values", "-v" }, variableArity = true, description = "Values parameter")
    private List<String> values = new ArrayList<>();

    @Parameter(names = { "--help", "-h" }, description = "Help parameter")
    private boolean help = false;

    public List<String> getParameters() {
        return parameters;
    }

    public boolean isRequired() {
        return required;
    }

    public boolean isOptional() {
        return optional;
    }

    public List<String> getValues() {
        return values;
    }

    public boolean isHelp() {
        return help;
    }
}

Arguments.java

El siguiente programa utiliza los argumentos anteriores que recoge de la línea de comandos, al programa Java se le proporcionan en el parámetro args del método main que es el punto de entrada en la aplicación.

Si un argumento requerido no se indica se produce un error mostrando la ayuda de uso. El argumento --required es requerido, el argumento --optional es opcional y el argumento --values recibe varios valores. El programa simplemente emite un mensaje con los valores de los argumentos en la salida.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package io.github.picodotdev.blogbitix.jcommander;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.ParameterException;

import java.util.stream.Collectors;

public class Main {

    public static void main(String[] argv) {
        Arguments arguments = new Arguments();
        JCommander jcommander = JCommander.newBuilder().addObject(arguments).build();

        try {
            jcommander.parse(argv);
        } catch (ParameterException e) {
            jcommander.usage();
        }

        System.out.printf("Main: required=%s, optional=%s, values=%s, help=%s%n%n",
                arguments.isRequired(),
                arguments.isOptional(),
                arguments.getValues().stream().collect(Collectors.joining(",")),
                arguments.isHelp());

        if (arguments.isHelp()) {
            jcommander.usage();
        }
    }
}
Main.java

Su invocación desde Gradle indicando varios argumentos, en el primer caso usando los nombres de argumentos largos y en el segundo los nombres de los argumentos cortos para escribir menos caracteres en la linea de argumentos.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
$ ./gradlew run --args='--required --values a1 b2 c3 d4 --help'

> Task :run
Main: required=true, optional=false, values=a1,b2,c3,d4, help=true

Usage: <main class> [options]
  Options:
    --help, -h
      Help parameter
      Default: false
    --optional, -o
      Optional parameter
      Default: false
  * --required, -r
      Required parameter
      Default: false
    --values, -v
      Values parameter
      Default: []


BUILD SUCCESSFUL in 596ms
2 actionable tasks: 2 executed

$ ./gradlew run --args='-r -v a1 b2 c3 d4 -h'

> Task :run
Main: required=true, optional=false, values=a1,b2,c3,d4, help=true

Usage: <main class> [options]
  Options:
    --help, -h
      Help parameter
      Default: false
    --optional, -o
      Optional parameter
      Default: false
  * --required, -r
      Required parameter
      Default: false
    --values, -v
      Values parameter
      Default: []


BUILD SUCCESSFUL in 531ms
2 actionable tasks: 1 executed, 1 up-to-date
gradlew-run.sh

Si el argumento requerido no se proporciona o se indica la opción --help se muestra la ayuda de uso.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ ./gradlew run --args=' '

> Task :run
Usage: <main class> [options]
  Options:
    --help, -h
      Help parameter
      Default: false
    --optional, -o
      Optional parameter
      Default: false
  * --required, -r
      Required parameter
      Default: false
    --values, -v
      Values parameter
      Default: []

Main: required=false, optional=false, values=, help=false


BUILD SUCCESSFUL in 539ms
2 actionable tasks: 1 executed, 1 up-to-date
gradlew-run-usage.sh

Como dependencia en el proyecto se ha de indicar la librería de JCommander.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
plugins {
    id 'java'
    id 'application'
}

repositories {
    jcenter()
}

dependencies {
    implementation 'com.beust:jcommander:1.71'
}

application {
    mainClassName = 'io.github.picodotdev.blogbitix.jcommander.Main'
}

test {
    useJUnitPlatform()
}
build.gradle
Terminal

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando siguiente comando:
./gradlew run --args='--required --values a1 b2 c3 d4 --help'


Comparte el artículo: