Error java.lang.NoSuchMethodError: No such DSL method '***' found among steps
Error java.lang.NoSuchMethodError: No such DSL method '***' found among steps
我是 Jenkins 和 Groovy 的初学者。我正在开发一个管道库。
一个文件(version.groovy)定义如下:
def dateInternal = { new Date().format('yy.Mdd.Hmm') }.memoize()
def date() {
dateInternal()
}
在我调用的另一个文件中 version.date()
。
执行此操作时遇到以下错误:
java.lang.NoSuchMethodError: No such DSL method 'dateInternal' found among steps [ansiColor, archive, bat, ...
这可能是一个菜鸟问题,但直到现在我才找到解决这个问题的方法...
您必须注意两件事。当你在 Groovy 脚本中定义一个方法时(就像你的 date()
方法)它被编译为一个 class 级别的方法(每个 Groovy 脚本编译成一个 class扩展 groovy.lang.Script
class)。另一方面,变量(比如你的 dateInternal
是一个包含闭包的变量)被编译为存在于 run()
方法中的局部变量。因此,当我们按照您编写的代码进行操作时,我们会发现当您调用 date()
方法时,它会尝试调用存储在 dateInternal
变量中的闭包,而该变量仅存在于 run()
方法中.
如果你反编译已编译的 version.groovy
脚本你会看到这样的东西:
import groovy.lang.Binding;
import groovy.lang.Closure;
import groovy.lang.Script;
import java.util.Date;
import org.codehaus.groovy.runtime.GeneratedClosure;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.callsite.CallSite;
public class version extends Script {
public version() {
CallSite[] var1 = $getCallSiteArray();
super();
}
public version(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
}
public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].call(InvokerHelper.class, version.class, args);
}
public Object run() {
CallSite[] var1 = $getCallSiteArray();
final class _run_closure1 extends Closure implements GeneratedClosure {
public _run_closure1(Object _thisObject) {
CallSite[] var3 = $getCallSiteArray();
super(version.this, _thisObject);
}
public Object doCall(Object it) {
CallSite[] var2 = $getCallSiteArray();
return var2[0].call(var2[1].callConstructor(Date.class), "yy.Mdd.Hmm");
}
public Object doCall() {
CallSite[] var1 = $getCallSiteArray();
return this.doCall((Object)null);
}
}
Object dateInternal = var1[1].call(new _run_closure1(this));
return dateInternal;
}
public Object date() {
CallSite[] var1 = $getCallSiteArray();
return var1[2].callCurrent(this);
}
}
解决方案
您可以通过将 dateInternal
提升为 class 级别字段而不是局部变量来解决它。您可以使用 groovy.transform.Field
注释:
import groovy.transform.Field
@Field
def dateInternal = { new Date().format('yy.Mdd.Hmm') }.memoize()
def date() {
dateInternal()
}
现在,当您查看已编译的 version.groovy
脚本的反编译版本时,您会看到如下内容:
import groovy.lang.Binding;
import groovy.lang.Closure;
import groovy.lang.Script;
import java.util.Date;
import org.codehaus.groovy.runtime.GeneratedClosure;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;
public class version extends Script {
Object dateInternal;
public version() {
CallSite[] var1 = $getCallSiteArray();
super();
Object var2 = var1[0].call(new version._closure1(this));
this.dateInternal = var2;
}
public version(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
Object var3 = var2[1].call(new version._closure1(this));
this.dateInternal = var3;
}
public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[2].call(InvokerHelper.class, version.class, args);
}
public Object run() {
CallSite[] var1 = $getCallSiteArray();
return null;
}
public Object date() {
CallSite[] var1 = $getCallSiteArray();
return ScriptBytecodeAdapter.invokeClosure(this.dateInternal, new Object[0]);
}
public final class _closure1 extends Closure implements GeneratedClosure {
public _closure1(Object _thisObject) {
CallSite[] var3 = $getCallSiteArray();
super(version.this, _thisObject);
}
public Object doCall(Object it) {
CallSite[] var2 = $getCallSiteArray();
return var2[0].call(var2[1].callConstructor(Date.class), "yy.Mdd.Hmm");
}
public Object doCall() {
CallSite[] var1 = $getCallSiteArray();
return this.doCall((Object)null);
}
}
}
你可以看到dateInternal
变成了一个class级别字段,date()
方法可以简单地访问它。
我是 Jenkins 和 Groovy 的初学者。我正在开发一个管道库。
一个文件(version.groovy)定义如下:
def dateInternal = { new Date().format('yy.Mdd.Hmm') }.memoize()
def date() {
dateInternal()
}
在我调用的另一个文件中 version.date()
。
执行此操作时遇到以下错误:
java.lang.NoSuchMethodError: No such DSL method 'dateInternal' found among steps [ansiColor, archive, bat, ...
这可能是一个菜鸟问题,但直到现在我才找到解决这个问题的方法...
您必须注意两件事。当你在 Groovy 脚本中定义一个方法时(就像你的 date()
方法)它被编译为一个 class 级别的方法(每个 Groovy 脚本编译成一个 class扩展 groovy.lang.Script
class)。另一方面,变量(比如你的 dateInternal
是一个包含闭包的变量)被编译为存在于 run()
方法中的局部变量。因此,当我们按照您编写的代码进行操作时,我们会发现当您调用 date()
方法时,它会尝试调用存储在 dateInternal
变量中的闭包,而该变量仅存在于 run()
方法中.
如果你反编译已编译的 version.groovy
脚本你会看到这样的东西:
import groovy.lang.Binding;
import groovy.lang.Closure;
import groovy.lang.Script;
import java.util.Date;
import org.codehaus.groovy.runtime.GeneratedClosure;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.callsite.CallSite;
public class version extends Script {
public version() {
CallSite[] var1 = $getCallSiteArray();
super();
}
public version(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
}
public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[0].call(InvokerHelper.class, version.class, args);
}
public Object run() {
CallSite[] var1 = $getCallSiteArray();
final class _run_closure1 extends Closure implements GeneratedClosure {
public _run_closure1(Object _thisObject) {
CallSite[] var3 = $getCallSiteArray();
super(version.this, _thisObject);
}
public Object doCall(Object it) {
CallSite[] var2 = $getCallSiteArray();
return var2[0].call(var2[1].callConstructor(Date.class), "yy.Mdd.Hmm");
}
public Object doCall() {
CallSite[] var1 = $getCallSiteArray();
return this.doCall((Object)null);
}
}
Object dateInternal = var1[1].call(new _run_closure1(this));
return dateInternal;
}
public Object date() {
CallSite[] var1 = $getCallSiteArray();
return var1[2].callCurrent(this);
}
}
解决方案
您可以通过将 dateInternal
提升为 class 级别字段而不是局部变量来解决它。您可以使用 groovy.transform.Field
注释:
import groovy.transform.Field
@Field
def dateInternal = { new Date().format('yy.Mdd.Hmm') }.memoize()
def date() {
dateInternal()
}
现在,当您查看已编译的 version.groovy
脚本的反编译版本时,您会看到如下内容:
import groovy.lang.Binding;
import groovy.lang.Closure;
import groovy.lang.Script;
import java.util.Date;
import org.codehaus.groovy.runtime.GeneratedClosure;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;
public class version extends Script {
Object dateInternal;
public version() {
CallSite[] var1 = $getCallSiteArray();
super();
Object var2 = var1[0].call(new version._closure1(this));
this.dateInternal = var2;
}
public version(Binding context) {
CallSite[] var2 = $getCallSiteArray();
super(context);
Object var3 = var2[1].call(new version._closure1(this));
this.dateInternal = var3;
}
public static void main(String... args) {
CallSite[] var1 = $getCallSiteArray();
var1[2].call(InvokerHelper.class, version.class, args);
}
public Object run() {
CallSite[] var1 = $getCallSiteArray();
return null;
}
public Object date() {
CallSite[] var1 = $getCallSiteArray();
return ScriptBytecodeAdapter.invokeClosure(this.dateInternal, new Object[0]);
}
public final class _closure1 extends Closure implements GeneratedClosure {
public _closure1(Object _thisObject) {
CallSite[] var3 = $getCallSiteArray();
super(version.this, _thisObject);
}
public Object doCall(Object it) {
CallSite[] var2 = $getCallSiteArray();
return var2[0].call(var2[1].callConstructor(Date.class), "yy.Mdd.Hmm");
}
public Object doCall() {
CallSite[] var1 = $getCallSiteArray();
return this.doCall((Object)null);
}
}
}
你可以看到dateInternal
变成了一个class级别字段,date()
方法可以简单地访问它。