我有一个抽象的 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: Could not create command foo instance at org.crsh.lang.impl.groovy.GroovyCompiler$1.getCommand(GroovyCompiler.java:192) ~[crash.shell-1.3.2.jar:?] at org.crsh.lang.LanguageCommandResolver.resolveCommand(LanguageCommandResolver.java:101) ~[crash.shell-1.3.2.jar:?] at org.crsh.shell.impl.command.CRaSH.getCommand(CRaSH.java:100) ~[crash.shell-1.3.2.jar:?] at org.crsh.shell.impl.command.CRaSHSession.getCommand(CRaSHSession.java:96) ~[crash.shell-1.3.2.jar:?] at org.crsh.lang.impl.script.PipeLineFactory.create(PipeLineFactory.java:89) ~[crash.shell-1.3.2.jar:?] at org.crsh.lang.impl.script.ScriptRepl.eval(ScriptRepl.java:88) ~[crash.shell-1.3.2.jar:?] at org.crsh.shell.impl.command.CRaSHSession.createProcess(CRaSHSession.java:163) ~[crash.shell-1.3.2.jar:?] at org.crsh.shell.impl.async.AsyncProcess.execute(AsyncProcess.java:172) ~[crash.shell-1.3.2.jar:?] at org.crsh.console.Console.iterate(Console.java:219) ~[crash.shell-1.3.2.jar:?] at org.crsh.console.Console.on(Console.java:158) ~[crash.shell-1.3.2.jar:?] at org.crsh.console.Console.on(Console.java:135) ~[crash.shell-1.3.2.jar:?] at org.crsh.console.jline.JLineProcessor.run(JLineProcessor.java:204) ~[crash.shell-1.3.2.jar:?] at org.crsh.ssh.term.CRaSHCommand.run(CRaSHCommand.java:99) ~[crash.connectors.ssh-1.3.2.jar:?] at 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 ERROR org.crsh.shell.impl.command.CRaSHProcess.execute:84 - Error while evaluating request 'foo' Could not compile command script foo org.crsh.shell.impl.command.spi.CommandException: Could not compile command script foo at org.crsh.lang.impl.groovy.GroovyClassFactory.parse(GroovyClassFactory.java:65) ~[crash.shell-1.3.2.jar:?] at org.crsh.lang.impl.groovy.GroovyCompiler$1.getCommand(GroovyCompiler.java:172) ~[crash.shell-1.3.2.jar:?] at org.crsh.lang.LanguageCommandResolver.resolveCommand(LanguageCommandResolver.java:101) ~[crash.shell-1.3.2.jar:?] at org.crsh.shell.impl.command.CRaSH.getCommand(CRaSH.java:100) ~[crash.shell-1.3.2.jar:?] at org.crsh.shell.impl.command.CRaSHSession.getCommand(CRaSHSession.java:96) ~[crash.shell-1.3.2.jar:?] at org.crsh.lang.impl.script.PipeLineFactory.create(PipeLineFactory.java:89) ~[crash.shell-1.3.2.jar:?] at org.crsh.lang.impl.script.ScriptRepl.eval(ScriptRepl.java:88) ~[crash.shell-1.3.2.jar:?] at org.crsh.shell.impl.command.CRaSHSession.createProcess(CRaSHSession.java:163) ~[crash.shell-1.3.2.jar:?] at org.crsh.shell.impl.async.AsyncProcess.execute(AsyncProcess.java:172) ~[crash.shell-1.3.2.jar:?] at org.crsh.console.Console.iterate(Console.java:219) ~[crash.shell-1.3.2.jar:?] at org.crsh.console.Console.on(Console.java:158) ~[crash.shell-1.3.2.jar:?] at org.crsh.console.Console.on(Console.java:135) ~[crash.shell-1.3.2.jar:?] at org.crsh.console.jline.JLineProcessor.run(JLineProcessor.java:204) ~[crash.shell-1.3.2.jar:?] at org.crsh.ssh.term.CRaSHCommand.run(CRaSHCommand.java:99) ~[crash.connectors.ssh-1.3.2.jar:?] at java.lang.Thread.run(Thread.java:745) [?:1.8.0_111] Caused by: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: foo: 9: unable to resolve class abstractcmd @ line 9, column 1. @Usage("bar") ^ 1 error at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310) ~[groovy-2.4.7.jar:2.4.7] at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:946) ~[groovy-2.4.7.jar:2.4.7] at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:593) ~[groovy-2.4.7.jar:2.4.7] at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:542) ~[groovy-2.4.7.jar:2.4.7] at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298) ~[groovy-2.4.7.jar:2.4.7] at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268) ~[groovy-2.4.7.jar:2.4.7] at org.crsh.lang.impl.groovy.GroovyClassFactory.parse(GroovyClassFactory.java:59) ~[crash.shell-1.3.2.jar:?] ... 14 more
如果我不扩展abstractcmd
,我能够使自定义命令正常工作的唯一方法是(从而实现命令类中的“util”方法)并删除 package
线。
我正在使用 Spring Boot v1.5.1.RELEASE。
关于我做错了什么有什么想法吗?
最佳答案
看起来 CRaSH 在扩展其他 Groovy 类的 Groovy 类方面存在问题,因为如果您不扩展一个类,它就可以正常工作。
很抱歉,我没有时间充分调查如何以及为什么(非常欢迎更正/更新),并且在 docs 中没有找到任何内容。但好消息是您可以扩展抽象 java 类来实现相同的功能。我偶然发现了这样的a sample for the cron
command扩展 GroovyCommand
具有以下 javadoc 的抽象类:
/**
* 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())
}
}
}
关于java - 使用继承的 Groovy 命令无法在 Spring Boot 远程 shell 中编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42893720/