3

我正在尝试从 JUnit 测试中调试 Eclipse 中的 Groovy 脚本。Groovy 代码是在 Tomcat 中运行的大型 Java 应用程序的一部分。由于各种原因,我们的系统设置为使用已编译的 JSR223 表达式。这是缩写的代码片段:

GroovyScriptEngineImpl engine = new GroovyScriptEngineImpl();
Resource r =
  new ClassPathResource("groovy/transformations/input/Foo.groovy");
String expression = IOUtils.toString(r.getInputStream());
CompiledScript script = engine.compile(expression);
String result = (String) script.eval(new SimpleBindings(bindings));

测试运行良好,但即使我在 Foo.groovy 中设置了断点,并且文件位于类路径中,调试时断点也不会被命中。我猜这不起作用,因为字符串格式的表达式与包含它的实际文件之间没有关联。那么有没有办法在字符串与其对应的文件名之间创建这种关联?如前所述,我需要使用 CompiledScript。作为旁注,当使用这种方法时,我已经能够使用相同的 Groovy 脚本在调试器中命中断点:

Resource r =
  new ClassPathResource("groovy/transformations/input/Foo.groovy");
GroovyShell shell = new GroovyShell(new Binding(bindings));
String str = (String) shell.evaluate(r.getFile());

当然,在这种情况下,Groovy 引擎直接加载文件。非常感谢有关如何使第一个示例工作的任何提示。谢谢。

4

1 回答 1

4

您完全正确,这与从字符串创建类有关。GroovyScriptEngineImpl 喜欢为编译后的脚本指定任意名称,因为它假定所有内容都来自字符串。然而,GroovyShell 会根据脚本来自的文件生成脚本名称,这是调试器需要的链接。

我可能会建议您避免使用 GroovyScriptEngineImpl 并改用 GroovyShell.parse。然后,您可以根据 GroovyShell.parse 的结果并使用新的 GroovyScriptEngineImpl 创建一个 GroovyCompiledScript。像这样的东西:

File f = getScriptFile();
Script s = new GroovyShell().parse(f);
CompiledScript cs = new GroovyCompiledScript(new GroovyScriptEngineImpl(), s.getClass());
...

请注意,我还没有尝试过,但根据我的经验,这应该可行。

如果您感觉非常好,我会在 groovy 问题跟踪器上提出一个 jira,以确保您可以为使用 GroovyScriptEngineImpl 创建的脚本传递正确的名称。

于 2013-05-01T20:19:19.653 回答