Reputation: 4083
This is followup question on
how to build console command in spring boot web application using spring shell?
As per suggestions on above question I am trying spring boot remote shell.
I have created my custom command following this documentation,
But in real world use cases, we mostly have arguments and options to command. There is no mention in doc about how to define them so that user should pass while running commands.
This is very well explained and easy to do in spring-shell.
http://docs.spring.io/spring-shell/docs/current/reference/htmlsingle/#simple-application
https://projects.spring.io/spring-shell/
But we cant use spring shell with spring boot.
what are the reliable production ready solutions to such use cases ?
Update:
Got the solution on CRaSH doc
http://www.crashub.org/1.3/reference.html#developping_commands
I can see myCommand in the list of commands after loggin into shell, but when I run command,
but I am getting exception
"Could not create command commandName instance".
I am trying to use spring beans in command so I did autowiring e.g.
package commands;
import org.crsh.cli.Argument;
import org.crsh.cli.Command;
import org.crsh.cli.Usage;
import org.crsh.cli.Option;
import org.crsh.cli.Required;
import org.crsh.command.BaseCommand;
import org.crsh.command.InvocationContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@Usage("My test computation commands.")
public class myCommand extends BaseCommand {
protected final Logger log = LoggerFactory.getLogger(getClass());
/**
*
*/
public Service1 service1;
/**
*
*/
public Service2 service2;
/**
* @param service1
* @param service2
*/
@Autowired
public myCommand(Service1 service1, Service2 service2) {
super();
this.service1 = service1;
this.service2 = service2;
}
@Usage("Test command")
@Command
public Map<String, Double> command1(InvocationContext<Object> context, @Usage("id") @Required @Argument int id)
throws Exception {
Map<String, Double> result = new HashMap<>();
result.put("key1", service1.compute(id));
result.put("key2", service2.compute(id));
return result;
}
}
Upvotes: 3
Views: 1829
Reputation: 17085
I don't think you can inject beans in your Remote shell command.
You may however inject an InvocationContext into your method and use it to retrieve a spring managed bean from your context:
@Usage('Example using spring.beanfactory')
@Command
def mycommand(InvocationContext context, ...) {
BeanFactory beans = context.attributes['spring.beanfactory']
YourBean bean = beans.getBean(YourBean.class);
...
}
A Complete example which works for me:
package commands
import org.crsh.cli.Command
import org.crsh.cli.Usage
import org.crsh.command.InvocationContext
import org.springframework.beans.factory.BeanFactory
import com.alexbt.goodies.MyBean
class SayMessage {
String message;
SayMessage(){
this.message = "Hello";
}
@Usage("Default command")
@Command
def main(InvocationContext context, @Usage("A Parameter") @Option(names=["p","param"]) String param) {
BeanFactory beanFactory = (BeanFactory) context.getAttributes().get("spring.beanfactory");
MyBean bean = beanFactory.getBean(MyBean.class);
return message + " " + bean.getValue() + " " + param;
}
@Usage("Hi subcommand")
@Command
def hi(InvocationContext context, @Usage("A Parameter") @Option(names=["p","param"]) String param) {
BeanFactory beanFactory = (BeanFactory) context.getAttributes().get("spring.beanfactory");
MyBean bean = beanFactory.getBean(MyBean.class);
return "Hi " + bean.getValue() + " " + param;
}
}
> saymsg -p Johnny
> Hello my friend Johnny
> saymsg hi -p Johnny
> Hi my friend Johnny
Upvotes: 4