Can't figure out why ScriptEngine engine is null in code
Asked Answered
S

3

5

This is some of the code I'm running for a MapleStory server. Whenever a script for an event like talking to an NPC is supposed to occur, this script will be run to create a scripting path for whatever script is being called up (NPC, portal, event etc.).

I am also using jdk1.7.0_80

lang-java
package scripting;

import java.io.File; 
import java.io.FileReader; 
import java.io.IOException;
import javax.script.Invocable; 
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import client.MapleClient; 
import tools.FileoutputUtil;

public abstract class AbstractScriptManager {

    private static final ScriptEngineManager sem = new ScriptEngineManager(null);

    protected Invocable getInvocable(String path, MapleClient c) {
        return getInvocable(path, c, false);
    }

    protected Invocable getInvocable(String path, MapleClient c, boolean npc) {
        FileReader fr = null;
        try {
            path = "scripts/" + path;
            ScriptEngine engine = null;

            if (c != null) {
                engine = c.getScriptEngine(path);
            }
            if (engine == null) {
                File scriptFile = new File(path);
                if (!scriptFile.exists()) {
                    return null;
                }
                engine = sem.getEngineByName("JavaScript");
                if (c != null) {
                    c.setScriptEngine(path, engine);
                }
                fr = new FileReader(scriptFile);
                engine.eval(fr);
            } else if (c != null && npc) {
                c.getPlayer().dropMessage(-1, "You already are talking to this NPC. Use @ea if this is 
                not intended.");
            }
            return (Invocable) engine;
        } catch (Exception e) {
            System.err.println("Error executing script. Path: " + path + "\nException " + e);
            FileoutputUtil.log(FileoutputUtil.ScriptEx_Log, "Error executing script. Path: " + path + 
            "\nException " + e);
            return null;
        } finally {
            try {
                if (fr != null) {
                    fr.close();
                }
            } catch (IOException ignore) {

            }
        }
    } 
}

This is the bat error I receive:

Error executing script. Path: scripts/event/someEvent.js Exception java.lang.NullPointerException: Cannot invoke "javax.script.ScriptEngine.eval(java.io.Reader)" because "engine" is null

These errors are thrown whenever I try to interact with something that utilizes this method (i.e. clicking NPC or on server start-up when some scripts are run).

Sandpit answered 16/1, 2021 at 6:41 Comment(7)
What version of Java are you running? Note that JavaScript was removed in Java 15. JDK-8236933: "The Nashorn JavaScript script engine, its APIs, and the jjs tool have been removed. The engine, the APIs, and the tool were deprecated for removal in Java 11 with the express intent to remove them in a future release."Hymnology
I'm using Java 7 for this projectSandpit
Oracle JDK 7 or OpenJDK 7 or some other build?Hymnology
Try running the following code. I bet it doesn't print anything, meaning that the Java build you're running on doesn't have any script engines. for (ScriptEngineFactory factory : sem.getEngineFactories()) { System.out.println(factory.getEngineName() + " " + factory.getEngineVersion() + " " + factory.getNames()); }. --- My Oracle JDK 8 prints Nashorn, my OpenJDK 7 prints nothing.Hymnology
The bat didn't output anything but I am also using jdk1.7.0_80Sandpit
Thank you @Hymnology I forgot I had other versions of Java also installed so my pathing was not set up correctly. It works as intended nowSandpit
Nashorn removal: GraalVM to the rescue!Tao
H
9

The NullPointerException occurs because the Java Runtime you're using doesn't have a "JavaScript" Script Engine installed, causing sem.getEngineByName("JavaScript") to return null.

That was verified (see comment) by running the following code:

ScriptEngineManager sem = new ScriptEngineManager();
List<ScriptEngineFactory> factories = sem.getEngineFactories();
for (ScriptEngineFactory factory : factories)
    System.out.println(factory.getEngineName() + " " + factory.getEngineVersion() + " " + factory.getNames());
if (factories.isEmpty())
    System.out.println("No Script Engines found");

When I run this on various Java implementations on Windows 10, I get the following results:

OpenJDK jdk1.7.0_75:
  No Script Engines found

Oracle jdk1.7.0_80:
  Mozilla Rhino 1.7 release 3 PRERELEASE [js, rhino, JavaScript, javascript, ECMAScript, ecmascript]

Oracle jdk1.8.0_181:
  Oracle Nashorn 1.8.0_181 [nashorn, Nashorn, js, JS, JavaScript, javascript, ECMAScript, ecmascript]

Oracle jdk-9.0.4:
  Oracle Nashorn 9.0.4 [nashorn, Nashorn, js, JS, JavaScript, javascript, ECMAScript, ecmascript]

OpenJDK jdk-11.0.2:
  Oracle Nashorn 11.0.2 [nashorn, Nashorn, js, JS, JavaScript, javascript, ECMAScript, ecmascript]

AdoptOpenJDK jdk-14.0.2+12:
  Oracle Nashorn 14.0.2 [nashorn, Nashorn, js, JS, JavaScript, javascript, ECMAScript, ecmascript]

AdoptOpenJDK jdk-15.0.1+9:
  No Script Engines found

As you can see, the OpenJDK version of Java 7 doesn't have a JavaScript engine, because the Mozilla Rhino library isn't open-source. You need the Oracle version of Java 7 to get the JavaScript engine.

You can also see that JavaScript was removed in Java 15, as documented in the JDK 15 Release Notes:

The Nashorn JavaScript script engine, its APIs, and the jjs tool have been removed. The engine, the APIs, and the tool were deprecated for removal in Java 11 with the express intent to remove them in a future release. See JDK-8236933

Hymnology answered 17/1, 2021 at 5:24 Comment(4)
Can you update the question for Java18? And does Rhino works in 18 too?Virginavirginal
OpenJDK Java 19 does NOT have it. SorryNourishing
I am using java 20. It does not include javascript engine. What do I have to do to get javascript functionality working?Jellicoe
Any updates that could get GraalJS working? I have js.exe in: /c/graaljs-community-jvm-23.1.2-windows-amd64/graaljs-community-23.1.2-windows-amd64/bin/js.exeTalos
L
2

I had the same problem with JDK 17 and lib rhino.js.engine-1.7.71.jar.

I added

org.mozilla.javascript-1.7.5.jar

to my classpath too. That solved the error.

Lancelancelet answered 14/4, 2023 at 11:35 Comment(0)
W
0

Or, just directly use rhino itself, without ScriptEngineManager:

pom.xml:

<dependency>
  <groupId>org.mozilla</groupId>
  <artifactId>rhino</artifactId>
  <version>1.7.15</version>
</dependency>

<dependency>
  <groupId>org.mozilla</groupId>
  <artifactId>rhino-engine</artifactId>
  <version>1.7.15</version>
</dependency>

<dependency>
  <groupId>org.mozilla</groupId>
  <artifactId>rhino-runtime</artifactId>
  <version>1.7.15</version>
</dependency>

java code:

import java.util.*;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;


public static String executeScript(String js) {
    // Creates and enters a Context. The Context stores information
    // about the execution environment of a script.
    Context cx = Context.enter();
    try {
        // Initialize the standard objects (Object, Function, etc.)
        // This must be done before scripts can be executed. Returns
        // a scope object that we use in later calls.
        Scriptable scope = cx.initStandardObjects();


        // Now evaluate the string we've colected.
        Object result = cx.evaluateString(scope, js, "<cmd>", 1, null);

        // Convert the result to a string and print it.
        logger.debug(Context.toString(result));
        return (String) result;
    } finally {
        // Exit from the context.
        Context.exit();
    }
}
Whiteheaded answered 30/7, 2024 at 19:26 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.