如何使用Scala作为脚本语言设置JSR223脚本?

7

到目前为止,我已经尝试了针对Scala的JSR223脚本的Sling实现,但是无法正确设置。

当我执行以下操作时:

public static void main(String[] args) {
    try {
        new ScriptEngineManager().getEngineByName("scala").
          eval("object HelloWorld {def main(args: Array[String]) { 
                  println(\"Hello, world!\") }}");
    } catch (ScriptException e) {
        e.printStackTrace();
    }
}

我只得到了以下内容:
javax.script.ScriptException: ERROR 
org.apache.sling.scripting.scala.Script line 13 : not found: type 
Script at org.apache.sling.scripting.scala.ScalaScriptEngine.eval(ScalaScriptEngine.scala:117)
    at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:247)

这里讨论了类似的问题:http://scala-programming-language.1934581.n4.nabble.com/How-to-compile-Scala-code-from-java-using-the-current-ClassLoader-instead-of-a-string-based-classpat-td1955873.html#a1955873http://dev.day.com/discussion-groups/content/lists/sling-dev/2009-12/2009-12-01_Scala_scripting_support_was_Re_And_another_one____Michael_D_rig.html,也许还有其他我不知道的实现。任何帮助都将不胜感激。
3个回答

6
请查看Apache Sling的scala/script模块中的测试用例,获取一个可工作的示例。脚本及其入口点(即对象)需要遵循某些约定。如果需要,我将稍后提供更多信息。
有关脚本引擎的概述,请参阅Scala Days 2010我的会议幻灯片更新:脚本必须具有以下形式:
package my.cool.script {
  class foo(args: fooArgs) {
    import args._ // import the bindings
    println("bar:" + bar)
  }
}
args的类型是由脚本引擎生成,并以简单类名附加'Args'命名。此外,示例假设传递给脚本评估的Bindings包含名称为'bar'的值。有关详细信息,请参见ScalaScriptEngine上的类注释。
您需要将脚本类的名称传递给脚本引擎。您可以通过在ScriptContext中使用完全限定的脚本名称(即my.cool.script.foo)放置名称'scala.script.class'来实现此目的。

4

随着2.11版本中https://issues.scala-lang.org/browse/SI-874的结论,现在应该像票证中所示的那样容易:

import javax.script.*;
ScriptEngine e = new ScriptEngineManager().getEngineByName("scala");
e.getContext().setAttribute("label", new Integer(4), ScriptContext.ENGINE_SCOPE);
try {
    engine.eval("println(2+label)");
} catch (ScriptException ex) {
    ex.printStackTrace();
}

在当前的Scala版本2.11.0-M4中,需要进行一些额外的工作来配置环境以使用Java类路径:... List nil = Nil$.MODULE$; $colon$colon vals = $colon$colon$.MODULE$.apply((String) "true", nil); ((IMain)engine).settings().usejavacp().tryToSet(vals); - VivaceVivo

0

很遗憾,我的评论没有换行符是无法阅读的 - 所以...

为了能够运行提到的代码片段,我需要进行以下更改。 我使用的是Scala 2.11.0-M4版本。

public static void main(String args[]){
  ScriptEngine engine = new ScriptEngineManager().getEngineByName("scala");

  // Set up Scriptenvironment to use the Java classpath
  List nil = Nil$.MODULE$;
  $colon$colon vals = $colon$colon$.MODULE$.apply((String) "true", nil);
  ((IMain)engine).settings().usejavacp().tryToSet(vals);ScriptContext.ENGINE_SCOPE);

  engine.getContext().setAttribute("labelO", new Integer(4), ScriptContext.ENGINE_SCOPE);
  try {
    engine.eval("val label = labelO.asInstanceOf[Integer]\n"+
                "println(\"ergebnis: \" + (2 + label ))");
  } catch (ScriptException ex) {
    ex.printStackTrace();
  }
}

当前的里程碑版本2.11.0-M5存在错误,调用getEngineByName("scala")方法会返回NULL。具体问题请参考https://issues.scala-lang.org/browse/SI-7843。M6版本应该可以解决这个问题(我还没有测试过)。 - VivaceVivo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接