JavaScript で定義された関数を Java コードから (Nashorn を使用して) 呼び出し、そこにいくつかのパラメーターを渡す必要があります。Invocable.invokeFunction("Foo", arg1, arg2) を使用する代わりに、インターフェイスを定義し、Invocable にその実装を作成するように要求します。これは、オラクルがここで提案している「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);
...
}
}
問題は、Tomcat で実行されている Web アプリケーションでこれを行っているため、Composer がアプリレベルのクラスローダーによって読み込まれ、nashorn クラスが拡張機能のクラスローダーによって読み込まれることです。そのため、getInterface はTypeError: Can not find a common class loader for ScriptObject と mypackage.Composer を言って失敗します。
それを克服する方法はありますか?もちろん、Composer が実際には ext ローダーであると仮定して (ハックのように)、親クラスローダーに Composer をロードしようとすることもできますが、それには少なくとも 1 つの問題があります。つまり、クラスが見つからないということです。私のパッケージは私の Web アプリケーションに存在し、拡張ローダーはそこに見えません。他に素晴らしいアイデアはありますか?
PSそして今、私はこのメッセージが奇妙であることに気付きました:アプリのクラスローダーが外部クラスローダーに委譲する場合、もちろん後者がそれらの共通のクラスローダーです。たぶん彼らは、ターゲットインターフェースのクラスローダーが実際の実装のクラスローダーと等しくなければならない、または実装のクラスローダーがターゲットのクラスローダーに委譲しなければならない(しかしその逆ではない)と言おうとしていたのでしょうか?