I stumbled upon this question from a while back, explaining how to get a Spring Shell application to exit after calling it from the command line with a single command. However, testing this in 2.0.0 with Spring Boot, it does not seem to be the case any more that invoking the JAR with command arguments will execute that command and then exit. The shell just starts as normal without executing the supplied command. Is it still possible to do this? If not, would it be possible to pass the arguments from the JAR execution to Spring Shell and then trigger an exit after execution?
For example, let's say I have a command, import
that has a couple options. It could be run in the shell like this:
$ java -jar my-app.jar
> import -f /path/to/file.txt --overwrite
Successfully imported 'file.txt'
> exit
But it would be nice to be able to simply execute and exit, for the sake of building a script that can utilize this function:
$ java -jar my-app.jar import -f /path/to/file.txt --overwrite
Successfully imported 'file.txt'
Running the Shell from the Jar File After obtaining the JAR file we run it using the command java -jar our-spring-shell-jar-name. jar . This will open our shell in the command line and have it ready for us to type in commands.
The Spring Boot CLI is a command line tool that you can use if you want to quickly develop a Spring application. It lets you run Groovy scripts, which means that you have a familiar Java-like syntax without so much boilerplate code. You can also bootstrap a new project or write your own command for it.
Spring Boot CLI(Command Line Interface) is a Spring Boot software to run and test Spring Boot applications from command prompt. When we run Spring Boot applications using CLI, then it internally uses Spring Boot Starter and Spring Boot AutoConfigurate components to resolve all dependencies and execute the application.
Run it with @my-script, like so:
java -jar my-app.jar @my-script
Where my-script is a file with your commands:
import -f /path/to/file.txt --overwrite
Just to add, I found another way of doing this, doesn't give you the option to run in interactive mode but using your profiles above you can of course swap the configuration. Please note I'm using lombok and jool (just in case anyone copy pastes and gets funny issues!)
Entry
@SpringBootApplication
public class Righter {
public static void main(String[] args) {
SpringApplication.run(Righter.class, args);
}
@Bean
public ApplicationRunner shellRunner(Shell shell) {
return new NonInteractiveShellRunner(shell);
}
Application runner:
@Order(0)
public class NonInteractiveShellRunner implements ApplicationRunner{
private final Shell shell;
public NonInteractiveShellRunner(Shell shell) {
this.shell = shell;
}
@Override
public void run(ApplicationArguments args) throws Exception {
shell.run(new CommandInputProvider(args.getSourceArgs()));
}
public static class PredefinedInputProvider implements InputProvider{
private final Input input;
private boolean commandExecuted = false;
public PredefinedInputProvider(String[] args) {
this.input = new PredefinedInput(args);
}
@Override
public Input readInput() {
if (!commandExecuted){
commandExecuted=true;
return input;
}
return new PredefinedInput(new String[]{"exit"});
}
@AllArgsConstructor
private static class PredefinedInput implements Input{
private final String[] args;
@Override
public String rawText() {
return Seq.of(args).toString(" ");
}
@Override
public List<String> words(){
return Arrays.asList(args);
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With