简体   繁体   English

Nashorn JavaScript Invocable.getInterface在Web应用程序中的类加载器中失败

[英]Nashorn JavaScript Invocable.getInterface fails across classloaders in web app

I need to invoke (with Nashorn) from Java code a function defined in JavaScript and to pass there some parameters. 我需要从Java代码调用(使用Nashorn)JavaScript中定义的函数并传递一些参数。 Instead of using Invocable.invokeFunction("Foo", arg1, arg2), I was going to define an interface, then request Invocable to produce its implementation, just like Oracle suggests here , "Embedding Oracle Nashorn": 而不是使用Invocable.invokeFunction(“Foo”,arg1,arg2),我打算定义一个接口,然后请求Invocable来生成它的实现,就像Oracle 在这里建议的那样,“嵌入Oracle Nashorn”:

package mypackage;
public final class MyClass {
  public interface Composer {
    void compose(final StringBuilder subject, final StringBuilder body);
  }

  public void composeEmail(...) {
      ...
      final ScriptEngineManager engineManager = new ScriptEngineManager();
      final ScriptEngine engine = engineManager.getEngineByName("nashorn");
      engine.eval(scriptText);
      final Invocable invocable = (Invocable) engine;
      final Composer composer = (Composer)invocable.getInterface(Composer);
      composer.compose(subject, body);
      ...
  }
}

Problem is, since I am doing this in a web application running in Tomcat, my Composer gets loaded by app-level classloader, while nashorn classes were loaded by extensions class loader. 问题是,因为我在Tomcat中运行的Web应用程序中执行此操作,所以我的Composer由app级别的类加载器加载,而nashorn类则由扩展类加载器加载。 So getInterface fails saying a TypeError: Can not find a common class loader for ScriptObject and mypackage.Composer 因此getInterface无法说出TypeError:找不到ScriptObject和mypackage.Composer的公共类加载器

Any ideas how to overcome that? 任何想法如何克服? I could, of course, try to load Composer in a parent classloader, in an assumption (hack-like) that it is actually an ext loader, but there is at least one problem with that: it cannot find my class. 当然,我可以尝试在父类加载器中加载Composer,假设(类似黑客)它实际上是一个ext加载器,但至少有一个问题:它无法找到我的类。 I suppose it's quite right: my package resides in my web application, and extension loader does not look there. 我认为这是非常正确的:我的软件包位于我的Web应用程序中,扩展加载程序看起来并不存在。 Any other great ideas? 还有其他好点子吗?

PS And now I noticed that this message is weird: if an app classloader delegates to ext classloader, then of course the latter is the common classloader for them. PS现在我注意到这个消息很奇怪:如果app类加载器委托给ext类加载器,那么后者当然是它们的通用类加载器。 Maybe they were trying to say that the target interfaces's classloader must be equal to actual implementation's classloader, or the implementation's classloader must delegate to the target's (but not vice versa)? 也许他们试图说目标接口的类加载器必须等于实际实现的类加载器,或者实现的类加载器必须委托给目标(但反之亦然)?

直接创建jdk.nashorn.api.scripting.NashornScriptEngineFactory的实例而不是执行engineManager.engineByName() ,然后通过调用NashornScriptEngineFactory.getScriptEngine(ClassLoader appLoader)并将其传递给应用程序级加载器来创建ScriptEngine

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM