Introduction to Nashorn
Java 8 introduced and new javascript engine named “Nashorn”. Nashorn is based on Da Vinci Machine, a project with aim of adding dynamic language support to JVM. Nashorn is a nice milestone to make the hybrid softwares easier than before. The nice features of this engine makes you able to make a full duplex communication between your java (any other compiled languages) codes and javascript.
The simplest way to use Nashorn is a command line tool which is bundled in JDK 8 or OpenJDK 8 and you can find it in “/bin”. with executing jjs you will face with jjs prompt that you can work with Nashorn interactively, also you can pass js files as arguments to jjs. You can find a basic example of using jjs in below:
Consider the following simple.js file:
var name="Nashorn"; print(name);
Now by calling: jjs simple.js the text “Nashorn” will be presented on your screen.
I think jjs is enough for introduction, if you need more information you can type jjs -help.
Also you can use Nashorn script engine in your java code. Consider the following Program.java file:
public class Program { public static void main(String... args) throws ScriptException { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine nashornEngine = factory.getEngineByName("nashorn"); nashornEngine.eval("print('hello world');"); } }
With this simple code a very nice hello world will be showed on your screen. Also you can evaluate js files to your script engine, ScriptEngine interfaces has an eval method overload with Reader abstract class type. So simply you can pass any objects which is an instance of Reader class. Consider the following code:
script1.js content:
var version = 1; function hello(name) { return "hello " + name; }
Program.java content:
public class Program { public static void main(String... args) throws ScriptException, NoSuchMethodException { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine nashornEngine = factory.getEngineByName("nashorn"); nashornEngine.eval(new InputStreamReader(Program.class.getResourceAsStream("script1.js"))); System.out.println(nashornEngine.get("version")); Invocable invocable = (Invocable) nashornEngine; Object result = invocable.invokeFunction("hello", "soroosh"); System.out.println(result); } }
ScriptEngine interface has a get method, As you noticed in sample you can call it to retrieve any variables or any states defined in your ScriptEngine. In above example “version” is a variable declared in simple.js file.
Every script engine has its own implementation of ScriptEngine class and there are some optional interfaces which script engines can implement to extend their functionality. If you check the source code of NashornSriptEngine the class signature is:
public final class NashornScriptEngine extends javax.script.AbstractScriptEngine implements javax.script.Compilable, javax.script.Invocable
So Nashorn script engine makes you able to use these two interfaces too. In above example for calling functions which are declared in our script engine we used Invocable interface.
Note: ScriptEngine is stateful, so if you call some functions or eval some codes on your script engine the state of objects and variables can effect on their result.
Conclusion:
In this post i tried to introduce Nashorn in a very basic and practical way, In future posts i will demonstrate Java + Nashorn interoperability more and its usages in real world.
Reference: | Introduction to Nashorn from our JCG partner Soroosh Sarabadani at the Just another Java blog blog. |