I'm building a Spring Boot 3.4.5 application with a JavaFX GUI. What I'm essentially trying to do is start the app with GUI which has the buttons to start/restart/stop the Spring Boot server. The app runs fine in development mode inside my IDE, but when I build a fat jar and try to run it, I get the following error, Below is the custom log that i print inside my JavaFX based GUI app:
[22:48:10] ▶ Starting server...
[22:48:10] ❌ Failed to start server: Unable to instantiate factory class [org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer] for factory type [org.springframework.context.ApplicationContextInitializer]
[22:48:10] 📋 java.lang.IllegalArgumentException: Unable to instantiate factory class [org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer] for factory type [org.springframework.context.ApplicationContextInitializer]
[22:48:10] 📋 at org.springframework.core.io.support.SpringFactoriesLoader$FailureHandler.lambda$throwing$0(SpringFactoriesLoader.java:641)
[22:48:10] 📋 at org.springframework.core.io.support.SpringFactoriesLoader$FailureHandler.lambda$handleMessage$3(SpringFactoriesLoader.java:665)
[22:48:10] 📋 at org.springframework.core.io.support.SpringFactoriesLoader.instantiateFactory(SpringFactoriesLoader.java:227)
[22:48:10] 📋 at org.springframework.core.io.support.SpringFactoriesLoader.load(SpringFactoriesLoader.java:202)
[22:48:10] 📋 at org.springframework.core.io.support.SpringFactoriesLoader.load(SpringFactoriesLoader.java:158)
[22:48:10] 📋 at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:466)
[22:48:10] 📋 at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:462)
[22:48:10] 📋 at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:278)
[22:48:10] 📋 at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:257)
[22:48:10] 📋 at org.springframework.boot.SpringApplication.run(SpringApplication.java:1362)
[22:48:10] 📋 at org.springframework.boot.SpringApplication.run(SpringApplication.java:1351)
[22:48:10] 📋 at com.novastream.config.ServerControlGUI.lambda$startServer$16(ServerControlGUI.java:403)
[22:48:10] 📋 at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1848)
[22:48:10] 📋 at java.base/java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1840)
[22:48:10] 📋 at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:507)
[22:48:10] 📋 at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1458)
[22:48:10] 📋 at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:2034)
[22:48:10] 📋 at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:189)
[22:48:10] 📋 Caused by: java.lang.ClassNotFoundException: org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer
[22:48:10] 📋 at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
[22:48:10] 📋 at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
[22:48:10] 📋 at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:528)
[22:48:10] 📋 at java.base/java.lang.Class.forName0(Native Method)
[22:48:10] 📋 at java.base/java.lang.Class.forName(Class.java:578)
[22:48:10] 📋 at java.base/java.lang.Class.forName(Class.java:557)
[22:48:10] 📋 at org.springframework.util.ClassUtils.forName(ClassUtils.java:321)
[22:48:10] 📋 at org.springframework.core.io.support.SpringFactoriesLoader.instantiateFactory(SpringFactoriesLoader.java:220)
[22:48:10] 📋 ... 15 more
Above image shows what my GUI looks like and is 100% working in dev mode.
Above in the 2nd image is the same GUI but when the app is run using built JAR (this error pops up when the server start button is pressed).
My main entry point looks like this:
package com.novastream;
import com.novastream.config.MediaConfig;
import com.novastream.config.ServerControlGUI;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.scheduling.annotation.EnableAsync;
@EnableAsync
@SpringBootApplication
@EnableConfigurationProperties(MediaConfig.class)
public class NovastreamBackendApplication {
public static void main(String[] args) {
System.setProperty("java.awt.headless", "false");
ServerControlGUI.launch(ServerControlGUI.class);
}
}
My pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.5</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.novastream</groupId>
<artifactId>novastream-backend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>novastream-backend</name>
<description>NovaStream Backend</description>
<url />
<licenses>
<license />
</licenses>
<developers>
<developer />
</developers>
<scm>
<connection />
<developerConnection />
<tag />
<url />
</scm>
<properties>
<java.version>23</java.version>
<javafx.version>21</javafx.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>3.2.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.4.5</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
A short version of my ServerControlGUI.java (My class for JavaFX based GUI):
@Component
public class ServerControlGUI extends Application {
@Override
public void start(Stage primaryStage) {
primaryStage.initStyle(StageStyle.TRANSPARENT);
DropShadow shadow = new DropShadow(20, Color.BLACK);
shadow.setOffsetX(0);
shadow.setOffsetY(10);
VBox root = createMainLayout(primaryStage);
root.setEffect(shadow);
root.getStyleClass().add("main-container");
Rectangle clip = new Rectangle(800, 600);
clip.setArcWidth(16);
clip.setArcHeight(16);
root.setClip(clip);
Scene scene = new Scene(root, 800, 600);
scene.setFill(Color.TRANSPARENT);
scene
.getStylesheets()
.add(getClass().getResource("/static/gui.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setTitle("NovaStream");
primaryStage.show();
animateStartup(primaryStage);
primaryStage.setOnCloseRequest(e -> {
stopServer();
Platform.exit();
System.exit(0);
});
setupSystemStreamRedirection();
}
private VBox createControlPanel() {
VBox panel = new VBox();
panel.getStyleClass().add("control-panel");
Label title = new Label("Server Controls");
title.getStyleClass().add("control-title");
HBox controls = new HBox();
controls.getStyleClass().add("controls-container");
startRestartBtn =
createActionButton("▶ Start Server", "start-button", this::startServer);
stopBtn =
createActionButton("⏹ Stop Server", "stop-button", this::stopServer);
clearLogsBtn =
createActionButton("🗑 Clear Logs", "clear-button", this::clearLogs);
stopBtn.setDisable(true);
clearLogsBtn.setDisable(true);
controls.getChildren().addAll(startRestartBtn, stopBtn, clearLogsBtn);
panel.getChildren().addAll(title, controls);
return panel;
}
private void startServer() {
if (loadingIndicator.isVisible() || serverRunning) return;
Platform.runLater(() -> {
loadingIndicator.setVisible(true);
updateStatusLabel("Starting...", "status-starting");
startRestartBtn.setDisable(true);
stopBtn.setDisable(true);
});
CompletableFuture.runAsync(() -> {
try {
appendLog("▶ Starting server...");
springContext =
SpringApplication.run(NovastreamBackendApplication.class);
serverRunning = true;
startTime = LocalDateTime.now();
Platform.runLater(() -> {
loadingIndicator.setVisible(false);
updateStatusLabel("Running", "status-running");
startRestartBtn.setDisable(false);
stopBtn.setDisable(false);
updateStartRestartButton();
startUptimeTimer();
});
appendLog("✅ Server started successfully");
appendLog("🌐 Server running on http://localhost:8080");
} catch (Exception e) {
Platform.runLater(() -> {
loadingIndicator.setVisible(false);
updateStatusLabel("Failed", "status-failed");
startRestartBtn.setDisable(false);
});
appendLog("❌ Failed to start server: " + e.getMessage());
e.printStackTrace();
}
});
}
}
The buttons toggle the server status.
So I basically need help creating the JAR, resolving this issue, as I'm trying to make an exe using that JAR using Launch4J later.

