我有一个抽象的groovy类,其中包含一些我想从其他groovy命令类扩展的实用程序方法(用于Spring Boot的远程shell)。但是,当我尝试运行groovy命令类时,得到了CommandException
。
我的常规类抽象如下。
package commands
import com.xyz.MyService
import org.crsh.command.InvocationContext
import org.springframework.beans.factory.BeanFactory
abstract class abstractcmd {
private static final String SPRING_FACTORY = "spring.beanfactory"
protected MyService getMyService(InvocationContext context) {
return getBeanFactory(context).getBean(MyService.class);
}
private BeanFactory getBeanFactory(InvocationContext context) {
return context.attributes[SPRING_FACTORY];
}
}
我的groovy命令类如下所示。
package commands
import org.crsh.cli.Command
import org.crsh.cli.Usage
import org.crsh.command.InvocationContext
@Usage("do something commands")
class foo extends abstractcmd {
@Command
@Usage("bar")
def String bar(InvocationContext context) {
try {
getMyService(context).bar()
return "did bar"
} catch (Exception e) {
return String.format("could not do bar: %s", e.toString())
}
}
}
当我SSH进入shell并执行
foo bar
时,出现以下异常。org.crsh.shell.impl.command.spi.CommandException:无法创建命令foo实例
在org.crsh.lang.impl.groovy.GroovyCompiler $ 1.getCommand(GroovyCompiler.java:192)〜[crash.shell-1.3.2.jar :?]
在org.crsh.lang.LanguageCommandResolver.resolveCommand(LanguageCommandResolver.java:101)〜[crash.shell-1.3.2.jar :?]
在org.crsh.shell.impl.command.CRaSH.getCommand(CRaSH.java:100)〜[crash.shell-1.3.2.jar :?]
在org.crsh.shell.impl.command.CRaSHSession.getCommand(CRaSHSession.java:96)〜[crash.shell-1.3.2.jar :?]
在org.crsh.lang.impl.script.PipeLineFactory.create(PipeLineFactory.java:89)〜[crash.shell-1.3.2.jar :?]
在org.crsh.lang.impl.script.ScriptRepl.eval(ScriptRepl.java:88)〜[crash.shell-1.3.2.jar :?]
在org.crsh.shell.impl.command.CRaSHSession.createProcess(CRaSHSession.java:163)〜[crash.shell-1.3.2.jar :?]
在org.crsh.shell.impl.async.AsyncProcess.execute(AsyncProcess.java:172)〜[crash.shell-1.3.2.jar :?]
在org.crsh.console.Console.iterate(Console.java:219)〜[crash.shell-1.3.2.jar :?]
在org.crsh.console.Console.on(Console.java:158)〜[crash.shell-1.3.2.jar :?]
在org.crsh.console.Console.on(Console.java:135)〜[crash.shell-1.3.2.jar :?]
在org.crsh.console.jline.JLineProcessor.run(JLineProcessor.java:204)〜[crash.shell-1.3.2.jar :?]
在org.crsh.ssh.term.CRaSHCommand.run(CRaSHCommand.java:99)〜[crash.connectors.ssh-1.3.2.jar :?]
在java.lang.Thread.run(Thread.java:745)[?:1.8.0_111]
如果我从
package commands
和abstractcmd
类中都删除了foo
行,则IDE(IntelliJ)和shell都抱怨找不到abstractcmd
。2017-03-19 19:34:06错误org.crsh.shell.impl.command.CRaSHProcess.execute:84-评估请求'foo'时出错无法编译命令脚本foo
org.crsh.shell.impl.command.spi.CommandException:无法编译命令脚本foo
在org.crsh.lang.impl.groovy.GroovyClassFactory.parse(GroovyClassFactory.java:65)〜[crash.shell-1.3.2.jar :?]
在org.crsh.lang.impl.groovy.GroovyCompiler $ 1.getCommand(GroovyCompiler.java:172)〜[crash.shell-1.3.2.jar :?]
在org.crsh.lang.LanguageCommandResolver.resolveCommand(LanguageCommandResolver.java:101)〜[crash.shell-1.3.2.jar :?]
在org.crsh.shell.impl.command.CRaSH.getCommand(CRaSH.java:100)〜[crash.shell-1.3.2.jar :?]
在org.crsh.shell.impl.command.CRaSHSession.getCommand(CRaSHSession.java:96)〜[crash.shell-1.3.2.jar :?]
在org.crsh.lang.impl.script.PipeLineFactory.create(PipeLineFactory.java:89)〜[crash.shell-1.3.2.jar :?]
在org.crsh.lang.impl.script.ScriptRepl.eval(ScriptRepl.java:88)〜[crash.shell-1.3.2.jar :?]
在org.crsh.shell.impl.command.CRaSHSession.createProcess(CRaSHSession.java:163)〜[crash.shell-1.3.2.jar :?]
在org.crsh.shell.impl.async.AsyncProcess.execute(AsyncProcess.java:172)〜[crash.shell-1.3.2.jar :?]
在org.crsh.console.Console.iterate(Console.java:219)〜[crash.shell-1.3.2.jar :?]
在org.crsh.console.Console.on(Console.java:158)〜[crash.shell-1.3.2.jar :?]
在org.crsh.console.Console.on(Console.java:135)〜[crash.shell-1.3.2.jar :?]
在org.crsh.console.jline.JLineProcessor.run(JLineProcessor.java:204)〜[crash.shell-1.3.2.jar :?]
在org.crsh.ssh.term.CRaSHCommand.run(CRaSHCommand.java:99)〜[crash.connectors.ssh-1.3.2.jar :?]
在java.lang.Thread.run(Thread.java:745)[?:1.8.0_111]
引起原因:org.codehaus.groovy.control.MultipleCompilationErrorsException:启动失败:
foo:9:无法解析类abstractcmd
@第9行,第1列。
@Usage(“ bar”)
^
1个错误
在org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)〜[groovy-2.4.7.jar:2.4.7]
在org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:946)〜[groovy-2.4.7.jar:2.4.7]
在org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:593)〜[groovy-2.4.7.jar:2.4.7]
在org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:542)〜[groovy-2.4.7.jar:2.4.7]
在groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)〜[groovy-2.4.7.jar:2.4.7]
在groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)〜[groovy-2.4.7.jar:2.4.7]
在org.crsh.lang.impl.groovy.GroovyClassFactory.parse(GroovyClassFactory.java:59)〜[crash.shell-1.3.2.jar :?]
...另外14个
我可以使自定义命令正常运行的唯一方法是不扩展
abstractcmd
(从而在命令类中实现“ util”方法)并删除package
行。我正在使用Spring Boot v1.5.1.RELEASE。
关于我在做什么错的任何想法吗?
最佳答案
看起来CRaSH的Groovy类存在扩展其他Groovy类的问题,因为如果您不扩展其中一个,它就可以正常工作。
很抱歉,但是我没有时间去充分研究如何以及为什么(更正欢迎更新/修正),并且在docs中没有找到任何东西,但是好消息是您可以扩展抽象的Java类。实现同一件事。我偶然发现了这样的a sample for the cron
command,它使用以下javadoc扩展了GroovyCommand
抽象类:
/**
* The base command for Groovy class based commands.
*/
public abstract class GroovyCommand extends BaseCommand implements GroovyObject
因此,总而言之,您可以使用以下解决方法:
抽象
SpringAwareCommand
java类package crash.commands;
import org.crsh.command.BaseCommand;
import org.springframework.beans.factory.BeanFactory;
public abstract class SpringAwareCommand extends BaseCommand {
private static final String SPRING_BEAN_FACTORY = "spring.beanfactory";
protected <T> T getBean(Class<T> beanClass) {
return ((BeanFactory) this.context.getAttributes().get(SPRING_BEAN_FACTORY)).getBean(beanClass);
}
}
更新了
foo
groovy类package crash.commands
import com.xyz.MyService
import org.crsh.cli.Command
import org.crsh.cli.Usage
@Usage("do something commands")
class foo extends SpringAwareCommand {
@Command
@Usage("bar")
def String bar() {
try {
getBean(MyService.class).bar()
return "did bar"
} catch (Exception e) {
return String.format("could not do bar: %s", e.toString())
}
}
}