Loading JavaScripts using Nashorn

Anuradha Karunarathna
3 min readOct 14, 2018

--

Enter to Nashorn

Java 8 release introduced lots of new features, including brand-new JavaScript engine to replace the existing Rhino. Nashorn is really needful whenever you want to mix and match Java and JavaScript codes. Using nashorn, you can invoke JavaScript functions from your java code and invoke Java code from JavaScript. So, JavaScript made great in Java 8 with nashorn.

If you have not experienced Nashorn, just try it because, it supports only for JDK 8–10.

From this blog post mainly I’m emphasizing the beauty of “load()” function in nashorn. Go through the code examples to understand it easily. Get the sample from here.

Invoke Nashorn from Java Code

Let’s invoke this JavaScript Function from Java code.

var function1 = function(name){
print("Hello "+name);
return "Greetings from JavaScript";
}

Sample Java code is here.

ScriptEngine engine = newScriptEngineManager().getEngineByName("nashorn");
engine.eval(new FileReader("script.js"));

Invocable invocable = (Invocable) engine;

Object result = invocable.invokeFunction("function1", "Anuradha");
System.out.println(result);
}

In order to invoke Nashorn in your Java application, create an instance of the Nashorn engine using the Java Scripting API.

  1. Import javax.script package
  2. Create a ScriptEngineManager object.
  3. Retrieve a ScriptEngine object from the manager using getEngineByName() method. To get an instance of the nashorn engine, pass “nashorn”
  4. After you have the Nashorn engine instance, you can use it to evaluate a script file or statement.

Instead of evaluating the script file, you can evaluate the above function using a statement as follows.

engine.eval("var function1 = function(name){\n" +
" print(\"Hello \"+name);\n" +
" return \"Greetings from JavaScript\";\n" +
"}");

In order to call a JavaScript function, first you have to cast the script engine to Invocable. The Invocable interface is implemented by the NashornScriptEngine implementation and defines a method invokeFunction to call a javascript function for a given name.

Your output will be:

Hello Anuradha
Greetings from JavaScript

Loading Scripts

“load()” function in nashorn loads and evaluates a script from a path, URL, or script object.

Le’ts try all three options.

create a JavaScript file as lib.js and write this function there.

function increment(number){
number=number+1;
return number;
}

Create a JavaScript file as math.js and write the following.

load('lib.js');

var function2 =function (number) {
return increment(number);

}

Invoke function2 from Java code.

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

engine.eval(new FileReader("math.js"));

Invocable invocable = (Invocable) engine;

Object result = invocable.invokeFunction("function2", 50);
System.out.println(result);
}

The output is:

51.0

Then, try to load the function in lib.js as a script object. Instead of load(‘lib.js’); line in math.js file write the following.

load({"name":"lib.js","script":"function increment(number){number=number+1;return number;}"});

The name of the script object could be any name.

If you have hosted the lib.js or have any other way to access the lib.js file from an URL, load("<URL>"); could be used. You can test it by hosting the file here. You can use load("http://yourjavascript.com/110181462191/lib.js"); to load lib.js as an URL.

Evaluate load function inside Java code

Instead of writing the load() function on top of another JavaScript file, you can load and evaluate the required file or script object or URL from the same nashorn engine instance beforehand.

As a file path:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");String filepath= "lib.js";
engine.eval("load('"+filepath+"')");

engine.eval(new FileReader("math.js"));

Invocable invocable = (Invocable) engine;

Object result = invocable.invokeFunction("function2", 50);
System.out.println(result);

As a script object:

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

String scriptObject ="{\"name\":\"lib.js\",\"script\":\"function increment(number){number=number+1;return number;}\"}";
engine.eval("load("+scriptObject+")");


engine.eval(new FileReader("math.js"));

Invocable invocable = (Invocable) engine;

Object result = invocable.invokeFunction("function2", 50);
System.out.println(result);

As an URL:

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

String url = "http://yourjavascript.com/110181462191/lib.js";
engine.eval("load('"+url+"')");


engine.eval(new FileReader("math.js"));

Invocable invocable = (Invocable) engine;

Object result = invocable.invokeFunction("function2", 50);
System.out.println(result);

There are so many other features in nashorn. Follow Nashorn user’s guide https://docs.oracle.com/javase/9/nashorn/JSNUG.pdf for more information.

Happy coding :)

--

--

Anuradha Karunarathna
Anuradha Karunarathna

Written by Anuradha Karunarathna

Technical Lead @ WSO2 | Computer Science and Engineering graduate@ University of Moratuwa, SriLanka

Responses (2)