Invocable.getInterface fails across classloaders in web app

Максим Гумеров mgumerov at gmail.com
Tue Jul 28 16:04:12 UTC 2015


Hello!
Recently I posted a question at stackoverflow, so far no one had the
answer, so I thought I might find one here.

My original question is here:
http://stackoverflow.com/questions/31669566/nashorn-javascript-invocable-getinterface-fails-across-classloaders-in-web-app

For reader's comfort, I will reproduce its below.
Thank you!
Maksim

====

I need to invoke (with Nashorn) from Java code a function defined in
JavaScript and to pass there some parameters. 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
<http://www.oracle.com/technetwork/articles/java/jf14-nashorn-2126515.html%20%22here'>,
"Embedding 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. So getInterface fails saying a
*TypeError:
Can not find a common class loader for ScriptObject and 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. I suppose it's quite right: my package resides in my web
application, and extension loader does not look there. Any other great
ideas?

P.S. 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. 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)?


More information about the nashorn-dev mailing list