Nashorn JavaScript Engine: Running JavaScript from Java

Published: Novembar 3, 2016


Introduction

Java provides an excellent feature for integrating JavaScript into Java applications through the Nashorn JavaScript Engine. Introduced in Java 8, Nashorn allows you to execute JavaScript code from within a Java application with high performance and efficiency.

In this tutorial, we will explore:

  • What Nashorn is and how it works.
  • How to run JavaScript code from Java.
  • Practical examples of using Nashorn to integrate JavaScript in Java applications.

By the end of this tutorial, you’ll be able to harness the power of Nashorn to run JavaScript directly from Java, which is useful for extending Java applications with scripting capabilities.


What is Nashorn?

Nashorn is a JavaScript runtime built into the Java Virtual Machine (JVM). It provides a high-performance engine for executing JavaScript code in Java applications. Nashorn is a replacement for the older Rhino JavaScript engine and offers improved performance, supporting the latest ECMAScript standards.

Some key features of Nashorn:

  • It executes JavaScript code directly within Java.
  • It provides access to Java classes and Java objects from JavaScript code.
  • It supports both JavaScript syntax and the Java API, making it easy to interact with Java from JavaScript and vice versa.

Setting Up Nashorn

Nashorn is available by default in JDK 8 and later versions, so you don’t need to install anything extra. However, it’s important to note that Nashorn has been deprecated as of JDK 11, so for modern Java versions, alternatives like GraalVM are recommended for running JavaScript.

To use Nashorn, you simply need to invoke it through the Java Scripting API (javax.script) provided by the Java platform.


Running JavaScript from Java

Example 1: Running a Simple JavaScript Expression

Let’s start by running a simple JavaScript expression from Java using Nashorn:

import javax.script.*;

public class NashornExample {
    public static void main(String[] args) {
        try {
            // Create a script engine
            ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");

            // Define a simple JavaScript code
            String script = "var x = 5; var y = 10; x + y;";

            // Execute the script
            Object result = engine.eval(script);

            // Print the result
            System.out.println("Result of JavaScript evaluation: " + result); // Output: 15
        } catch (ScriptException e) {
            e.printStackTrace();
        }
    }
}

In this example:

  • We create a ScriptEngine instance that uses Nashorn.
  • We define a JavaScript expression that adds two numbers.
  • We execute the script with engine.eval() and print the result.

Example 2: Using JavaScript Functions in Java

Nashorn allows you to define and call JavaScript functions from Java. Let’s define a JavaScript function and call it from Java:

import javax.script.*;

public class NashornExample {
    public static void main(String[] args) {
        try {
            // Create a script engine
            ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");

            // Define a JavaScript function
            String script = "function greet(name) { return 'Hello, ' + name; }";

            // Evaluate the script to define the function
            engine.eval(script);

            // Call the function from Java
            Invocable invocable = (Invocable) engine;
            Object result = invocable.invokeFunction("greet", "Java Developer");

            // Print the result
            System.out.println(result); // Output: Hello, Java Developer
        } catch (ScriptException | NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

Here:

  • We define a JavaScript function greet() that takes a name as an argument and returns a greeting.
  • We then call this function from Java using the Invocable interface, passing in "Java Developer" as an argument.

Accessing Java Objects from JavaScript

One of the powerful features of Nashorn is the ability to interact with Java objects from JavaScript. This allows you to use Java classes and libraries directly in your JavaScript code.

Example 3: Using Java Classes in JavaScript

Let’s access Java classes (like ArrayList) and use them in JavaScript:

import javax.script.*;
import java.util.ArrayList;

public class NashornExample {
    public static void main(String[] args) {
        try {
            // Create a script engine
            ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");

            // Define Java objects in JavaScript
            String script = "var list = new java.util.ArrayList();"
                            + "list.add('Java');"
                            + "list.add('JavaScript');"
                            + "list.add('Nashorn');"
                            + "list;";

            // Evaluate the script
            Object result = engine.eval(script);

            // Print the result (Java List)
            System.out.println("List from JavaScript: " + result); // Output: [Java, JavaScript, Nashorn]
        } catch (ScriptException e) {
            e.printStackTrace();
        }
    }
}

In this example:

  • We create a Java ArrayList from JavaScript using new java.util.ArrayList().
  • We add elements to the list and return it.
  • The list is printed as a Java ArrayList object.

Handling JavaScript Exceptions in Java

You can handle exceptions in JavaScript just like you would in Java. Nashorn allows you to catch and throw exceptions between Java and JavaScript seamlessly.

Example 4: Handling Errors

import javax.script.*;

public class NashornExample {
    public static void main(String[] args) {
        try {
            // Create a script engine
            ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");

            // Define a JavaScript function that throws an exception
            String script = "function throwError() { throw new Error('Something went wrong!'); }";

            // Evaluate the script
            engine.eval(script);

            // Call the function that throws an error
            Invocable invocable = (Invocable) engine;
            invocable.invokeFunction("throwError");

        } catch (ScriptException | NoSuchMethodException e) {
            System.out.println("Caught JavaScript exception: " + e.getMessage());
        }
    }
}

In this example:

  • We define a JavaScript function throwError() that throws an exception.
  • When the function is invoked, the exception is caught and printed by the Java catch block.

Conclusion

The Nashorn JavaScript engine makes it easy to run JavaScript code from Java applications, bridging the gap between Java and JavaScript. This functionality is useful for scenarios like adding scripting capabilities to your Java application or integrating with JavaScript libraries.

However, with the deprecation of Nashorn in JDK 11 and its removal in JDK 15, you may want to consider other alternatives like GraalVM if you’re working with modern Java versions.

In the next tutorial, we will explore the flatMap() method in Java 8’s Streams API and its usage in handling more complex data structures.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *