2

I'm trying to build my javafx program into a .jar file. The program runs fine when i'm running it from intelliJ but won't run from .jar file. I'm using intelliJ with java11 and javafx version 11. I followed all the instructions correctly to build the project into a .jar file but when i run my program i get some strange error (see below). I also checked javafx library in the .jar file and it's there so i don't know why i'm getting this error.

edit: I tried both on Windows and ubuntu but was still getting the error. I used to intelliJ to create the jar file using artefact feature. I made sure to attach javafx (external library) when building the artifact.

[Main.java]

package app;

import javafx.fxml.FXMLLoader;
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import java.util.Objects;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent root = FXMLLoader.load(Objects.requireNonNull(getClass().getResource("ui/index.fxml")));
        primaryStage.getIcons().add(new Image(Objects.requireNonNull(getClass().getResourceAsStream("data/NUIMLogoIcon.png"))));
        primaryStage.setScene(new Scene(root, 740, 600));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

[Launcher.java]

import app.Main;

public class Launcher {
    public static void main(String[] args) {
        Main.main(args);
    }
}

[index.fxml]

<ScrollPane focusTraversable="false"
            hbarPolicy="NEVER"
            maxHeight="-Infinity"
            maxWidth="720.0"
            minHeight="-Infinity"
            minWidth="-Infinity"
            prefHeight="1383.0"
            prefWidth="720.0"
            xmlns="http://javafx.com/javafx/11"
            xmlns:fx="http://javafx.com/fxml/1"
            fx:controller="app.ui.Controller"><!--   LINE 40-->
  <content>
    <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="1374.0" prefWidth="720.0">
         <children>
         

[ERROR]

ninja@ninja-lat5410:~/Desktop/MULECodeLab/out/artifacts/MULECodeLab_jar$ java -jar MULECodeLab.jar 
Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: javafx.fxml.LoadException: 
file:/home/ninja/Desktop/MULECodeLab/out/artifacts/MULECodeLab_jar/MULECodeLab.jar!/app/ui/index.fxml:40

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2603)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3237)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3194)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3163)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3136)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3113)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3106)
    at app.Main.start(Main.java:15)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)

[Controller] removed

[Project repo] removed

