In this example we will see how to execute a JavaScript function in Java using Nashorn. Also we will pass as an argument Java map (LinkedHashMap) which will be considered in the JavaScript as an object.
Project structure:
For this tutorial we are using Mavan with pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>NashornTest</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- https://mvnrepository.com/artifact/org.openjdk.nashorn/nashorn-core --> <dependency> <groupId>org.openjdk.nashorn</groupId> <artifactId>nashorn-core</artifactId> <version>15.4</version> </dependency> </dependencies> </project>
As you can see we are using nashorn-core as the dependency. After Java 14 the Nashorn was removed from the JVM, so we are using it here as an external library. More information: https://github.com/openjdk/nashorn
Let’s put our JavaScript file javascript_function.js inside the folder resources:
function printProperties(obj) { print(obj) var total = 0; for (var prop in obj) { print("key: " + prop + " value: " + obj[prop]); total = total + obj[prop]; } return total; }
At the end we can check our only Java class:
package org.example; import org.openjdk.nashorn.api.scripting.NashornScriptEngineFactory; import javax.script.*; import java.io.*; import java.util.LinkedHashMap; import java.util.Map; public class Main { public static void main(String[] args) throws ScriptException, NoSuchMethodException, IOException { // create a script engine manager NashornScriptEngineFactory factory = new NashornScriptEngineFactory(); // create a Nashorn script engine ScriptEngine engine = factory.getScriptEngine(); // Create map that it will represent our object Map<String, Integer> map = new LinkedHashMap<>(); map.put("Danny McCann", 200); map.put("Hilda Ogden", 300); map.put("Don Baldwin", 330); /** * Load the javascript function from the JS file. * The content of the function: * * function printProperties(obj) { * print(obj) * var total = 0; * for (var prop in obj) { * print("key: " + prop + " value: " + obj[prop]); * total = total + obj[prop]; * } * return total; * } * */ try (InputStream is = Main.class.getClassLoader().getResourceAsStream("javascript_function.js"); Reader reader = new InputStreamReader(is)) { engine.eval(reader); Invocable invocable = (Invocable) engine; /** * Call the function passing the function name and the map as argument. * Now the function will consider the Java Map as Javascript Object. * It will print the key and values then it will sum up the values */ Object funcResult = invocable.invokeFunction("printProperties", map); System.out.println("Class: " + funcResult.getClass() + " value: " + funcResult); } } }
Result:
{Danny McCann=200, Hilda Ogden=300, Don Baldwin=330}
key: Danny McCann value: 200
key: Hilda Ogden value: 300
key: Don Baldwin value: 330
Class: class java.lang.Double value: 830.0
You can check the Git repository for the whole project: