Я сталкиваюсь с чрезвычайно странным поведением в Groovy. Когда я выбрасываю исключение из замыкания в сценарии, было сгенерировано конечное исключение.
Вот код и детали:
public class TestDelegate {
def method(Closure closure) {
closure.setResolveStrategy(Closure.DELEGATE_FIRST);
closure.delegate = this;
closure.call();
}
public static void main(String[] args) {
// Make Script from File
File dslFile = new File("src/Script.dsl");
GroovyShell shell = new GroovyShell();
Script dslScript = shell.parse(dslFile);
TestDelegate myDelegate = new TestDelegate();
dslScript.metaClass.methodMissing = {
// will run method(closure)
String name, arguments ->
myDelegate.invokeMethod(name, arguments);
}
dslScript.metaClass.propertyMissing = {
String name ->
println "Will throw error now!"
throw new MyOwnException("errrrror");
}
dslScript.run();
}
}
class MyOwnException extends Exception {
public MyOwnException(String message) {
super(message);
}
}
Script.dsl:
method {
println a;
}
Таким образом, план состоит в том, что когда я запускаю метод main()
в TestDelegate
, он запускает сценарий DSL, который вызывает метод method()
. Не найдя его в скрипте, он вызовет methodMissing
, который затем вызовет method()
из myDelegate
, что, в свою очередь, вызовет замыкание, установив делегату значение testDelegate
. Все идет нормально. Затем предполагается, что замыкание попытается распечатать «a», которое не определено, и, таким образом, будет установлено значение propertyMissing
, которое выдаст MyOwnException
.
Однако, когда я запускаю код, я получаю следующий вывод:
Will throw error now!
Exception in thread "main" groovy.lang.MissingPropertyException: No such property: a for class: TestDelegate
Теперь он, должно быть, достиг этого блока catch, поскольку на нем было напечатано "Будет выдано сообщение об ошибке!" Должно быть, выбросил MyOwnException
тоже! Но где-то вдоль линии MyOwnException
был преобразован в MissingPropertyException
, и я понятия не имею, почему. У кого-нибудь есть идеи?
P.S. если я удаляю closure.setResolveStrategy(Closure.DELEGATE_FIRST)
из TestDelegate#method()
, код работает как положено и выдает MyOwnException
. Но мне действительно нужен setResolveStrategy(Closure.DELEGATE_FIRST)
для моего проекта DSL. И я бы предпочел узнать причину этого, а не просто удалить строку или две, и увидеть, что это работает, не понимая, почему.