Module javafx.controls not found in Java 9
Asked Answered
H

1

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?

Hymenium answered 21/9, 2017 at 17:22 Comment(11)
Is there a reason you didn’t simply put requires javafx.controls; in your module-info.java?Amidships
@Amidships Sorry, didn't understand you. In modulea module-info I have requires javafx.controls.Hymenium
The JDK modules can be accessed already using the parent layer. How else are you trying to access them?Exit
@nullpointer Thank you for your comment. But then why do I get this exception?Hymenium
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.Sanction
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 moduleExit
@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.*.Hymenium
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.Sanction
@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.Hymenium
@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?Feodor
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.Sanction
H
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.

Hymenium answered 19/11, 2018 at 13:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.