3

I've attempted to use JavaFX by following instructions found at:

https://openjfx.io/openjfx-docs/ under "JavaFX and IntelliJ" -> "Non-modular with Maven"

After completing steps 1 & 2 (Installation & Verification) I attempted to run a very simple program from IntelliJ rather than through the Maven plugin.

TraderWindow.java

public class TraderWindow extends Application {

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

    @Override
    @SneakyThrows
    public void start(Stage primaryStage) {
        Scene scene = FXMLLoader.load(getClass().getResource("/TraderWindow.fxml"));
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

TraderWindow.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1">
  <columnConstraints>
    <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
    <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
  </columnConstraints>
  <rowConstraints>
    <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
    <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
    <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
  </rowConstraints>
   <children>
      <Button mnemonicParsing="false" text="Button" />
   </children>
</GridPane>

However when I attempted to run it I got:

java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.IllegalAccessError: class com.sun.javafx.fxml.FXMLLoaderHelper (in unnamed module @0x6adc19e3) cannot access class com.sun.javafx.util.Utils (in module javafx.graphics) because module javafx.graphics does not export com.sun.javafx.util to unnamed module @0x6adc19e3
    at com.sun.javafx.fxml.FXMLLoaderHelper.<clinit>(FXMLLoaderHelper.java:38)
    at javafx.fxml.FXMLLoader.<clinit>(FXMLLoader.java:2138)
    at com.trader.gui.TraderWindow.start(TraderWindow.java:19)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:474)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:447)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:446)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    ... 1 more
Exception running application com.trader.gui.TraderWindow

Process finished with exit code 1

The relevant part:

Caused by: java.lang.IllegalAccessError: class com.sun.javafx.fxml.FXMLLoaderHelper (in unnamed module @0x6adc19e3) cannot access class com.sun.javafx.util.Utils (in module javafx.graphics) because module javafx.graphics does not export com.sun.javafx.util to unnamed module @0x6adc19e3

Which, I guess, is understandable since JafaFx is modularized and my application is not. In order to circumvent the problem I added this to VM path:

--add-opens javafx.graphics/com.sun.javafx.util=ALL-UNNAMED

I tried again, this time getting:

Caused by: java.lang.IllegalAccessError: class javafx.fxml.JavaFXBuilderFactory (in unnamed module @0x4e342850) cannot access class com.sun.javafx.reflect.ConstructorUtil (in module javafx.base) because module javafx.base does not export com.sun.javafx.reflect to unnamed module @0x4e342850

And so I added another --add-opens directive... And then I repeated these steps 3 more times before giving up.

Is there another way of making JavaFX work with Java 11+ rather than modularizing the application or painstakingly adding --add-opens directives for each and every illegal access operation?

Noozen
  • 379
  • 3
  • 13
  • 3
    You don't have to modularize your application, but you should put the javafx jars on the module path (putting them on the class path is not supported). From the access error you are getting, it looks like the jar containing `com.sun.javafx.fxml.FXMLLoaderHelper` is on the class path instead (in the unnamed module). – Jorn Vernee May 24 '21 at 01:47
  • @JornVernee Shouldn't IntelliJ put Maven modules on module-path by default instead of class-path? Assuming that that is the issue, how can I force it to use module path instead? – Noozen May 24 '21 at 01:58
  • 3
    Ok, that reminds me: AFAIK IntelliJ is currently (very) limited in that it is not possible to put specific dependencies on the module path or class path. It either puts all dependencies on the class path, or all dependencies on the module path. What's worse is, this decision is based on whether the application itself is modular, which is mostly unrelated to the dependencies. I've been able to make this work before by manually adding the jars to the module path through VM options in the run configuration in IntellIJ, but this is very tedious. – Jorn Vernee May 24 '21 at 02:04
  • 2
    Your problem is at least similar to the one described here: [Module error when running JavaFx media application](https://stackoverflow.com/questions/53237287/module-error-when-running-javafx-media-application). Except instead of needing to make sure `javafx.media` is resolved as a module you need to do the same for `javafx.fxml`. Though I'm not sure what specific steps you need to take when using Maven. Anyways, like @JornVernee said, _your own code_ does not need to be modular but JavaFX itself should be resolved as named modules. – Slaw May 24 '21 at 04:31
  • 1
    You need to have a main class that is not your Application. [This](http://mail.openjdk.java.net/pipermail/openjfx-dev/2018-June/021977.html) discusses the issue, but it seems to be left open because it is not a supported version. – matt May 24 '21 at 08:13

1 Answers1

6

If you completely want to get rid of all this module system trouble you could add a line like this to your main class

class MyAppLauncher {public static void main(String[] args) {MyApp.main(args);}}

and then launch the app via this launcher. If you do that you can put everything on the classpath and remove all -add-opens. (actually you have to.) The only drawback is that since JavaFX 16 you will get a nasty warning message saying Unsupported JavaFX configuration but you can just ignore that.

mipa
  • 10,369
  • 2
  • 16
  • 35
  • This resolved my issue. But why does moving the location of main class affect behaviour of class/module path? – Noozen May 24 '21 at 12:56
  • 1
    That's a long and sad story. https://mail.openjdk.java.net/pipermail/openjfx-dev/2020-April/025903.html – mipa May 24 '21 at 15:56
  • 1
    I get the feeling you're really not a fan of the _Java Platform Module System_ :p – Slaw May 24 '21 at 21:07
  • Maybe because I am not a masochist who constantly likes to have his fingers burned :-) – mipa May 25 '21 at 07:44