Reputation: 109
I generally store away all the command line options to a different class, say, CliArguments. This avoids the noise in the main class. This is what I have with picocli:
public final class MyApp {
private static final CliArguments cliArgs = new CliArguments();
private MyApp() {}
public static void main (String[] args) {
if (parseArgs (args)) {
new MyApp().execute();
}
}
/* want to avoid this boiler plate */
private static boolean parseArgs(String[] args) {
CommandLine cmd = new CommandLine ( cliArgs );
try {
cmd.parseArgs( args );
if (cmd.isUsageHelpRequested()) {
cmd.usage( cmd.getOut() );
return false;
}
else if ( cmd.isVersionHelpRequested() ) {
cmd.printVersionHelp (cmd.getOut());
return false;
}
logger.info("{}", cliArgs);
return true;
}
catch ( ParameterException ex ) {
logger.error ("Failure to parse : {}", ex);
return false;
}
}
private void execute() {
// execution logic
}
}
How do I avoid the boiler plate method, pargeArgs(String[])
? The CliArguments class, technically, should not implement a Callable or Runnable. I can make MyApp be a Callable or Runnable. but to CommandLine, new MyApp() is not a command, new CliArguments() is.
If I want to do something like this:
final int exitCode = new CommandLine(new MyApp()).execute(args);
if (0 != exitCode) {
logger.error("Failed to parse");
System.exit(exitCode);
}
how do I push off all the @Option
specification to a different class, CliArguments while still having the execution control in MyApp?
I am sure I am missing something straight forward.
Upvotes: 1
Views: 394
Reputation: 36754
The simplest way to achieve this is by making CliArguments
a mixin in MyApp
. We can then put the business logic in MyApp
, and make it a Runnable
or Callable
so we can bootstrap the application with new CommandLine(new MyApp()).execute(args)
.
For example:
@Command(mixinStandardHelpOptions = true, version = "1.0.0")
public class CliArgs {
@Option(names = "-x") boolean x;
@Option(names = "-y") boolean y;
}
@Command(name = "myapp", description = "...")
public class MyApp implements Runnable {
// options defined in the mixin are added to this command
// also, @Command attributes from the mixin are applied to this command
@Mixin
CliArgs cliArgs;
public void run() {
System.out.printf("-x=%s%n", cliArgs.x);
System.out.printf("-y=%s%n", cliArgs.y);
}
public void main(String... args) {
System.exit(new CommandLine(new MyApp()).execute(args));
}
}
The options defined in the CliArgs
mixin become part of the MyApp
mixee.
Also, any @Command
attributes defined in CliArgs
become part of the MyApp
command.
You can now run:
java MyApp -x
and this will print
-x=true
-y=false
Since the mixin has @Command(mixinStandardHelpOptions = true)
, the MyApp
command also has --help
and --version
options that work as you would expect.
Upvotes: 1