I have to convert a large Spring boot application into a flexible CLI tool, where the requests sent by the Spring boot application (among other things) are determined by user input at the command line. I decided to use picocli to implement the command line functionality, however I can’t figure out how to even do something as simple as print some text to stdout if the user passes a given option flag, Spring boot just runs as it normally does. How am I supposed to write this so picocli can function alongside Spring boot (and eventually control all the Spring boot stuff)
Advertisement
Answer
As a follow-up to this I eventually got the code working by refactoring out the “controller methods” into 3 as follows:
|
|_ MainApp.java
|_ CmdRunner.java
|_ TheCommand.java
Where MainApp is the @SpringBootApplication
which basically just does:
System.exit(SpringApplication.exit(new SpringApplication(MainApp.class).run(args)));
Kicking everything off.
CmdRunner is an @Component
& simple implementation of the CommandLineRunner
Interface provided by SpringBoot, the most important bit is below:
@Autowired private TheCommand theCommand; @Override public void run(String... args) { new CommandLine(theCommand).execute(args); }
It executes the passed cli arguments (which were passed to it from MainApp.java) on a new picocli CommandLine
object. Which brings us to the final class, TheCommand.java
which is simultaneously a picocli @Command
& Springboot @Controller
implementing the Runnable
interface. And essentially just contains all the logic and (ever-growing)functionality I needed to deliver.
The only downside of this implementation is that when a user runs it with the --help
flag, the app still runs the spring boot stuff making it a little unresponsive in that particular scenario.