Bhagat
Bhagat

Reputation: 11

Nashorn - Can not find a common class loader for ScriptObject and MyInterface

I recently upgraded my java version from java 1.7 to java 1.8. After the upgrade i am getting this error.

Caused by: ECMAScript Exception: Type Error: Can not find a common class loader for ScriptObject and My Interface.

Please help me fix this issue.

Below is my method

private final ScriptEngine engine;
ScriptEngineManager sem = new ScriptEngineManager();
engine = sem.getEngineByName("nashorn");

public <K> K getNewInterface(MyScript myScript){
        ScriptContext ctx = new SimpleScriptContext();
        String script = myScript.getScript();
        if(Strings.isEmpty(script)) {markInvalid(myScript, "Script is empty", null); return null;}
        script += " (function(){return this;})();";
        Object thiz;
        try{
            thiz = engine.eval(script, ctx);
        } catch (ScriptException e){
            markInvalid(myScript, "Can't execute script", e);
            return null;
        }
        if(thiz==null) {markInvalid(myScript, "Script executed, but context is null", null); return null;}
        K ret = (K) ((Invocable)engine).getInterface(thiz, myScript.getScriptInterfaceClass());
        if(ret==null) {
            markInvalid(myScript, "Script executed, but it's incompatible with required interface", null);
            return null;
        }else{
            myScript.setValid(true);
            return ret;
        }
    }

Upvotes: 0

Views: 1041

Answers (2)

Bhagat
Bhagat

Reputation: 11

The issue was not with the code. The issue was with the application server. I was using JBoss 6.4.0 Application Server, the issue was it did not have nashorn paths in module.xml file under EAP_HOME\modules\system\layers\base\sun\jdk\main. I added the missing nashorn paths to the module.xml file mentioned in the above path and it resolved my issue. You can also resolve the issue by using Jboss 7.0 as it has the nashorn paths by default.

Missing nashorn paths

                <path name="jdk/nashorn/api/scripting"/>
                <path name="jdk/nashorn/api/scripting/resources"/>
                <path name="jdk/nashorn/internal/codegen"/>
                <path name="jdk/nashorn/internal/codegen/types"/>
                <path name="jdk/nashorn/internal/ir"/>
                <path name="jdk/nashorn/internal/ir/annotations"/>
                <path name="jdk/nashorn/internal/ir/debug"/>
                <path name="jdk/nashorn/internal/ir/visitor"/>
                <path name="jdk/nashorn/internal/lookup"/>
                <path name="jdk/nashorn/internal/objects"/>
                <path name="jdk/nashorn/internal/objects/annotations"/>
                <path name="jdk/nashorn/internal/parser"/>
                <path name="jdk/nashorn/internal/runtime"/>
                <path name="jdk/nashorn/internal/runtime/arrays"/>
                <path name="jdk/nashorn/internal/runtime/linker"/>
                <path name="jdk/nashorn/internal/runtime/options"/>
                <path name="jdk/nashorn/internal/runtime/regexp"/>
                <path name="jdk/nashorn/internal/runtime/regexp/joni"/>
                <path name="jdk/nashorn/internal/runtime/resources"/>
                <path name="jdk/nashorn/internal/runtime/resources/fx"/>
                <path name="jdk/nashorn/internal/runtime/scripts"/>
                <path name="jdk/nashorn/internal/tools"/>
                <path name="jdk/nashorn/internal/tools/resources"/>
                <path name="jdk/internal/dynalink"/>
                <path name="jdk/internal/dynalink/beans"/>
                <path name="jdk/internal/dynalink/linker"/>
                <path name="jdk/internal/dynalink/support"/>

Upvotes: 0

Attila Szegedi
Attila Szegedi

Reputation: 4595

In order for Nashorn to crete an implementation of your interface, it must create (at runtime) a new class that both extends ScriptObject (Nashorn's internal native JS object representation) and your interface (let's say it's named MyInterface).

Such a class can only be created in the JVM if there's a class loader that can resolve both ScriptObject and MyInterface. Since ScriptObject normally exists in the ext classpath (jre/lib/ext) (in Java 8), you need to ensure that the class loader for MyInterface has the so-called "ext class loader" in its parent class loader chain. This is normally true, as most code is loaded by the JVM app class loader. If you have a more elaborate class loader setup (e.g. you're in some kind of an app container), it might not be true.

Basically, see if this works (I presume there's no security manager around…):

ClassLoader myClassLoader = myScript.getScriptInterfaceClass().getClassLoader();
Class.forName("jdk.nashorn.internal.runtime.ScriptObject", true, myClassLoader);

If it throws a ClassNotFoundException, you need to find out why doesn't myClassLoader see the ScriptObject class.

Upvotes: 1

Related Questions