Can't call hasOwnProperty on Java List with Nashorn

1.7k Views Asked by At

I've got an application that executes a lot of javascript server side and I'm trying to convert from Rhino to Nashorn but I am running into trouble with my scripts. Using Rhino I would always convert whatever arguments I had for a function into a JSON string but that's really slow. With Nashorn I'm trying to just pass in the arguments as Java objects but they don't seem to inherit functions from Javascript's Object type. Here is a sample method that illustrates my problem where hasOwnProperty is not available on my array:

public String printArrayValues() throws ScriptException, NoSuchMethodException {

  String script =
      "function printArrayValues(objArray) {\n" +
      "  var result = '';\n" +
      "  for(var obj in objArray) {\n" +
      "    if(objArray.hasOwnProperty(obj)) {\n" +
      "      result = result + ' ' + objArray[obj];\n" +
      "    }\n" +
      "  }\n" +
      "  return result;\n" +
      "}";

  List<String> data = Arrays.asList(new String[]{ "one", "two", "three"});

  ScriptEngine scriptEngine = new NashornScriptEngineFactory().getScriptEngine();
  scriptEngine.eval(script);
  String result = (String) ((Invocable) scriptEngine).invokeFunction("printArrayValues", data);
}

Here the call to invokeFunction throws an exception:

javax.script.ScriptException: TypeError: [one, two, three] has no such function "hasOwnProperty" in <eval> at line number 4

If I call the same function in a browser, I get what I would expect:

> printArrayValues(["one", "two", "three"]);
> " one two three"

Is there some way I can accomplish this so I really can use these Java objects without turning them into a JSON string and then eval'ing it into a Javascript object?

2

There are 2 best solutions below

0
On BEST ANSWER

You can't use Java arrays in this way. Java arrays are "hardwired" objects. Unlike ordinary objects, they don't have methods and they support the [] operator, which objects can't.

This Article about Nashorn at Oracle explains that you need to use the Java.to and Java.from methods in your javascript in order to change a Java array to a Javascript array.

0
On

use Java.from() to transform the Java List to Javascript Array, and then operate on it.

  String script =
  "function printArrayValues(objArray) {\n" +
  "  var result = '';\n var temp = Java.from(objArray);" +
  "  for(var obj in temp ) {\n" +
  "    if(temp .hasOwnProperty(obj)) {\n" +
  "      result = result + ' ' + temp [obj];\n" +
  "    }\n" +
  "  }\n" +
  "  return result;\n" +
  "}";