I need to add a new feature to my Java-8-based application (can't upgrade Java) where it takes an encoded string and decodes it to a JSON. The issue is that that decoding library is written in JavaScript, and the effort to convert the JavaScript code to Java could be consequential.
Looking into alternative solutions, I came across Nashorn, which supposedly is able to run Javascript code from Java. And so I tried to make it work.
First, I created a project with my `index.js" file containing an import statement and a function:
import codec from "some-package"
function decode(a, b) {
...
}
I then installed the necessary packages through npm -i and ran my JavaScript code to verify that it worked by itself. Both node index.js and running the code through the right click action of VisualStudio ("Run Code") worked.
Then, I tried to make it work with Java. I moved all the files from my front project into the resources folder of Java, I created a test project with a main() function, and I wrote the following code:
NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
ScriptEngine engine = factory.getScriptEngine("--language=es6");
try (Reader reader = new InputStreamReader(Objects.requireNonNull(Pulse4Decoder.class.getClassLoader().getResourceAsStream(DECODER_FILE_NAME)), StandardCharsets.UTF_8))
{
engine.eval(reader);
}
I then ran this code but got the following error:
Exception in thread "main" javax.script.ScriptException: <eval>:2:0 Expected an operand but found import
import codec from "some-package";
^ in <eval> at line number 2 at column number 0
at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:470)
at jdk.nashorn.api.scripting.NashornScriptEngine.compileImpl(NashornScriptEngine.java:537)
at jdk.nashorn.api.scripting.NashornScriptEngine.compileImpl(NashornScriptEngine.java:524)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:402)
at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:150)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:249)
at com.edoreld.decoder.Pulse4Decoder.decode(Pulse4Decoder.java:30)
at com.edoreld.decoder.Pulse4Decoder.main(Pulse4Decoder.java:20)
I thought the problem could be due to Nashorn requiring a specific form of the import statement, so I changed it to const codec = require('@adeunis/codecs');. However, this failed with the following error:
Exception in thread "main" javax.script.ScriptException: ReferenceError: "require" is not defined in <eval> at line number 1
at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:470)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:454)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:406)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:402)
at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:150)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:249)
at com.edoreld.decoder.Pulse4Decoder.decode(Pulse4Decoder.java:30)
at com.edoreld.decoder.Pulse4Decoder.main(Pulse4Decoder.java:20)
I googled both errors (which is how I came to use --language=es6 in my code originally), but I wasn't able to make it work.
Are import/require statements not supported in Nashorn? How am I supposed to call a function in a JavaScript file that required a specific package if I can't make import/require to work?