I am trying to build installer package for a Spring Boot JavaFX application (Mac and Windows) by following these steps below. However, during the execution of ./gradlew jpackage
command, I get several errors e.g. “module not found: javafx.base requires javafx.base;”, and when I debug I also get “Unsupported class file major version 66”.
Tried several workarounds mentioned on SO, etc. to fix, it does not make and still the same problems. I am using Java 21 and not sure if there are some incompatibility with this. Here is the config and steps I followed:
build.gradle:
plugins {
id 'org.springframework.boot' version '3.3.2'
id 'io.spring.dependency-management' version '1.1.6'
id 'java'
id 'application'
id 'jacoco'
id 'org.openjfx.javafxplugin' version '0.0.13'
id 'org.beryx.jlink' version '2.26.0'
}
group = 'com.company'
version = '1.0.0'
sourceCompatibility = '21'
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
// Spring Dependencies
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-batch'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
// External Dependencies
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.2'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.17.2'
implementation 'io.netty:netty-resolver-dns-native-macos:4.1.72.Final:osx-aarch_64'
implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.5'
runtimeOnly 'com.h2database:h2:2.3.230'
// Test Dependencies
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.batch:spring-batch-test'
}
tasks.named('test') {
useJUnitPlatform()
finalizedBy jacocoTestReport
}
javafx {
version = "21"
modules = [ 'javafx.controls', 'javafx.fxml' ] // 'javafx.base' (also tried with this)
}
application {
mainModule = 'com.company.accountmanagement' // Replace with your main module name
mainClass = 'com.company.AccountManagementApplication.main' // Replace with your main class
}
jlink {
imageZip = project.file("${buildDir}/distributions/app-${javafx.platform.classifier}.zip")
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'app'
}
jpackage {
jpackageHome = '/Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home'
installerType = 'dmg'
imageOptions = []
installerOptions = [
'--resource-dir', "${projectDir}/src/main/resources",
'--vendor', 'Company Name'
]
installerName = 'AccountManagement'
appVersion = '1.0.0'
if (org.gradle.internal.os.OperatingSystem.current().windows) {
installerOptions += ['--win-dir-chooser', '--win-menu', '--win-shortcut']
imageOptions += ["--icon", "${projectDir}/src/main/resources/icon.ico"]
}
if (org.gradle.internal.os.OperatingSystem.current().macOsX) {
installerOptions += ['--mac-package-name', 'AccountManagement']
imageOptions += ["--icon", "${projectDir}/src/main/resources/icon.icns"]
}
}
}
tasks.jlink {
group = 'distribution'
}
tasks.jpackage {
group = 'distribution'
}
- Build the application:
./gradlew build
- Create the runtime image and installer package:
./gradlew jpackage
It may also be related to module-info.java
, but it seems fine as far as I checked:
module com.company.accountmanagement {
requires javafx.base;
requires javafx.controls;
requires javafx.fxml;
requires javafx.graphics;
requires spring.boot;
requires spring.context;
requires jasypt.spring.boot;
requires spring.boot.autoconfigure;
opens com.company.accountmanagement to javafx.fxml;
exports com.company.accountmanagement;
}
13
As per my guess, you might be running this on a different JDK (lower) jdk
Ensure JDK Compatibility: Verify that both your build and runtime environments are using the same JDK version. For JDK 21, ensure that the sourceCompatibility and targetCompatibility in your build.gradle are set to 21.
gradle
sourceCompatibility = '21'
targetCompatibility = '21'
1