Create an instance of jdk.nashorn.api.scripting.NashornScriptEngineFactory directly instead of doing engineManager.engineByName(), then create a ScriptEngine by invoking NashornScriptEngineFactory.getScriptEngine(ClassLoader appLoader) and passing it your app-level loader.
Hope that helps, Attila. (I’ll answer to StackOverflow too.) > On Jul 28, 2015, at 6:04 PM, Максим Гумеров <[email protected]> wrote: > > 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)?
