gluonhq / gluonfx-maven-plugin

Plugin that simplifies creating native images for Java/JavaFX maven projects
BSD 3-Clause "New" or "Revised" License
188 stars 39 forks source link

Swing And JavaFX application run fails #443

Open ygarg465 opened 2 years ago

ygarg465 commented 2 years ago

I am trying to create a native-image of a straightforward application 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);
    }
}

Please let me know if any more information is needed

Khithar commented 1 year ago

mvn gluonfx:runagent and click through everything before mvn gluonfx:build copy your .exe to graalvm\bin and execute it from there - if it works there, the awt and dependent dll's are missing and they must exist in the directory where you start the .exe