Closed magicprinc closed 6 months ago
Example application
Branch main
shows the bug.
Branch fix
shows the fix.
https://github.com/magicprinc/SmallRyeConfig-SpringBoot
@radcortez @dmlloyd Sorry to bother you 🙏 But the situation is critical. SmallRye Config doesn't work in a typical Spring Boot application (bundled as spring boot jar). Could it be fixed in the near future?
git clone https://github.com/magicprinc/SmallRyeConfig-SpringBoot.git
cd SmallRyeConfig-SpringBoot
./gradlew runBootJar
⇒
> Task :runBootJar FAILED
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:118)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:65)
Caused by: java.lang.ExceptionInInitializerError
at fink.demo.smallryeconfigspringboot.ExampleApplication.main(ExampleApplication.java:13)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
... 5 more
Caused by: java.io.UncheckedIOException: Failed to read C:\TEMP\test\SmallRyeConfig-SpringBoot\build\libs\SmallRyeConfig-SpringBoot-1.0.jar!\BOOT-INF\classes
at io.smallrye.common.classloader.ClassPathUtils.processAsPath(ClassPathUtils.java:146)
at io.smallrye.common.classloader.ClassPathUtils.consumeAsPath(ClassPathUtils.java:102)
at io.smallrye.common.classloader.ClassPathUtils.consumeAsPaths(ClassPathUtils.java:86)
at io.smallrye.config.AbstractLocationConfigSourceLoader.tryClassPath(AbstractLocationConfigSourceLoader.java:141)
at io.smallrye.config.AbstractLocationConfigSourceLoader.loadConfigSources(AbstractLocationConfigSourceLoader.java:104)
at io.smallrye.config.AbstractLocationConfigSourceLoader.loadConfigSources(AbstractLocationConfigSourceLoader.java:87)
at io.smallrye.config.PropertiesConfigSourceProvider.<init>(PropertiesConfigSourceProvider.java:37)
at fink.config.spring.SmallRyeConfigAutoConf.<clinit>(SmallRyeConfigAutoConf.java:75)
... 7 more
Caused by: java.nio.file.NoSuchFileException: C:\TEMP\test\SmallRyeConfig-SpringBoot\build\libs\SmallRyeConfig-SpringBoot-1.0.jar!\BOOT-INF\classes
at jdk.zipfs/jdk.nio.zipfs.ZipFileSystem.<init>(ZipFileSystem.java:166)
at jdk.zipfs/jdk.nio.zipfs.ZipFileSystemProvider.getZipFileSystem(ZipFileSystemProvider.java:125)
at jdk.zipfs/jdk.nio.zipfs.ZipFileSystemProvider.newFileSystem(ZipFileSystemProvider.java:120)
at java.base/java.nio.file.FileSystems.newFileSystem(FileSystems.java:528)
at java.base/java.nio.file.FileSystems.newFileSystem(FileSystems.java:400)
at io.smallrye.common.classloader.ClassPathUtils.processAsPath(ClassPathUtils.java:139)
... 14 more
FAILURE: Build failed with an exception.
(Not the best fix at all, but it helps)
git checkout fix
./gradlew runBootJar
⇒ works! App starts.
curl localhost:8080/key/java.version
The bug reports do not have a lot to make it clear exactly what is going on in your case. However based on what I know of Sprint Boot (which isn't much) and the stack traces, I wonder if the problem relates to multiple levels of JAR nesting?
I did find some minor problems in the processAsPath
code (including the indexOf
problem you found) but it's definitely unclear as to whether it could have caused your issue. I will be putting up a PR in a few minutes and you can test it out.
The nesting is not our problem: Spring Boot ClassLoader (class org.springframework.boot.loader.LaunchedURLClassLoader) handles it.
If you run spring boot jar
java -jar application.jar
You actually run spring boot loader classes, which install special ClassLoader, which can handle jar in jar and runs your application class.
Sure, the class loader aspect is fine, but the code that is failing in your stack trace also would need knowledge of how to handle this case, and currently it does not. Let me know if PR #293 fixes the issue for you.
Spring BootJar has complex layout and special spring ClassLoader to make it work SmallRye Config doesn't work in Spring Application packed as spring bootJar.
I have found, the problem is in your class
io.smallrye.common.classloader.ClassPathUtils
Full explanation and fix: https://github.com/smallrye/smallrye-config/issues/1101
PS: more advanced research and fix are welcome 🙏