micronaut-spring-boot:5.4.0 fails with io.micronaut.context.exceptions.NoSuchBeanException: No bean of type [io.micronaut.context.event.ApplicationEventPublisher<io.micronaut.context.event.StartupEvent>] when running a jar file
donbeave opened this issue · 5 comments
Expected Behavior
No response
Actual Behaviour
gradle bootRun
works well, but building the application as jar file and running it leads to an startup error:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:119)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:91)
at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:53)
at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:58)
Caused by: io.micronaut.context.exceptions.NoSuchBeanException: No bean of type [io.micronaut.context.event.ApplicationEventPublisher<io.micronaut.context.event.StartupEvent>] exists. Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor).
at io.micronaut.context.DefaultBeanContext.newNoSuchBeanException(DefaultBeanContext.java:2773)
at io.micronaut.context.DefaultApplicationContext.newNoSuchBeanException(DefaultApplicationContext.java:304)
at io.micronaut.context.DefaultBeanContext.resolveBeanRegistration(DefaultBeanContext.java:2735)
at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:1729)
at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:856)
at io.micronaut.context.BeanLocator.getBean(BeanLocator.java:96)
at io.micronaut.context.DefaultBeanContext.publishEvent(DefaultBeanContext.java:1815)
at io.micronaut.context.DefaultBeanContext.start(DefaultBeanContext.java:376)
at io.micronaut.context.DefaultApplicationContext.start(DefaultApplicationContext.java:199)
at io.micronaut.spring.context.MicronautApplicationContext.start(MicronautApplicationContext.java:458)
at com.example.demo.DemoApplication.main(DemoApplication.java:14)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
... 4 more
Steps To Reproduce
- Clone
micronaut-spring-no-bean-of-type-applicationeventpublisher-exists
repository - Build jar
./gradlew bootJar
- Run jar
java -jar build/libs/demo-0.0.1-SNAPSHOT.jar
Environment Information
JDK Version:
openjdk 19.0.2 2023-01-17
OpenJDK Runtime Environment Temurin-19.0.2+7 (build 19.0.2+7)
OpenJDK 64-Bit Server VM Temurin-19.0.2+7 (build 19.0.2+7, mixed mode)
Example Application
https://github.com/donbeave/micronaut-spring-no-bean-of-type-applicationeventpublisher-exists
Version
4.2.3
You might want to check if it did create a shadow jar and if meta-inf services are merged correctly
You might want to check if it did create a shadow jar and if meta-inf services are merged correctly
There is only one file in services:
java.nio.file.spi.FileSystemProvider
There is no shadow jar, as it normal Spring Boot application created with Spring Initializer (https://start.spring.io) with micronaut-spring-boot
dependency. It's not using Micronaut Gradle plugin and Gradle Shadow plugin. It's using Micronaut as parent context for Spring Boot application.
@dstepanov I found a related issue in Micronaut Gradle plugin: micronaut-projects/micronaut-gradle-plugin#406, the only difference is that in my case I'm using Micronaut as a parent context without Gradle shadow and Micronaut Gradle plugins, only Spring gradle plugin with micronaut-spring-boot
dependency. It worked fine for Micronaut 3, but not for Micronaut 4. Has something changed in 4th version and need to add some extra config?
Looks like there was some change in Spring Boot 3. Config below helps to resolve this issue:
tasks.bootJar { loaderImplementation = org.springframework.boot.loader.tools.LoaderImplementation.CLASSIC }
The upstream change in Spring Boot 3.2 is documented in the release notes.
The previous URL format of
jar:file:/dir/myjar.jar:BOOT-INF/lib/nested.jar!/com/example/MyClass.class
has been replaced with
jar:nested:/dir/myjar.jar/!BOOT-INF/lib/nested.jar!/com/example/MyClass.class.
A new NestedFileSystemProvider was added in support of this new scheme.
However, micronaut-spring has code that prepends any jarUri that isn't starting with "file:" with that scheme:
https://github.com/micronaut-projects/micronaut-core/blob/0118db96962eaf7a83abbcb81c1afd73139ff777/core/src/main/java/io/micronaut/core/io/IOUtils.java#L156-L162
So you get something like file:/nested:/dir/myjar.jar/!BOOT-INF/lib/nested.jar!/com/example/MyClass.class
That causes the FileSystemProvider
for "file:" to be used instead of Spring's NestedFileSystemProvider
, and that former one won't be able to load /nested:.../
.
This is then causing the ServiceScanner to be unable to find any META-INF/micronaut/io.micronaut.inject.BeanDefinitionReference
files listing out bean definitions, causing those NoSuchBeanException
.