I am using IntelliJ on a Windows machine. I am able to follow various instructions found on the web to create a HelloWorld JavaFX application. I am building and running using Gradle. I am able to run the application within IntelliJ without any issue. I am using the jpackage plugin to package the app into an exe. This is also successful as I'm able to then click on the generated .exe file and the application launches as expected.
However, my application ultimately will use HSQLDB. I am having trouble figuring out how to include this into a modular application.
In build.gradle I have included the dependency:
implementation("org.hsqldb:hsqldb:2.6.1")
I have then added it to my module-info.java file:
module my.openjfx.hellofx {
requires javafx.controls;
requires javafx.fxml;
requires org.hsqldb;
opens my.openjfx.hellofx to javafx.fxml;
exports my.openjfx.hellofx;
}
When doing this I can still run the application successfully within IntelliJ using the gradle 'run' command. However, after I package it up using jpackage, the exe fails with the following error:
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.InternalError: Module my.openjfx.hellofx not in boot Layer
at java.base/sun.launcher.LauncherHelper.loadModuleMainClass(Unknown Source)
at java.base/sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Failed to launch JVM
Child process exited with code 1
I know for certain it is the line requires org.hsqldb; that is causing the problem because if I comment out that line, I am able to run the packaged program.
Does anyone have experience packaging HSQLDB into a JavaFX modular program packaged using jpackage?
Additional information: I'm using the badass plugin to package the application. Here are all the files: build.gradle:
plugins {
id 'java'
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.10'
id 'org.beryx.jlink' version '2.24.1'
}
group 'my.openjfx'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
ext {
junitVersion = '5.8.2'
}
sourceCompatibility = '17'
targetCompatibility = '17'
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
application {
mainModule = 'my.openjfx.hellofx'
mainClass = 'my.openjfx.hellofx.HelloApplication'
}
javafx {
version = '17.0.1'
modules = ['javafx.controls', 'javafx.fxml']
}
dependencies {
// https://mvnrepository.com/artifact/org.hsqldb/hsqldb
implementation("org.hsqldb:hsqldb:2.6.1")
testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
}
test {
useJUnitPlatform()
}
jlink {
imageZip = project.file("${buildDir}/distributions/app-${javafx.platform.classifier}.zip")
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'HelloFX'
}
jpackage {
appVersion = '0.0.7'
if (org.gradle.internal.os.OperatingSystem.current().windows) {
installerOptions += ['--win-per-user-install', '--win-dir-chooser', '--win-menu', '--win-shortcut']
imageOptions += ['--win-console']
}
}
}
jlinkZip {
group = 'distribution'
}
module-info.java
module my.openjfx.hellofx {
requires javafx.controls;
requires javafx.fxml;
requires org.hsqldb;
opens my.openjfx.hellofx to javafx.fxml;
exports my.openjfx.hellofx;
}
HelloApplication.java
package my.openjfx.hellofx;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class HelloApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 320, 240);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
HelloController.java
package my.openjfx.hellofx;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class HelloController {
@FXML
private Label welcomeText;
@FXML
protected void onHelloButtonClick() {
welcomeText.setText("Welcome to JavaFX Application!");
}
}
fxml file:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Button?>
<VBox alignment="CENTER" spacing="20.0" xmlns:fx="http://javafx.com/fxml"
fx:controller="my.openjfx.hellofx.HelloController">
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/>
</padding>
<Label fx:id="welcomeText"/>
<Button text="Hello!" onAction="#onHelloButtonClick"/>
</VBox>
