0

I'm trying my hardest to export my javafx(11) projects, but nothing seems to work. I am on IntelliJ IDE, and for example let's use this project: https://github.com/EveningSt3r/JFX-hotel-project. (I wrote this in 30 minutes but it's simple and fills this question's purpose)

When I use IntelliJ's Build Artifacts function: "fx:deploy is not available" I have no idea how to use jlink, and all tutorials online are stumping me. Most javafx tutorials are from when it was part of the JDK, so that doesn't help. I have no idea how to use Maven and Gradle.

This is coming from a dude who doesn't have a great understanding of how Java actually works, just knows how to make stuff.

I've spent weeks trying to figure this out, so can someone please just dumb it down to baby levels for me, on how to get this into something runnable or an exe? I know I sound stupid but I'm just tired

  • What is the ```module-info.java``` file? That's not valid Java qualified name and IntelliJ doesn't allow its creation... How'd it get there? And why is it there? – Chaos_Is_Harmony Aug 30 '21 at 00:57
  • I'm taking the Tim Buchalka Java course. He makes it there. It's where I define module dependencies, and you make it by right clicking src and then selecting new (module-info). Without it my app doesn't run, (I suspect this is a java 11 thing) – EveningSt3r Aug 30 '21 at 01:33
  • 1
    @Chaos_Is_Harmony The `module-info.java` file is the module descriptor, which is part of the _Java Platform Module System_ added in Java 9. Any IntelliJ version capable of handling Java 9+ should understand that file. That said, it is not required to have a module descriptor (though with JavaFX that may involve a mixture of JavaFX placed on the module-path while your own code/other dependencies are placed on the class-path). – Slaw Aug 30 '21 at 01:39
  • 1
    @Yeetles Is it possible for you to use Java 14+? If so, you may want to check out the [packaging tool `jpackage`](https://docs.oracle.com/en/java/javase/16/jpackage/packaging-overview.html#GUID-C1027043-587D-418D-8188-EF8F44A4C06A). It was an incubating feature in Java 14-15 and was standardized in Java 16, if I'm not mistaken. You may also want to check out [JPackageScriptFX](https://github.com/dlemmermann/JPackageScriptFX) (never tried it out myself but it's recommended by another user on here). – Slaw Aug 30 '21 at 01:44
  • @Slaw I'll try it out when I get home. Two things though: 1: I just need to install java 14 and I can use jpackage from the command line, correct? 2. Could you theoretically dumb down the command I'd have to use for this project? I did take a look at the jpackage documentation earlier this week and it stumped me. – EveningSt3r Aug 30 '21 at 01:46
  • If you're going to upgrade the Java version then you might as well go with Java/JavaFX version 16. It's the latest release (though Java 17, and probably JavaFX 17, are just around the corner). But yes, if you download a Java version which includes `jpackage` then you will be able to invoke it from the command-line. I added a community answer showing a minimal example. But keep in mind that since you're using an IDE some of the steps are likely to be different for you. – Slaw Aug 30 '21 at 02:31
  • @Slaw Yes, the *jpackage* tool was officially delivered as part of Java 16. See [*JEP 392: Packaging Tool*](https://openjdk.java.net/jeps/392). But I would use [early-access Java 17](https://jdk.java.net/17/), given that its release is due next month, and will likely be a Long-Term Support (LTS) version. – Basil Bourque Aug 30 '21 at 02:36
  • Please provide enough code so others can better understand or reproduce the problem. – Community Aug 31 '21 at 16:42

2 Answers2

1

One option is to use the jpackage tool. That tool was an incubating feature in Java 14-15 and was standardized in Java 16. It creates a self-contained application. In other words, the resulting application contains not only your own code and any dependencies, but an embedded Java Runtime Environment (JRE) as well. That way your end users don't need to worry about having Java or JavaFX installed. Instead, they end up with a native installer/executable.

There is a user guide for jpackage. There's also a script another user on this site (along with others, if I'm not mistaken) has created that may make things simpler for you: JPackageScriptFX.


Here is a minimal example of creating a JavaFX application, where the application is packaged with jpackage, entirely from the command line. The example assumes a modular application (i.e. your code and all dependencies have a module-info file), but jpackage is also capable of packaging class-path based applications (i.e. non-modular applications).

Project Structure

├───out
│   ├───classes
│   └───package
└───src
    └───com.example
        │   module-info.java
        │
        └───com
            └───example
                └───app
                        Main.java

Note I have the source code under a directory named com.example. That is the same name as the module and makes working with javac manually easier (when compiling modules). However, you don't need to do that. In fact, if you're using an IDE then your source code is likely directly under src (or src/main/java if using Maven/Gradle).

Since you're likely letting your IDE compile the code I would not recommend creating a directory whose name matches the module name.

Source Files

Here is the module-info.java file:

module com.example {
  requires javafx.controls;

  exports com.example.app to javafx.graphics;
}

Here is the Main.java file:

package com.example.app;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {

  public void start(Stage primaryStage) {
    StackPane root = new StackPane(new Label("Hello, World!"));
    Scene scene = new Scene(root, 500, 300);
    primaryStage.setScene(scene);
    primaryStage.setTitle("JPackage Example");
    primaryStage.show();
  }
}

Compilation

Here is the command to compile the above code. Note the working directory is the project directory.

javac --module-source-path src --module com.example -d out\classes

I have a JDK which includes JavaFX. If you do not then you need to make sure to put JavaFX on the module-path. For example:

javac --module-path <path-to-fx> --module-source-path src --module com.example -d out\classes

But again, you are likely letting your IDE handle compilation.

Packaging

Here is the command to package the now-compiled application.

jpackage --type app-image --name JPackageExample --module-path out/classes --module com.example/com.example.app.Main --dest out/package

The --type determines the application type. On Windows there's three options: app-image (common to all platforms, I believe), exe, and msi. The first will simply create an exploded directory (containing a exe file on Windows). The latter two will create Windows installers for your application. Note you must be on Windows to create Windows packages (same for MacOS and Linux).

The --module argument tells the tool what the main module and class is (i.e. the entry point of the application). It's format is <main-module>[/<main-class>]. The main class may be omitted if appropriate (e.g. you packaged your code into a JAR file with --main-class specified).

Again, I have a JDK which includes JavaFX. If you do not then make sure to include JavaFX in the --module-path argument, along with your own code. Important: Unlike during compilation, if you have JavaFX separate from the JDK then make sure to place the JavaFX JMOD files on the module-path, not the normal JAR files; you can get the JMOD files from Gluon (likely same place you got the JavaFX SDK). Keep in mind that JavaFX is platform-specific.


The above example is entirely from the command-line. You are likely using an IDE so some of the steps may be different. For instance, you can rely on the IDE to compile your code and, if you want, package it into a JAR file. You might even be able to let the IDE handle invoking jpackage as well but I'm not sure.

Slaw
  • 37,820
  • 8
  • 53
  • 80
  • My JDK and IDE both do not support JavaFX, but this is a really detailed post. Thank you so much! IntelliJ won't let me build a Jar to use for the --module-path argument, and I'm not sure where exactly to put the JMOD files. Also, how are you having a JDK with javafx and using jpackage? I thought jpackage was 14+ and javafx was removed from 9 or below – EveningSt3r Aug 30 '21 at 03:28
  • If you have the JavaFX SDK then you can simply put the JMOD files in the same location. But it doesn't really matter where you put them, so long as you pass the correct path to `--module-path` when executing `jpackage`. As for having a JDK that includes JavaFX, I'm not using the Oracle distribution. There are at least two other distributors that provide JDKs with JavaFX: _Bellsoft Liberica_ and _Azul Zulu_. You have to choose the JDK download that includes JavaFX though. Both of them (and Oracle) are based on OpenJDK so there shouldn't be much difference between them. Check licenses if needed – Slaw Aug 30 '21 at 04:35
  • Note if you have a JDK that includes JavaFX then the JMOD files are included and will be used automatically. By the way, [here's an explanation of why you should use the JMOD files](https://stackoverflow.com/questions/61294243/running-javafx-application-after-jpackage/61294909#61294909) when using `jpackage` (note that `jpackage` uses `jlink` to create the custom run-time image). – Slaw Aug 30 '21 at 04:36
  • The JavaFX JDK would be the "Full Liberica JDK" 64 bit java 16 right? Theoretically with this, the need for the JMOD files is erased, I'm assuming Also, with Java 16 and 11 on my computer there won't be problems I'm assuming. Once I have java 16, can IntelliJ just package it by itself? – EveningSt3r Aug 30 '21 at 05:59
  • Yes, "Full Liberica JDK" should be the one that includes JavaFX. And if you have that JDK it's not that the JMOD files are no longer needed, it's that they're included with the JDK and are implicitly used (just like the JMOD files for the standard Java modules, e.g. `java.base`, `java.sql`, etc.) which means you don't have to explicitly add them to the `--module-path` argument. – Slaw Aug 30 '21 at 19:59
  • I have downloaded the JDK and have set my VM options in intelliJ as "--module-path "C:\Users\User\Desktop\jdk-16.0.2-full\lib". It is telling me Error occurred during initialization of boot layer java.lang.LayerInstantiationException: Package jdk.internal.jrtfs in both module java.base and module jrt.fs. also, how would my argument change if i wanted to use the jdbc driver for sql? I noticed it is in the liberica sdk. I'm not sure how to get the jar running right now though. – EveningSt3r Sep 18 '21 at 00:44
  • Can you try without that `--module-path` argument? The JDK should implicitly already be on the module path. – Slaw Sep 18 '21 at 00:56
  • the project runs without the module path argument, but the jar still does not run on double click. – EveningSt3r Sep 18 '21 at 22:58
  • Does `java -jar ` work? – Slaw Sep 19 '21 at 02:40
  • Unfortunately not. – EveningSt3r Sep 20 '21 at 05:06
  • How would I run the compiled `.class` files directly from the command line? – Tech Expert Wizard Nov 26 '21 at 13:44
0

It has nothing to do with jlink, just with the way you are creating the artifact.

Whenever you are creating a .jar file in IntelliJ, before creating the artifacts, you have to input the files from your java bin file into your artifact.

To do that you have to go to File-Project Structure-Artifacts.

Then click the plus "+", hover over JAR and select From modules with dependencies.

After that select the "Main Class" bar in your popup display and input your main class (probably titled "Main") and click ok.

After that you will see a new box. In that box click the plus inside it then click "File".

Then go to your jre folder in your program files, which will be in the "Java" folder. Go into it then double click "bin". Highlight everything that is a FILE, not a folder, then put it into your artifacts.

After that click "ok" on your artifacts window and it will close.

Now you are set up to click the "Build Artifacts" button!

Click the button and select "Build"

The .jar file will appear in your project folder under "out" and in "artifacts" after clicking the button!

Have a nice day! :)

msnba
  • 1
  • 1