single command + shell in one CLI program

115 views
Skip to first unread message

Jan Nielsen

unread,
Jun 12, 2020, 4:45:53 PM6/12/20
to picocli
Hi there,

I'd like to build a Spring Boot 2.3 CLI application with picocli as I described on Stackoverflow which run individual commands as well as a shell:
  manager -u <user> -p <pass> [list|create|delete] # run and exit
  manager -u <user> -p <pass> @script              # run and exit
  manager -u <user> -p <pass>                      # run shell
The first two work, but the shell does not when I follow the JLine3 example:
    https://github.com/remkop/picocli/blob/master/picocli-shell-jline3/
with PicocliCommands and PicocliJLineCompleter as Spring @Components but enabling the components disables the picocli functionality. I don't know, yet, what's happening but just wondering if there any known issues.
I'll setup repo for this sample in a bit -- but any ideas in the interim are greatly appreciated.

Cheers,
Jan

Jan Nielsen

unread,
Jun 12, 2020, 5:22:32 PM6/12/20
to picocli

Remko Popma

unread,
Jun 12, 2020, 7:30:12 PM6/12/20
to picocli
Hi Jan,

Thank you for raising this.

It looks like you already found how to implement most of the requirements mentioned in the StackOverflow question. That is good!

I am not aware of any issues with combining JShell with Spring, but that could be simply because I never tried this combination.

Thank you for providing a link to a working example, that makes this conversation a lot easier.

I noticed that your repo has picocli-spring-boot-starter as a dependency, that is good.
However, the ApplicationRunner class instantiates the ConnectCommand directly.
To enable Spring dependency injection in the subcommands, please use the SpringPicocliFactory to instantiate the ConnectCommand.
The picocli-spring-boot-starter README has an example.

In the ConnectCommand#run method, the ShellCommand#main method is invoked.
This in turn means we instantiate the CliCommands object directly without going through Spring.
This is similar, we need to give Spring a chance to do dependency injection here.

One idea is to have an @Inject CliCommands field in ConnectCommand, as well as a @Inject IFactory field,
and pass these to the ShellCommand#main method, so that this method can use these objects to create a CommandLine to start the interactive shell.

I hope this helps,
Remko.

Jan Nielsen

unread,
Jun 13, 2020, 11:12:05 PM6/13/20
to picocli
Ahh -- thanks for those, Remko! The repository sample now works as I need. You can update to see the changes. It still does not feel quite right but it now has all the functional elements which is awesome! 

Thanks hugely for your help -- I'll tidy the sample up a bit more before taking more of your time with my questions.


Cheers,

Jan

Remko Popma

unread,
Jun 14, 2020, 12:09:46 AM6/14/20
to picocli
Great! Glad to hear you’re making good progress.
Please let me know if you get stuck or if you find anything where the documentation can be improved.

Remko.
Reply all
Reply to author
Forward
0 new messages