Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to execute simple JavaScript expressions in Java 21 without any manual installations? [closed]

I have version 21 installed and as far as I understand, I can't use Nashorn engine anymore, but maybe GraalVM is available for me?

I have installed all the necessary dependencies:

<dependency>
    <groupId>org.graalvm.js</groupId>
    <artifactId>js</artifactId>
    <version>21.1.0</version>
</dependency>
<dependency>
    <groupId>org.graalvm.js</groupId>
    <artifactId>js-scriptengine</artifactId>
    <version>21.1.0</version>
</dependency>

Here is a simple example that I'm trying to execute:

public static void main(String[] args) throws ScriptException {
    try (Context context = Context.newBuilder("js")
            .allowAllAccess(true)
            .build()) {
        // Evaluate JavaScript code
        String jsCode = "console.log('Hello, GraalVM!');";
        context.eval("js", jsCode);
    } catch (Exception e) {
        throw new ScriptException("Script execution failed: " + e.getMessage());
    }
}

However, I get an error:

Exception in thread "main" javax.script.ScriptException: Script execution failed: A language with id 'js' is not installed. Installed languages are: []. at org.example.Main.main(Main.java:23)

I also tried something like this:

public static void main(String[] args) throws ScriptException {
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine  = manager.getEngineByName("JavaScript");
    engine.eval("print('HI');");
}

But I got another error:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "javax.script.ScriptEngine.eval(String)" because "engine" is null at org.example.Main.main(Main.java:20)

The problem is that manual installation of any components is impossible for some reason. I just need to some dependencies and make everything works. Something "out of the box". Is there any workaround for this problem? Maybe there are any other available engines?


1 Answers

Graalvm js - Project

jsEngineScriptJDK21_graalvm_js

├── pom.xml
└── src
    └── main
        └── java
            └── com
                └── example
                    └── JsTest.java

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>graalvm-js-engine-script</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>GraalvmJsEngineScript</name>
    <description>jsEngineScript App Project</description>
    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>

    <dependency>
        <groupId>org.graalvm.js</groupId>
        <artifactId>js</artifactId>
        <version>23.0.0</version>
    </dependency>
        
    </dependencies>    

    <build>
        <finalName>app</finalName>
    </build>

</project>

JsTest.java

package com.example;

import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;

public class JsTest {

  public static void main(String[] args) throws Exception {
  
    try (Context context = Context.newBuilder("js")
            .allowAllAccess(true)
            .build()) {
        // Evaluate JavaScript code
        String jsCode = "console.log('Hello, GraalVM!');";
        context.eval("js", jsCode);
    } catch (Exception e) {
        throw new Exception("Script execution failed: " + e.getMessage());
    }
    
  }
  
}

JsTest3.java

package com.example;

import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;

public class JsTest3 {

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

        try (Context context = Context.newBuilder("js")
                .option("engine.WarnInterpreterOnly", "false")
                .allowAllAccess(true)
                .build()) {

            Value result = context.eval("js", "2 + 2");
            System.out.println("Result: " + result.asInt());

            // Call JavaScript Function
            context.eval("js", "function greet(name) { return 'Hello, ' + name; }");
            Value greetFunction = context.getBindings("js").getMember("greet");
            System.out.println("Greeting: " + greetFunction.execute("World").asString());


            // Evaluate JavaScript code
            String jsCode = "print('HI');";
            context.eval("js", jsCode);

        } catch (Exception e) {
            throw new Exception("Script execution failed: " + e.getMessage());
        }

    }

}

Build And Run

Build

mvn clean package

mvn dependency:copy-dependencies -DoutputDirectory=target/libs

Run

JsTest

java -cp "target/libs/*:target/app.jar" \
  com.example.JsTest

Result:

[To redirect Truffle log output to a file use one of the following options:
* '--log.file=<path>' if the option is passed using a guest language launcher.
* '-Dpolyglot.log.file=<path>' if the option is passed using the host Java launcher.
* Configure logging using the polyglot embedding API.]
[engine] WARNING: The polyglot context is using an implementation that does not support runtime compilation.
The guest application code will therefore be executed in interpreted mode only.
Execution only in interpreted mode will strongly impact the guest application performance.
For more information on using GraalVM see https://www.graalvm.org/java/quickstart/.
To disable this warning the '--engine.WarnInterpreterOnly=false' option or use the '-Dpolyglot.engine.WarnInterpreterOnly=false' system property.
Hello, GraalVM!

JsTest3

java -cp "target/libs/*:target/app.jar" \
  com.example.JsTest3

Result: There is no warning message.

Result: 4
Greeting: Hello, World
HI

JDK Version

$ javac -version
javac 21.0.4

$ java -version
openjdk version "21.0.4" 2024-07-16 LTS
OpenJDK Runtime Environment Temurin-21.0.4+7 (build 21.0.4+7-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.4+7 (build 21.0.4+7-LTS, mixed mode, sharing)

Notice:

  • (1) This example project uses a general JDK; you can try to use it with GraalVM CE or GraalVM Oracle JDK for your testing.
  • (2) Do not use Zulu JDK; if you use Zulu JDK to execute this sample project, there will be other error messages.
  • (3) When using IDE (Eclipse, IDEA) to develop Maven projects, if there are errors such as class not found, you can do this:
    • (a) Try to execute Command Line in Terminal, mvn clean package. If no error occurs, it is a problem with the IDE.
    • (b) Try Refresh Maven in the IDE. Let the IDE capture the content after updating the pom.xml settings.

nashorn script engine - Project

jsEngineScriptJDK21

├── pom.xml
└── src
    └── main
        └── java
            └── com
                └── example
                    └── JsTest.java

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>js-engine-script</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>jsEngineScript</name>
    <description>jsEngineScript App Project</description>
    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.openjdk.nashorn</groupId>
            <artifactId>nashorn-core</artifactId>
            <version>15.4</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>app</finalName>
    </build>

</project>

JsTest.java

package com.example;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class JsTest {
    public static void main(String[] args) throws ScriptException {
        try {
            //ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
            //ScriptEngine engine  =new ScriptEngineManager().getEngineByName("JavaScript");
            ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine engine  = manager.getEngineByName("JavaScript");

            if (engine == null) {
                System.out.println("Nashorn script engine not available.");
                return;
            }

            engine.eval("print('HI');");
            engine.eval("print('Hello, Nashorn!');");
            engine.eval("var x = 10 + 20; print('x = ' + x);");

        } catch (ScriptException e) {
            e.printStackTrace();
        }
    }
}

Build And Run

Build

mvn clean package

mvn dependency:copy-dependencies -DoutputDirectory=target/libs

Run

java -cp "target/libs/*:target/app.jar" \
  com.example.JsTest

Result:

HI
Hello, Nashorn!
x = 30
like image 122
life888888 Avatar answered Sep 19 '25 15:09

life888888