javascriptjavanetbeansfxml

How do I solve Nashorn removal and JS replacement in Netbeans 22?


Despite having followed every procedure exactly as specified to install an alternative to Nashorn in Netbeans 22, I still get the following error when trying to build a FXML project:

Java 15 has removed Nashorn, you must provide an engine for running JavaScript yourself.

GraalVM JavaScript is the js that I am trying to integrate. Following the Oracle graalvm page I downloaded and extracted the following:

https://download.oracle.com/graalvm/22/latest/graalvm-jdk-22_windows-x64_bin.zip

Extracted the download to the directory C:Program Files/Java/graalvm-jdk-22.0.1+8.1 and renamed the folder graalvm-22

In an admin cmd shell, set JAVA_HOME environment variable with:

setx /M JAVA_HOME "C:\Progra~1\Java\graalvm-22"

and set the path with:

setx /M PATH "C:\Progra~1\Java\<graalvm>\bin;%PATH%"

Checked these variables with echo, which showed:

echo %JAVA_HOME%
C:\Progra~1\Java\graalvm-22

echo %PATH%
C:\Progra~1\Java\graalvm-22\bin;
C:\Program Files\CommonFiles\Oracle\Java\javapath;
C:\WINDOWS\system32;
C:\WINDOWS;
C:\WINDOWS\System32\Wbem;
C:\WINDOWS\System32\WindowsPowerShell\v1.0\;
C:\WINDOWS\System32\OpenSSH\;
C:\Program Files\HP\HP One Agent;C:\Users\qabpa\AppData\Local\Microsoft\WindowsApps;

I have been stuck for a few days with this issue and would appreciate help. Thanks.


