1 year ago
#318250

Pavel Taruts
Running a spring-boot-gradle-plugin fat jar with named application modules at runtime?
I've got a simplest modular sample application made with Gradle and Spring Boot, and I'm having trouble to launch it with the modules being full-fledged named modules at runtime.
My questions are the following
- Can spring-boot-gradle-plugin build fat jars that you can run with full-fledged named modules at runtime?
- If it can, then how do you make it build the jar, and how do you run it?
- If it cannot, then what do I do to have modules at runtime in a Spring Boot app?
The Gradle version is 7.2
The source
(You can get it here as well: https://github.com/ptrts/modules-bootRun-bug)
settings.gradle
rootProject.name = 'app'
build.gradle
plugins {
id 'org.springframework.boot' version '2.6.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'application'
}
group = 'we'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
}
application {
mainModule = 'app'
mainClass = 'app.Main'
}
src/main/java/module-info.java
module app {
requires spring.boot;
requires spring.boot.autoconfigure;
requires java.annotation;
exports app;
}
src/main/java/app/Main
package app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Main {
public static void main(String[] args) {
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// Output the module name
System.out.println("Module name = " + Main.class.getModule().getName());
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
SpringApplication.run(Main.class, args);
}
}
As you can see the app outputs to stdout the module name of the Main class when launched
The resulting fat jar layout
org/springframework/boot/loader Spring Boot bootstrapping stuff META-INF/MAINIFEST.MF ... Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: app.Main ... BOOT-INF lib dependency libs classes app/Main.class **the package is deep in the JAR** module-info.class **the module descriptor is in the JAR root**
How I tried to launch the application
I tried three different ways of launching the app
- ./gradlew bootRun -i (-i is for INFO logging level)
- java -jar build/libs/app.jar
- java --module-path build/libs/app.jar --module app/app.Main
Launching with ./gradlew bootRun -i
The app prints out Module name = null
In the gradle logs we can see the command line used to launch the JVM, which also tells us that everything is in the class path Here it is with some extra line brakes which I added for readability
C:\Program Files\Java\jdk-17.0.1\bin\java.exe ... -cp C:\data\projects\modules-bootRun-bug\build\classes\java\main; C:\data\projects\modules-bootRun-bug\build\resources\main; C:\Users\pavel\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-autoconfigure\2.6.4\36e75a2781fc604ac042945eed8be2fe049731df\spring-boot-autoconfigure-2.6.4.jar; ... app.Main
Launching with java -jar build/libs/app.jar
The app prints out Module name = null
Launching with java --module-path build/libs/app.jar --module app/app.Main
Error occurred during initialization of boot layer java.lang.module.FindException: Error reading module: app.jar Caused by: java.lang.module.InvalidModuleDescriptorException: Package app not found in module
This is of course expectable, since module-info.class is in the jar root and it's package is somewhere deeper in the jar
java
spring
spring-boot
gradle
java-platform-module-system
0 Answers
Your Answer