Scripting API in Java: Invoking JavaScript from Java

Scripting languages like JavaScript sometimes prove to be more flexible over the normal Java code. The Scripting API (javax.script.*) introduced in Java 6 allows to use the advantage of JavaScript in Java.

With the help of a Scripting Engine, the Scripting API can invoke scripts in the Java code. Java 6 comes with an implementation of JavaScript interpreter by Mozilla, Rhino. Scripting engines for other scripting languages can be found at http://scripting.dev.java.net.

Let us see an example of how to invoke JavaScript from a Java class.

package com.technicalmusings.sample.js;
import java.util.List;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class ScriptRunner {

public static void main(String[] args) throws Exception{

    //the script manager
    ScriptEngineManager scriptManager = new ScriptEngineManager();

    //Check the available script engines
    List<ScriptEngineFactory> scriptFactories = scriptManager.getEngineFactories();

    System.out.println("Available Engines in Java 1.6.0_17:");
    for (ScriptEngineFactory factory : scriptFactories){
        System.out.println(factory.getEngineName());
    }
    System.out.println("-----------------------------------");

    System.out.println("Java Script Variables");
    System.out.println("-----------------------------------");

    //Get the java script engine
    ScriptEngine engine = scriptManager.getEngineByName("JavaScript");

    /*
    * USING A JAVASCRIPT VARIABLE:
    * Variables evaluated in JavaScript engine defaults to engine scope.
    * In the below example I am using the method engine.eval(String
    * script) to invoke JavaScript. In case you wish to store JavaScript
    * in a file like abc.js, you can use the overloaded version of the
    * same method which takes a Reader object; engine.eval(Reader
    * reader);
    */

    engine.put("i", 10);
    System.out.println("i * 10 : " + engine.eval("i * 10"));//100
    System.out.println("i : " + engine.eval("i"));//10
    System.out.println("i = i * 10 : " + engine.eval("i = i * 10"));//100
    System.out.println("i : " + engine.eval("i"));//100

    //using javascript variable in java
    int i = ((Double)engine.eval("i")).intValue();
    System.out.println("JavaScript variable in Java; i : " + i);
    System.out.println("-----------------------------------");

    /*
    * USING JAVASCRIPT FUNCTION:
    * Script engines provide the feature of invoking a function. In order
    * to be able to invoke a function the script engine must implement
    * the Invocable interface. Following example shows how to use a
    * simple function in JavaScript.
    */

    System.out.println("Java Script Function");
    System.out.println("-----------------------------------");
    //Check whether engine implements Invocable as it depends on the engine’s implementation.
    if(engine instanceof Invocable){
    //Declare the function
        String functionScript = "function display(message){ return message }";
        engine.eval(functionScript);

        //Invoke the function with a String parameter
        String message = "Hey JS! Greetings from Java";
        Object result = ((Invocable)engine).invokeFunction("display", message);
        System.out.println(result);

        //Invoke the function using a pre defined variable
        result = ((Invocable)engine).invokeFunction("display", "i is " + engine.eval("i"));
        System.out.println(result);
    }
    System.out.println("-----------------------------------");
 }
}

The output of the above example is given as below:

Available Engines in Java 1.6.0_17:
Mozilla Rhino
-----------------------------------
Java Script Variables
-----------------------------------

i * 10 : 100.0
i : 10
i = i * 10 : 100.0
i : 100.0
-----------------------------------
Java Script Function
-----------------------------------
Hey JS! Greetings from Java
i is 100.0
-----------------------------------

I have shown very basic use of the scripting APIs in this post. There are many other features which a scripting engine provides. For example if we require executing a script multiple times we can compile the script once and use that as required. The engine in that case must implement the Compilable interface.

The Scripting API also solved the problem of using a JavaScript variable in java and vice-versa. Most of the times we face this problem in a JSP where we have to use workarounds. Though I still need to test this but this should work. Let me know if you have tested the same.

Enjoy Learning,

Kamlesh

Advertisements