A frequent source of frustration for developers adopting the Java Platform Module System (JPMS) is integrating it with JavaFX. Many assume that adding module-info.java
is enough, only to face errors like:
java.lang.module.FindException: Module javafx.controls not found
- “package is not visible” or reflective access issues
The root cause is that JavaFX is no longer bundled with the JDK (since Java 11), and must be explicitly added as modular dependencies. Without correct configuration, applications fail at runtime.
In real-world applications—desktop tools, enterprise dashboards, and rich-client UIs—modularizing JavaFX projects ensures smaller runtimes, clearer architecture, and easier deployment.
Think of JavaFX integration as plugging in a lighting system in a new office. The wiring (modules) must be correctly connected, or the lights won’t turn on—even if the bulbs (JavaFX classes) are present.
Setting Up JavaFX with JPMS
Example module-info.java
module com.example.myapp {
requires javafx.controls;
requires javafx.fxml;
exports com.example.myapp.ui;
opens com.example.myapp.ui to javafx.fxml;
}
requires javafx.controls
→ for UI componentsrequires javafx.fxml
→ for FXML supportopens com.example.myapp.ui
→ allows reflection for FXML loaders
Running JavaFX Modular Applications
Maven Example
Add dependencies:
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>20</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>20</version>
</dependency>
Configure the plugin:
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<configuration>
<mainClass>com.example.myapp/com.example.myapp.MainApp</mainClass>
</configuration>
</plugin>
Gradle Example
plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.13'
}
javafx {
version = "20"
modules = [ 'javafx.controls', 'javafx.fxml' ]
}
application {
mainModule = 'com.example.myapp'
mainClass = 'com.example.myapp.MainApp'
}
Best Practices & Pitfalls
✅ Best Practices
- Always use targeted
opens
for FXML packages - Modularize UI and business logic separately
- Use
jlink
to create smaller runtimes for distribution - Test modular builds locally before CI/CD integration
❌ Pitfalls
- Forgetting to add JavaFX modules to the module path
- Using
open module ...
(weakens encapsulation) - Mixing UI, services, and persistence in the same module
- Relying solely on classpath builds when targeting JPMS
Example: Minimal JavaFX App with JPMS
module-info.java
module com.example.hellofx {
requires javafx.controls;
requires javafx.fxml;
exports com.example.hellofx;
opens com.example.hellofx to javafx.fxml;
}
MainApp.java
package com.example.hellofx;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
public class MainApp extends Application {
@Override
public void start(Stage stage) {
Scene scene = new Scene(new Label("Hello, Modular JavaFX!"), 400, 200);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
What's New in Java Versions?
- Java 5–8 → N/A (no JPMS, JavaFX bundled in JDK 8)
- Java 9 → JPMS introduced; JavaFX modular but still bundled
- Java 11 → JavaFX removed from JDK, distributed via OpenJFX
- Java 17 → Stable long-term support for modular JavaFX apps
- Java 21 → No significant updates across Java versions for this feature
Real-World Analogy
Integrating JavaFX with JPMS is like building a stage play. The actors (controllers) need spotlights (FXML reflection) directed at them. Without opening the right curtains (opens
), the audience (JavaFX runtime) cannot see them.
Summary & Key Takeaways
- JavaFX requires explicit module declarations since Java 11
- Use requires javafx.controls, javafx.fxml in
module-info.java
- Use
opens
for FXML-related packages - Build and run with Maven/Gradle plugins for OpenJFX
- Avoid shortcuts like
open module ...
; keep encapsulation intact
FAQ: JavaFX and JPMS
1. Why do I get Module javafx.controls not found
?
Because JavaFX isn’t bundled with the JDK since Java 11—you must add it separately.
2. Why do I get FXML reflection errors?
Because the controller package isn’t opens
to javafx.fxml
.
3. What does requires transitive
mean in JavaFX apps?
It exposes dependencies downstream, but rarely needed in JavaFX projects.
4. How do open
and opens
differ for FXML?open
exposes the entire module; opens
limits reflection to specific packages.
5. Are automatic modules suitable for JavaFX apps?
They can help in migration but aren’t recommended for production.
6. How does JPMS improve JavaFX security?
It ensures only declared modules/packages are accessible, reducing attack surface.
7. Should I use jlink or jmod for JavaFX apps?
Use jlink
for optimized runtimes; jmod
for packaging artifacts.
8. Can I migrate a JavaFX 8 app to JPMS?
Yes, modularize step by step—first run with automatic modules, then refine.
9. How do I handle third-party non-modular libraries in JavaFX apps?
Use them on the classpath or wrap them as automatic modules.
10. Is JavaFX fully JPMS-compatible?
Yes, OpenJFX provides modular JARs ready for JPMS.