Swing and JavaFX native image with GraalVM - no awt in java.library.path error

Viewed 89

I am trying to create a native-image of a straightforward application using gluonfx-maven-plugin but it requires being a Swing application with JFrame and JFXPanel to run JavaFX UI as I am using Java Chromium Embedded Framework (JCEF) to replace Javafx WebView on Windows as GraalVM does not currently support it. And JavaFX does not render the browser correctly, hence Swing usage. Plugin's build command runs perfectly fine but when I try to run the image using nativerun it fails to run.

C:\Users\Yash\Documents\Gluon-SingleViewProject\target\gluonfx>mvn -f "C:\Users\Yash\Documents\Gluon-SingleViewProject\pom.xml" com.gluonhq:gluonfx-maven-plugin:1.0.15:nativerun
[INFO] Scanning for projects...
[INFO]
[INFO] ------------< com.gluonapplication:gluon-singleviewproject >------------
[INFO] Building Gluon-SingleViewProject 1.0-SNAPSHOT
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- gluonfx-maven-plugin:1.0.15:nativerun (default-cli) @ gluon-singleviewproject ---
[Tue Sep 13 20:37:44 IST 2022][INFO] ==================== RUN TASK ====================
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB] Exception in thread "main" java.lang.UnsatisfiedLinkError: no awt in java.library.path
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at com.oracle.svm.core.jdk.NativeLibrarySupport.loadLibraryRelative(NativeLibrarySupport.java:132)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.lang.ClassLoader.loadLibrary(ClassLoader.java:47)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.lang.Runtime.loadLibrary0(Runtime.java:818)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.lang.System.loadLibrary(System.java:1989)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.awt.Toolkit$2.run(Toolkit.java:1388)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.awt.Toolkit$2.run(Toolkit.java:1386)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.security.AccessController.executePrivileged(AccessController.java:169)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.security.AccessController.doPrivileged(AccessController.java:318)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.awt.Toolkit.loadLibraries(Toolkit.java:1385)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.awt.Toolkit.initStatic(Toolkit.java:1423)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.awt.Toolkit.<clinit>(Toolkit.java:1397)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.awt.Component.<clinit>(Component.java:624)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.lang.Class.ensureInitialized(DynamicHub.java:518)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.lang.Class.ensureInitialized(DynamicHub.java:518)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.lang.Class.ensureInitialized(DynamicHub.java:518)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.lang.Class.ensureInitialized(DynamicHub.java:518)
[Tue Sep 13 20:37:44 IST 2022][INFO] [SUB]      at java.lang.Class.ensureInitialized(DynamicHub.java:518)
             _______  ___      __   __  _______  __    _
            |       ||   |    |  | |  ||       ||  |  | |
            |    ___||   |    |  | |  ||   _   ||   |_| |
            |   | __ |   |    |  |_|  ||  | |  ||       |
            |   ||  ||   |___ |       ||  |_|  ||  _    |
            |   |_| ||       ||       ||       || | |   |
            |_______||_______||_______||_______||_|  |__|

    Access to the latest docs, tips and tricks and more info on
    how to get support? Register your usage of Gluon Substrate now at

    https://gluonhq.com/activate

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  4.139 s
[INFO] Finished at: 2022-09-13T20:37:46+05:30
[INFO] ------------------------------------------------------------------------

Application Code

package com.gluonapplication;

import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import org.cef.CefApp;
import org.cef.CefClient;
import org.cef.CefSettings;
import org.cef.browser.CefBrowser;
import org.cef.browser.CefFrame;
import org.cef.handler.CefAppHandlerAdapter;
import org.cef.handler.CefDisplayHandlerAdapter;
import org.cef.handler.CefFocusHandlerAdapter;

import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.Serial;

public class MainFrame extends JFrame {
    @Serial
    private static final long serialVersionUID = -5570653778104813836L;
    private final JTextField address_;
    private final CefApp cefApp_;
    private final CefClient client_;
    private final CefBrowser browser_;
    private final Component browerUI_;
    private boolean browserFocus_ = true;