lag
  • 520
  • 2
  • 10
  • 26
  • 1
    Include the controller code so everything in the question could be replicated just with copy and paste. – jewelsea Sep 17 '21 at 16:35
  • it's very long file around 1k lines – lag Sep 17 '21 at 16:37
  • Unrelated to your question, but I am curious, why do you create a `Launcher` class? I have seen such a thing in other questions too. It seems redundant and unnecessary to me. – jewelsea Sep 17 '21 at 16:38
  • 2
    Create a [mcve] then. – jewelsea Sep 17 '21 at 16:38
  • Javafx doesn't seems to like Main class that extends Application so another class needs to be created which doesn't extend anything – lag Sep 17 '21 at 16:39
  • added a link to the file – lag Sep 17 '21 at 16:44
  • Thanks for that. If you get some time please do create a minimal example and place the code inline in your question, doing so may increase your chances of getting concrete assistance. – jewelsea Sep 17 '21 at 18:43
  • @jewelsea Some code internal to the JDK requires that the `javafx.graphics` module is present in the boot `ModuleLayer`, but only if the main class extends `Application`. So if you want to allow JavaFX to be loaded from the class-path you have to create a separate "launcher" class that simply launches JavaFX. – Slaw Sep 17 '21 at 20:39
  • @Ninja47 Is there more to the stack trace? Typically `LoadException` has a cause. – Slaw Sep 17 '21 at 20:41
  • 1
    @Slaw thanks for explaining the theory behind the separate `Launcher` class pattern. That would be an [unsupported launch model](https://bugs.openjdk.java.net/browse/JDK-8256362) which is not recommended and may not continue to function as expected in future JavaFX versions. Modern JavaFX versions are designed to run only from the module path and are only supported in that configuration. Note: having your app code and other libraries on the class path with all `javafx` modules on the module path would still be a supported configuration. Note also, this is not the fxml error here. – jewelsea Sep 17 '21 at 21:29
  • 1
    @jewelsea Yeah, I try to avoid suggesting the workaround these days (especially since a warning is now emitted). I've even tried to go back to some of my answers and warn that loading JavaFX from the class-path is unsupported. But for a while (versions 9 to 15) there was no official discouragement for putting JavaFX on the class-path, and so this workaround has become rather well known. Especially back when tools like Maven and Gradle didn't handle modules properly out-of-the-box. – Slaw Sep 17 '21 at 22:48
  • So is the answer to [my question](https://stackoverflow.com/questions/69226778/javafx-jar-file-wont-run-on-ubuntu-20-04-from-terminal#comment122360774_69226778) yes or no? – Slaw Sep 19 '21 at 23:22
  • no, unfortunately – lag Sep 21 '21 at 14:14
  • Can you share the content of your jar file? Or can you describe how you jar is built? – Mumrah81 Sep 23 '21 at 15:49
  • You wrote "on ubuntu 20.4", does it work on Windows ? Did you already run successfully a java application with a gui from the command line on this ubuntu? – Mumrah81 Sep 23 '21 at 15:55
  • Really helpful would be if you used something like Maven/Gradle . We have no idea how you built your jar. – Alex Sep 24 '21 at 17:04
  • I guess providing the instructions on how to build the jar for the program would be good – Alex Sep 24 '21 at 17:10
  • @Alex instructions on how i created jar file is now included in the description – lag Sep 24 '21 at 19:43
  • 1
    Unfortunately, without one or more subsequent `Caused by:`s, I think it will be very difficult for anyone to provide help. The `LoadException` doesn't tell us anything except that an error occurred. This is to be expected, as that exception is supposed _wrap_ the exception that would tell us what's really going wrong. Though, looking at the source code of JavaFX 11, I don't see how it's possible there's not more to the stack trace. Line `2603` of `FXMLLoader` is literally just `throw constructLoadException(exception)`, which itself simply creates a `LoadException` with `exception` as the cause – Slaw Sep 25 '21 at 03:49
  • see this link that must help you : [how-to-run-javafx-application-from-command-line](https://stackoverflow.com/questions/62129569/how-to-run-javafx-application-from-command-line) – Ashkan Khaleghi Sep 25 '21 at 17:15
  • see this link i desired help you : [How to run JavaFx application from command line](https://stackoverflow.com/questions/62129569/how-to-run-javafx-application-from-command-line) – Ashkan Khaleghi Sep 25 '21 at 17:17
  • Btw in the IntelliJ docs it says something like: "Go use some other tool to package java fx applications" https://www.jetbrains.com/help/idea/packaging-javafx-applications.html#java_fx_build_artifact If you're using a JDK build of version 9 and later, use third-party solutions for packaging. – Alex Sep 25 '21 at 21:27
  • It might be you are trying something that is impossible/really hard. Easy fix would be use a proper build tool like gradle and steal some config from some working application. I tried building a java fx jar with IntelliJ and I fail. Like one thing you really would need to do as well is load the native libraries(the .so files). That is simply not possible from a jar. Either you have a jdk that includes the java fx sdk or you need to pass some parameter to java.So building a jar at all seems to be a bad idea unless the jre you are running it with includes java fx which it does not by default – Alex Sep 25 '21 at 21:40
  • add a module... I think it will give you hints where things are going bad – Harley Sep 26 '21 at 09:09
  • it's a tricky one.. it's like you say running fine in Intellij... it can't find the css but I don't think that's a deal breaker... it doesn't like your index.fxml but that loads okay in intellij and scenebuilder – Harley Sep 26 '21 at 09:37
  • There's an error in HTMLDataStorage.java, I just made the line... `css = "../../style.css";` and put style.css in the app package folder, but then there's more errors - that fixes the java.nio.file.NoSuchFileException error about the style.css not being found. – Harley Sep 26 '21 at 12:14
  • then there's more path errors – Harley Sep 26 '21 at 12:18
  • it's looking like the problems aren't FXML related, check the paths in ScriptsDataStorage.java, they're not working – Harley Sep 26 '21 at 12:22
  • ok, I got it to load from the jar in the terminal... heaps of errors, but it loaded... I'll post an answer – Harley Sep 26 '21 at 12:43

1 Answers1

1

First, your FXML is fine. There are other issues... There's an error in HTMLDataStorage.java, I just made the line... css = "../../style.css"; and put style.css in the app package folder - that fixes the java.nio.file.NoSuchFileException error about the style.css not being found.

Next... ScriptsDataStorage.java, this ain't working. This was my quick fix. Maybe you can do something better:

public List<Regex> getPredefinedRegex() {

        ArrayList<String> comments = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new FileReader("../../data/comments.txt"))) {
            while (br.ready()) {
                comments.add(br.readLine());
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        ArrayList<String> regex = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new FileReader("../../data/regex.txt"))) {
            while (br.ready()) {
                regex.add(br.readLine());
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //String[] comments = Util.readlines("comments.txt").split("\n");
        //String[] regex = Util.readlines("regex.txt").split("\n");

        // [ASSUMPTION] regex and comments are the same length
        // conversion from java to bash format
        for (int i = 0; i < regex.size(); i++) {
            regex.set(i, regex.get(i).replace("\\", "\\\\"));
        }

        int size = Math.min(comments.size(), regex.size());
        List<Regex> list = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            list.add(new Regex(regex.get(i), comments.get(i)));
        }
        return  list;
    }

It now builds and loads when your run it from the terminal or double click on the jar file... but it spits out lots of errors in the terminal still.

It's getting java.io.FileNotFoundException for comments.txt and regex.txt and I'm having great difficulty solving it.

I see I've completely sabotaged your Util.readlines(). I got the GUI to load using the terminal though! You can ignore my code.

Focus on this:

Your problems are your paths when you build aren't working

Harley
  • 1,305
  • 1
  • 13
  • 28