Picocli: What to do for multiple commands

Created on 15 Oct 2018  路  12Comments  路  Source: remkop/picocli

Hi Team,

Below is the situation I am facing:

I want to build a cli tool with picocli. I want to bundle it in a fat jar and give it to the users so that they can use it as a cli tool.

The tool is going to have multiple commands. Below is the format:

java commandone -a somevalue

java commandtwo -b someothervalue

For these, i can write classes for each individual commands with the help of @Command annotation.
e.g:
@Command(name="commandcone")
public class CommandOne implements Runnable { ... }

But the problem is, all the example given in the wiki demand to have public static void main() in the class and manually call CommandLine.run( ... ) in order to get the commands executed.

In the case of a tool having multiple commands (not subcommands), what do I do? I can not write main method to each class that i create for a command, right?

Do i manually write the routing for different commands? or is there a mechanism available already in picocli and I am unable to find it properly?

Please help. (btw other features are cool and you guys rock :) )

question

Most helpful comment

If your application has multiple top-level commands, each of these will need its own main method so it can be called from the commandline like this:

java -cp myjar.jar com.package.CommandOneClass -a somevalue
java -cp myjar.jar com.package.CommandTwoClass -b someothervalue

Your jar can only have one Main-Class in its manifest, and that will be the command when users invoke the jar as an application, like this:

java -jar myjar.jar -x somevalue

If you have multiple top-level commands, what people often do is provide multiple script files (shell script or batch scripts) that the end user can invoke. For example, for Windows:

# commandone.bat
java -cp myjar.jar com.package.CommandOneClass %*

This allows end users to call the command with its script name.
Build tools like gradle offer plugins that can generate these scripts for you.

All 12 comments

Hi @NagendraHegde , please take a look at this example:
https://github.com/remkop/picocli/blob/master/picocli-examples/src/main/java/picocli/examples/subcommands/ParentCommandDemo.java

It demonstrates how to code a top-level command with a single subcommand.
You can add more subcommands by adding them in the @Command(subcommands = {Aaa.class, Bbb.class, Ccc.class, ...}) list.

It is a good idea to make all your commands implement Runnable or Callable (either one is fine), then in your main method you can simply say:

CommandLine.run(new RunnableTopCommand(), args);

// or, if the top-level command implements Callable:
// CommandLine.call(new CallableTopCommand(), args);

Picocli will execute the most specific subcommand that the user specified. So, for example, if you have a command hierarchy like this:

top
  |
  +- sub
  |    |
  |    +- subsub
  |    
  +- sub2 
       |
       +- sub2sub

Then, when the user invokes top --option sub subsub --otheroption,
picocli will call run (or call) on the subsub subcommand (the most specific subcommand that the user specified.)

@NagendraHegde Did this answer your question?

@NagendraHegde Were you able to make progress or do you have follow-up questions?

@NagendraHegde Can this ticket be closed?

In the case of a tool having multiple commands (not subcommands), what do I do? I can not write main method to each class that i create for a command, right?

Since you are talking about top-level commands (not subcommands), every top-level command will need a separate class with its own main method to run it.

If your application has multiple top-level commands, each of these will need its own main method so it can be called from the commandline like this:

java -cp myjar.jar com.package.CommandOneClass -a somevalue
java -cp myjar.jar com.package.CommandTwoClass -b someothervalue

Your jar can only have one Main-Class in its manifest, and that will be the command when users invoke the jar as an application, like this:

java -jar myjar.jar -x somevalue

If you have multiple top-level commands, what people often do is provide multiple script files (shell script or batch scripts) that the end user can invoke. For example, for Windows:

# commandone.bat
java -cp myjar.jar com.package.CommandOneClass %*

This allows end users to call the command with its script name.
Build tools like gradle offer plugins that can generate these scripts for you.

Closing this ticket. Feel free to reopen if you want further clarification

I have the same problem and I find the last comment more as a workaround than a real solution.

This jar will receive args[] so it has all what it needs to have in order to interprete parameters. I don't see why we should require some bash or batch scripts here.

Isn't there a better solution which could work with picocli without having to use a script ?

@sebastienvermeille, would you mind creating a new ticket to explain your use case?

@sebastienvermeille The OP never replied after multiple comments so it鈥檚 hard to say whether I understood their problem. I鈥檓 happy to help but it would be good if you could explain in your own words what it is you鈥檙e trying to achieve.

@remkop sure if can help somehow I will :)
I create one right now with the more details I can give

@NagendraHegde I feel that I didn鈥檛 explain things very well in response to your question.

Please take a look at #641: perhaps my answer there is more clear and hopefully the discussion on that ticket is useful to you as well.

Was this page helpful?
0 / 5 - 0 ratings