    private MainFrame(String startURL, boolean useOSR, boolean isTransparent) {
        CefApp.addAppHandler(new CefAppHandlerAdapter(null) {
            @Override
            public void stateHasChanged(org.cef.CefApp.CefAppState state) {
                if (state == CefApp.CefAppState.TERMINATED) System.exit(0);
            }
        });
        CefSettings settings = new CefSettings();
        settings.windowless_rendering_enabled = useOSR;
        cefApp_ = CefApp.getInstance(settings);

        client_ = cefApp_.createClient();

        browser_ = client_.createBrowser(startURL, useOSR, isTransparent);
        browerUI_ = browser_.getUIComponent();

        address_ = new JTextField(startURL, 100);
        address_.addActionListener(e -> browser_.loadURL(address_.getText()));

        client_.addDisplayHandler(new CefDisplayHandlerAdapter() {
            @Override
            public void onAddressChange(CefBrowser browser, CefFrame frame, String url) {
                address_.setText(url);
            }
        });

        address_.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                if (!browserFocus_) return;
                browserFocus_ = false;
                KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
                address_.requestFocus();
            }
        });

        client_.addFocusHandler(new CefFocusHandlerAdapter() {
            @Override
            public void onGotFocus(CefBrowser browser) {
                if (browserFocus_) return;
                browserFocus_ = true;
                KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
                browser.setFocus(true);
            }

            @Override
            public void onTakeFocus(CefBrowser browser, boolean next) {
                browserFocus_ = false;
            }
        });

        getContentPane().add(address_, BorderLayout.NORTH);
        getContentPane().add(browerUI_, BorderLayout.CENTER);
        JFXPanel jfxPanel = new JFXPanel();
        javafx.scene.control.Button button = new javafx.scene.control.Button("Print");
        button.setOnAction(e -> browser_.print());
        jfxPanel.setScene(new Scene(button));
        getContentPane().add(jfxPanel, BorderLayout.SOUTH);
        pack();
        setSize(800, 600);
        setVisible(true);

        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                CefApp.getInstance().dispose();
                dispose();
            }
        });
    }

    public static void main(String[] args) {
        if (!CefApp.startup(args)) {
            System.out.println("Startup initialization failed!");
            return;
        }

        boolean useOsr = false;
        new MainFrame("https://www.google.com", useOsr, false);
    }
}

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>com.gluonapplication</groupId>
    <artifactId>gluon-singleviewproject</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>Gluon-SingleViewProject</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.release>17</maven.compiler.release>
        <javafx.version>18.0.2</javafx.version>
        <gluonfx.plugin.version>1.0.15</gluonfx.plugin.version>
        <javafx.plugin.version>0.0.8</javafx.plugin.version>
        <mainClassName>com.gluonapplication.MainFrame</mainClassName>
    </properties>

    <dependencies>
        <dependency>
            <groupId>me.friwi</groupId>
            <artifactId>jcefmaven</artifactId>
            <version>105.3.36</version>
            <exclusions>
                <exclusion>
                    <groupId>me.friwi</groupId>
                    <artifactId>jogl-all</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.googlecode.json-simple</groupId>
                    <artifactId>json-simple</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>me.friwi</groupId>
            <artifactId>gluegen-rt</artifactId>
            <version>2.4.0</version>
        </dependency>
        <dependency>
            <groupId>me.friwi</groupId>
            <artifactId>jogl-all</artifactId>
            <version>2.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-graphics</artifactId>
            <version>17.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>17.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-swing</artifactId>
            <version>17.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>17.0.2</version>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>Gluon</id>
            <url>https://nexus.gluonhq.com/nexus/content/repositories/releases</url>
        </repository>
    </repositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>15</source>
                    <target>15</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>assemble-all</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.2.2</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>${mainClassName}</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>com.gluonhq</groupId>
                <artifactId>gluonfx-maven-plugin</artifactId>
                <version>${gluonfx.plugin.version}</version>
                <configuration>
                    <target>host</target>
                    <attachList>
                        <list>display</list>
                        <list>lifecycle</list>
                        <list>statusbar</list>
                        <list>storage</list>
                    </attachList>
                    <mainClass>${mainClassName}</mainClass>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.8</version>
                <executions>
                    <execution>
                        <id>default-cli</id>
                        <configuration>
                            <mainClass>${mainClassName}</mainClass>
                            <launcher>app</launcher>
                            <jlinkZipName>app</jlinkZipName>
                            <jlinkImageName>app</jlinkImageName>
                            <noManPages>true</noManPages>
                            <stripDebug>true</stripDebug>
                            <noHeaderFiles>true</noHeaderFiles>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

0 Answers
Related