3

I am new to Java and currently reading through a text and learning. I have installed the JDK in my /opt directory (working on Kubuntu). I have also installed openjfx in /opt. Since I work out the terminal, whenever I want to compile or run something involving a module from JavaFX, I use

javac --module-path $PATH_TO_FX --add-modules ALL-MODULE-PATH className.java

However, when I try the same thing with jshell it will not work. That is,

jshell --module-path $PATH_TO_FX --add-modules ALL-MODULE-PATH

What I am trying to find out is, is there any way I can install the JavaFX SDK so that it is merged with the Java SDK directory and saves me having to use the flags whenever I want to compile/run a program that requires any modules from JavaFX?

If not, can anyone tell me why the jshell comand above will not work as I expect it to?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Zeta-Squared
  • 257
  • 2
  • 7
  • The only way to do that is to use a JDK that already bundles JavaFX. I think Azul and BellSoft Liberica do so. You can't just put JavaFX into a JDK yourself (though I'm not sure trying to use JavaFX from jshell makes much sense TBH). – Mark Rotteveel May 02 '23 at 14:01
  • https://openjfx.io/openjfx-docs/ – SedJ601 May 02 '23 at 14:33
  • 1
    @MarkRotteveel "You can't just put JavaFX into a JDK yourself"; you essentially can do this with `jlink`. (It doesn't put JavaFX into an existing JDK, but can create a new one.) – James_D May 02 '23 at 16:52
  • @James_D You're right, I entirely forgot about that scenario. – Mark Rotteveel May 03 '23 at 06:57

1 Answers1

5

For this part of your question:

What I am trying to find out is, is there any way I can install the JavaFX SDK so that it is merged with the Java SDK directory and saves me having to use the flags whenever I want to compile/run a program that requires any modules from JavaFX?

you can use jlink, which generates a custom runtime image. In order to include services in the generated runtime image, use the --bind-services option. For reasons I don't quite understand, to include jshell in this, you must explicitly add the jdk.jshell module (simply using --add-modules ALL-MODULE-PATH will not work). So you need something like:

jlink --module-path $PATH_TO_FX --add-modules javafx.controls,javafx.fxml,jdk.jshell --bind-services --output JavaWithFX

to create a JDK that includes the JavaFX modules. You might need to include other JavaFX modules (e.g. javafx.web if you are using WebView, javafx.media if you are using MediaPlayer, etc.), or omit javafx.fxml if you are not using FXML.

Now you can just use that JDK to compile and run:

export JAVA_HOME=JavaWithFX
javac ClassName.java
java ClassName

(or possibly export PATH=JavaWithFX/bin:$PATH instead of the export JAVA_HOME, depending on how Java works on your system).

Running

JavaWithFX/bin/jshell

will give you a jshell that includes the JavaFX modules:

% JavaWithFX/bin/jshell
|  Welcome to JShell -- Version 20
|  For an introduction type: /help intro

jshell> import javafx.beans.property.SimpleIntegerProperty

jshell> var x = new SimpleIntegerProperty(0)
x ==> IntegerProperty [value: 0]

jshell> x.addListener((obs, oldValue, newValue) -> System.out.printf("x changed from %d to %d%n", oldValue, newValue))

jshell> x.set(42)
x changed from 0 to 42

jshell> 
James_D
  • 201,275
  • 16
  • 291
  • 322
  • This is a great answer. Thank you. I have also seen that this is now in the documentation. Further to this though, is there any downsides in now making `JavaWithFX/bin/*` our standard Java compiler and VM? Is this perhaps not a best practice? If so, what is generally recommended if you want to work with certain modules for a project -- create a custom runtime image and place it in the project root directory? Thanks again. – Zeta-Squared May 02 '23 at 22:21
  • @Zeta-Squared The real use case for `jlink` is to build a Java runtime with just the modules needed for the application. That way, when you create a native package for application deployment, you can minimize its size. There's nothing to stop you creating a (probably large) runtime that you can use during development easily, but ultimately at deployment time you'll want to do something else. – James_D May 03 '23 at 13:14
  • @Zeta-Squared Generally I would strongly recommend using an IDE to manage compilation and running the application while you are developing it, and using a standard JRE (letting the IDE transparently manage the options to the compiler and execution for you). At some point, even if you use a runtime as created here, building from the terminal will become too cumbersome. (A JavaFX application will typically need a lot of resources in addition to the compiled code: FXML files, CSS files, images, etc. You would need to copy those manually from your source to build folders.) – James_D May 03 '23 at 14:08