Search code examples
javajavascriptinheritancenashorn

Get extended Java class from Nashorn


Is there a way to get and use an extended Java class from JavaScript (Nashorn)?

What I am trying to do is to extend a Java class in Nashorn and then pass it back to Java. For example, we define a class which extends another class in JS:

var SomeClass= Java.type("com.test.SomeClass");
var MySomeClass = Java.extend(SomeClass, {
    aMethod1: function() {
        print("m1");
    },
    aMethod2: function() {
        print("m2");
    },
}); 

Then I've tried to get this extended object in Java like so: Object mySomeClass = scriptEngine.get("MySomeClass");

However, I am unable to make any method calls on this object in Java. It always throws an exception when I am trying to cast it to a base class - com.test.SomeClass.

Is it possible to use an extended class created in Nashorn (JS) in Java?


Solution

  • Here is a working example extending ArrayList:

    String script = "(function() {\n" +
      "  var ArrayList = Java.type('java.util.ArrayList')\n" +
      "  var ArrayListExtender = Java.extend(ArrayList)\n" +
      "  var list = new ArrayListExtender() {\n" +
      "    get: function(idx) {\n" +
      "      return idx >= list.size() ? " +
      "'no such value' : Java.super(list).get(idx);\n" +
      "    }\n" +
      "  }\n" +
      "  return list;\n" +
      "} ());";
    
      ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
      @SuppressWarnings("unchecked")
      List<String> result = (List<String>) engine.eval(script);
      result.add("gotcha");
      System.out.println(result.get(0));
      System.out.println(result.get(10));
    

    You don't state what exception you are getting but the problem is likely in how you consume or use the type. Note that neither Java.type nor Java.extend return a java.lang.Class - these methods return an internal Nashorn type with an undocumented API.