Solution

  • This is just an example of Java + JavaFX + nashorn Script Engine.

    If you want to integrate GraalVM JavaScript, it should be another answer. ( https://github.com/graalvm/polyglot-embedding-demo ) only GraalVM , not include JavaFX.

    Remove or Uninstall All

    Install zulu JDK include JavaFX

    https://www.azul.com/downloads/?version=java-21-lts&os=windows&architecture=x86-64-bit&package=jdk-fx#zulu

    Download -> .msi

    JDK_000.png

    zulu21.34.19-ca-fx-jdk21.0.3-win_x64.msi

    click zulu21.34.19-ca-fx-jdk21.0.3-win_x64.msi

    Drop down Set JAVA_HOME variable , Select Entire feature will be installed on local hard drive

    JDK_001.png

    Click Next

    JDK_002.png

    Please note that you do not need to set the JAVA_HOME or PATH environment variables yourself.

    Because the installation program has been automatically configured.

    Check JDK install

    Open CMD , input command javac -version

    javac 21.0.3
    

    input another command : java -version

    openjdk version "21.0.3" 2024-04-16 LTS
    OpenJDK Runtime Environment Zulu21.34+19-CA (build 21.0.3+9-LTS)
    OpenJDK 64-Bit Server VM Zulu21.34+19-CA (build 21.0.3+9-LTS, mixed mode, sharing)
    

    Install Netbeans 22

    Note, please use exe to install and not zip.

    click Apache-NetBeans-22-bin-windows-x64.exe

    Netbeans_001.png

    NetBeans will detected Zulu-21

    click Next

    Netbeans_002.png

    Click Install

    Config JavaFX

    Menu Tools -> Options

    Netbeans_JavaFX_001.png

    Click Next

    Netbeans_JavaFX_002.png

    Select accept the terms in all of the license agreements.

    Click Install

    Netbeans_JavaFX_003.png

    Click Finish

    Netbeans_JavaFX_004.png

    Click OK

    Create JavaFX Example

    File -> New Project...

    Netbeans_Example_001.png

    Click Next

    Netbeans_Example_002.png

    Click Finish

    Netbeans_Example_003.png

    Click Icon (Run)

    Then appear the javafx window.

    Create Script Engine

    Project Directory Tree

    hello1fx
    ├── nbactions.xml
    ├── pom.xml
    └── src
        ├── main
        │   ├── java
        │   │   ├── com
        │   │   │   └── example
        │   │   │       └── hello1fx
        │   │   │           ├── App.java
        │   │   │           └── PrimaryController.java
        │   │   └── module-info.java
        │   └── resources
        │       └── com
        │           └── example
        │               └── hello1fx
        │                   └── primary.fxml
        └── test
            └── java
    

    pom.xml

    <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/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.example</groupId>
        <artifactId>hello1fx</artifactId>
        <version>1.0-SNAPSHOT</version>
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>21</maven.compiler.source>
            <maven.compiler.target>21</maven.compiler.target>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-controls</artifactId>
                <version>21</version>
            </dependency>
            <dependency>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-fxml</artifactId>
                <version>21</version>
            </dependency>
            <dependency>
                <groupId>org.openjdk.nashorn</groupId>
                <artifactId>nashorn-core</artifactId>
                <version>15.4</version>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                    <configuration>
                        <release>11</release>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.openjfx</groupId>
                    <artifactId>javafx-maven-plugin</artifactId>
                    <version>0.0.4</version>
                    <configuration>
                        <mainClass>com.example.hello1fx.App</mainClass>
                    </configuration>
                    <executions>
                        <execution>
                            <!-- Default configuration for running -->
                            <!-- Usage: mvn clean javafx:run -->
                            <id>default-cli</id>
                        </execution>
                        <execution>
                            <!-- Configuration for manual attach debugging -->
                            <!-- Usage: mvn clean javafx:run@debug -->
                            <id>debug</id>
                            <configuration>
                                <options>
                                    <option>-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=localhost:8000</option>
                                </options>
                            </configuration>
                        </execution>
                        <execution>
                            <!-- Configuration for automatic IDE debugging -->
                            <id>ide-debug</id>
                            <configuration>
                                <options>
                                    <option>-agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address}</option>
                                </options>
                            </configuration>
                        </execution>
                        <execution>
                            <!-- Configuration for automatic IDE profiling -->
                            <id>ide-profile</id>
                            <configuration>
                                <options>
                    <option>${profiler.jvmargs.arg1}</option>
                    <option>${profiler.jvmargs.arg2}</option>
                    <option>${profiler.jvmargs.arg3}</option>
                    <option>${profiler.jvmargs.arg4}</option>
                    <option>${profiler.jvmargs.arg5}</option>
                                </options>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </project>
    
            <dependency>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-controls</artifactId>
                <version>21</version>
            </dependency>
            <dependency>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-fxml</artifactId>
                <version>21</version>
            </dependency>
            <dependency>
                <groupId>org.openjdk.nashorn</groupId>
                <artifactId>nashorn-core</artifactId>
                <version>15.4</version>
            </dependency>
    

    primary.fxml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.layout.VBox?>
    <?import javafx.scene.control.TextArea?>
    <?import javafx.scene.control.Button?>
    <?import javafx.geometry.Insets?>
    
    <VBox alignment="CENTER" spacing="20.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.hello1fx.PrimaryController">
       <children>
          <TextArea fx:id="inputArea" text="" promptText="Enter your script here..." />
          <Button fx:id="runButton" text="run" onAction="#execRun"/>
          <Button fx:id="cleanButton" text="clean" onAction="#execClean"/>
          <TextArea fx:id="outputArea" text="" editable="false" />
       </children>
    </VBox>
    

    module-info.java

    module com.example.hello1fx {
        requires javafx.controls;
        requires javafx.fxml;
        
        requires java.scripting;
        requires jdk.dynalink;
        
        opens com.example.hello1fx to javafx.fxml;
        exports com.example.hello1fx;
    }
    

    App.java

    package com.example.hello1fx;
    
    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    import java.io.IOException;
    
    /**
     * JavaFX App
     */
    public class App extends Application {
    
        private static Scene scene;
    
        @Override
        public void start(Stage stage) throws IOException {
            scene = new Scene(loadFXML("primary"), 640, 480);
            stage.setScene(scene);
            stage.setTitle("Nashorn JavaScript Engine");
            stage.show();
        }
    
        static void setRoot(String fxml) throws IOException {
            scene.setRoot(loadFXML(fxml));
        }
    
        private static Parent loadFXML(String fxml) throws IOException {
            FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml + ".fxml"));
            return fxmlLoader.load();
        }
    
        public static void main(String[] args) {
            launch();
        }
    
    }
    

    PrimaryController.java

    package com.example.hello1fx;
    
    import java.io.IOException;
    import javafx.fxml.FXML;
    import javafx.scene.control.TextArea;
    
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    import java.io.PrintWriter;
    import java.io.StringWriter;
    
    public class PrimaryController {
        ScriptEngineManager manager ;
        ScriptEngine engine;
        @FXML
        private TextArea inputArea;
        
        @FXML
        private TextArea outputArea;
        
        @FXML
        private void execRun() throws IOException {
                manager = new ScriptEngineManager();
                engine = manager.getEngineByName("nashorn");
                StringWriter writer  = new StringWriter();
                engine.getContext().setWriter(writer);
    
                try {
                    String inputText = inputArea.getText();
                    System.out.println(">>> inputText = "+inputText);
                    engine.eval(inputText );
                    System.out.println(">>> OK");
                    outputArea.setText( "Processed: \n"+writer.toString());
                    System.out.println(">>> set output OK");
                } catch (ScriptException e1) {
                    e1.printStackTrace(new PrintWriter(writer));
                }       
        }
        
        @FXML
        private void execClean() throws IOException {
            inputArea.clear();
            outputArea.clear();
        }
    }
    

    Final Result

    Click Icon Run Again

    JavaFX_Script_001.png

    in (1) input area put some java script code.

    print('Hello World!')
    print(100 + 200)
    

    Click Button run (3)

    Then show the result in (2)

    You can click Button clean (4) to clean (1) & (2)