7

I have two JPMS module in two files: modulea.jar and moduleb.jar. Modulea requires javafx.controls module. I need to use these modules in new layer, so I do:

ModuleFinder finder = ModuleFinder.of(modAPath, modBPath);
ModuleLayer parent = ModuleLayer.boot();
Configuration cf = parent.configuration().resolveAndBind(finder, ModuleFinder.of(), new HashSet<>());
ClassLoader scl = ClassLoader.getSystemClassLoader();
ModuleLayer newLayer = parent.defineModulesWithOneLoader(cf, scl);

I thought that JDK modules will be loaded automatically but I get

Exception in thread "main" java.lang.module.FindException: Module javafx.controls not found, required by modulea
    at java.base/java.lang.module.Resolver.findFail(Resolver.java:889)
    at java.base/java.lang.module.Resolver.resolve(Resolver.java:191)
    at java.base/java.lang.module.Resolver.bind(Resolver.java:297)
    at java.base/java.lang.module.Configuration.resolveAndBind(Configuration.java:428)
    at java.base/java.lang.module.Configuration.resolveAndBind(Configuration.java:230)

At the same time when I do: java --list-modules, the output is:

...
javafx.base@9
javafx.controls@9
javafx.deploy@9
javafx.fxml@9
javafx.graphics@9
javafx.media@9
javafx.swing@9
javafx.web@9

How to fix it?

fabian
  • 67,623
  • 12
  • 74
  • 102
Pavel_K
  • 8,216
  • 6
  • 44
  • 127
  • Is there a reason you didn’t simply put `requires javafx.controls;` in your module-info.java? – VGR Sep 21 '17 at 18:00
  • @VGR Sorry, didn't understand you. In modulea module-info I have `requires javafx.controls`. – Pavel_K Sep 21 '17 at 18:02
  • The JDK modules can be accessed already using the `parent` layer. How else are you trying to access them? – Naman Sep 21 '17 at 18:02
  • @nullpointer Thank you for your comment. But then why do I get this exception? – Pavel_K Sep 21 '17 at 18:03
  • 2
    The `javafx.controls` module must not be in the boot layer. You can force it into the boot layer by running with `--add-modules javafx.controls` but it would be interesting to know more about the initial module - is this your own launcher/container module that only requires java.base? If so then you may want to run with `--add-modules ALL-SYSTEM` to ensure that all system modules are in the boot layer as it's unknown what applications it launches might require. – Alan Bateman Sep 21 '17 at 18:14
  • To add onto the above, comparing it with the output of `java --list-modules` should only hold true to my understanding when the JVM has at least the boot layer which contains the named `java.base` module – Naman Sep 21 '17 at 18:17
  • 1
    @Alan Bateman Thank you for your comment. Ok. `javafx.controls` must not be in boot layer. However, I need it only for this layer, but not for any other layers. How can I add it dynamically to this layer? Answering to your question - in boot layer I have a launcher for other layers which needs `java.base`, `java.rmi` and some others but not any `javafx.*`. – Pavel_K Sep 21 '17 at 18:53
  • Module layers are immutable, there is no support for adding modules to a module layer once it is created. So in your scenario, where the main application is itself a launcher, you need to ensure that all the necessary platform modules are in the boot layer so that they can be found when resolving modules for the child layers. In summary, containers (like your launcher) really need to be run with `--add-module ALL-SYSTEM`. – Alan Bateman Sep 22 '17 at 16:22
  • @Alan Bateman Thank you very much for your comment and such important information. It seems that every module system (JPMS and OSGi) has some constraints that can not be explained (by me at least). After reading your comment the following came to my mind. In osgi, only `java.*` packages are exported to bundles. If you want for example `javafx.*` packages you must add them manually, but, you can add them only when you start framework. So, later you can not install bundle that needs some package which you didn't export when started the framework. I think I could express the idea. – Pavel_K Sep 22 '17 at 18:08
  • @AlanBateman Is there an alternative to `--add-module ALL-SYSTEM`? I know i can manually list all system modules in the launcher/container module declaration, but is there an automatic way? – Mordechai Feb 28 '18 at 20:27
  • I suspect you'll find `--show-module-resolution` useful as it helps to understand the modules in the boot layer. There is no support for dynamically augmenting the set of modules in the boot layer once it is created. You can create child layers, as per the original question. I can't say if the javafx.* can be loaded into child layers, if they can then specify ModuleFinder.ofSystem() to resolveAndBind. – Alan Bateman Feb 28 '18 at 21:08

1 Answers1

1

From @AlanBateman's comment:

The javafx.controls module is not loaded by default. You can force it into the boot layer by running with --add-modules javafx.controls.

NOTE: Starting with Java 11 JavaFX is a separate project.

Pavel_K
  • 8,216
  • 6
  • 44
  • 127