micronaut-projects / micronaut-spring

A collection of utilities for Spring users of Micronaut
Apache License 2.0
159 stars 46 forks source link

Unable to build SpringContext with MicronautApplicationContext as parent #521

Closed sascha-frinken closed 4 months ago

sascha-frinken commented 5 months ago

Expected Behavior

Run an application with SpringContext and MicronautApplicationContext as parent.

Actual Behaviour

Application won't start.

Same was working with micronaut 3.

Error
Exception in thread "main" io.micronaut.core.io.service.SoftServiceLoader$ServiceLoadingException: Failed to load a service: io.micronaut.context.exceptions.BeanContextException: Unexpected error loading bean definition [com.example.$Application$AutoConfigurationPackages$Registrar0$Definition]: failed to access class org.springframework.boot.autoconfigure.AutoConfigurationPackages$Registrar from class com.example.$Application$AutoConfigurationPackages$Registrar0$Definition$Reference (org.springframework.boot.autoconfigure.AutoConfigurationPackages$Registrar and com.example.$Application$AutoConfigurationPackages$Registrar0$Definition$Reference are in unnamed module of loader 'app')
    at io.micronaut.core.io.service.ServiceScanner$ServiceInstanceLoader.collect(ServiceScanner.java:364)
    at io.micronaut.core.io.service.ServiceScanner$MicronautMetaServicesLoader.collect(ServiceScanner.java:289)
    at io.micronaut.core.io.service.ServiceScanner$DefaultServiceCollector.collect(ServiceScanner.java:246)
    at io.micronaut.core.io.service.SoftServiceLoader.collectDynamicServices(SoftServiceLoader.java:201)
    at io.micronaut.core.io.service.SoftServiceLoader.collectAll(SoftServiceLoader.java:176)
    at io.micronaut.context.DefaultBeanContext.resolveBeanDefinitionReferences(DefaultBeanContext.java:1865)
    at io.micronaut.context.DefaultApplicationContext.isBootstrapPropertySourceLocatorPresent(DefaultApplicationContext.java:162)
    at java.base/java.util.Objects.requireNonNullElseGet(Objects.java:310)
    at io.micronaut.context.DefaultApplicationContext.isBootstrapEnabled(DefaultApplicationContext.java:158)
    at io.micronaut.context.DefaultApplicationContext.createEnvironment(DefaultApplicationContext.java:146)
    at io.micronaut.context.DefaultApplicationContext.getEnvironment(DefaultApplicationContext.java:180)
    at io.micronaut.context.DefaultApplicationContextBuilder.build(DefaultApplicationContextBuilder.java:322)
    at io.micronaut.spring.context.MicronautApplicationContext.(MicronautApplicationContext.java:114)
    at io.micronaut.spring.context.MicronautApplicationContext.(MicronautApplicationContext.java:106)
    at com.example.Application.main(Application.groovy:16)
Caused by: io.micronaut.core.io.service.SoftServiceLoader$ServiceLoadingException: io.micronaut.context.exceptions.BeanContextException: Unexpected error loading bean definition [com.example.$Application$AutoConfigurationPackages$Registrar0$Definition]: failed to access class org.springframework.boot.autoconfigure.AutoConfigurationPackages$Registrar from class com.example.$Application$AutoConfigurationPackages$Registrar0$Definition$Reference (org.springframework.boot.autoconfigure.AutoConfigurationPackages$Registrar and com.example.$Application$AutoConfigurationPackages$Registrar0$Definition$Reference are in unnamed module of loader 'app')
    at io.micronaut.core.io.service.SoftServiceLoader.lambda$collectDynamicServices$2(SoftServiceLoader.java:197)
    at io.micronaut.core.io.service.ServiceScanner$ServiceInstanceLoader.compute(ServiceScanner.java:355)
    at java.base/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:194)
    at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
    at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
    at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
    at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
    at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
Caused by: io.micronaut.context.exceptions.BeanContextException: Unexpected error loading bean definition [com.example.$Application$AutoConfigurationPackages$Registrar0$Definition]: failed to access class org.springframework.boot.autoconfigure.AutoConfigurationPackages$Registrar from class com.example.$Application$AutoConfigurationPackages$Registrar0$Definition$Reference (org.springframework.boot.autoconfigure.AutoConfigurationPackages$Registrar and com.example.$Application$AutoConfigurationPackages$Registrar0$Definition$Reference are in unnamed module of loader 'app')
    at io.micronaut.context.AbstractInitializableBeanDefinitionReference.isPresent(AbstractInitializableBeanDefinitionReference.java:205)
    at io.micronaut.core.io.service.SoftServiceLoader.lambda$collectDynamicServices$2(SoftServiceLoader.java:190)
    ... 7 more
Caused by: java.lang.IllegalAccessError: failed to access class org.springframework.boot.autoconfigure.AutoConfigurationPackages$Registrar from class com.example.$Application$AutoConfigurationPackages$Registrar0$Definition$Reference (org.springframework.boot.autoconfigure.AutoConfigurationPackages$Registrar and com.example.$Application$AutoConfigurationPackages$Registrar0$Definition$Reference are in unnamed module of loader 'app')
    at com.example.$Application$AutoConfigurationPackages$Registrar0$Definition$Reference.getBeanType(Unknown Source)
    at io.micronaut.context.AbstractInitializableBeanDefinitionReference.isPresent(AbstractInitializableBeanDefinitionReference.java:197)
    ... 8 more

Steps To Reproduce

  1. create a micronaut application
  2. add spring
  3. Replace main in Application.class with:
    new SpringApplicationBuilder()
                .parent(new MicronautApplicationContext().tap { start() })
                .sources(Application)
                .build()
                .run()

Environment Information

OS: Linux JDK: 17 & 21

Example Application

https://github.com/safri-net/mn4-spring-issue

Version

4.2.3

altro3 commented 5 months ago

@graemerocher @dstepanov I confirm that there is indeed a bug and now it is not possible to launch the application with spring annotations

In general, I think we need to pay more attention to this library and refine it to maximum spring support. I think this will help to popularize micronaut even more. if he can work with the spring code.

sascha-frinken commented 5 months ago

@altro3 I hope you mean Micronaut not Microsoft ;)

altro3 commented 5 months ago

@sascha-frinken yeah, thanks. This is a dumb online translator. He doesn't understand what micronaut is :-). Usually, he translates it as minecraft, but it seems like today is a special day.

sascha-frinken commented 5 months ago

@altro3 @graemerocher Sorry to rush, but we need to make a decision on whether we can continue to work with micronaut in our GUIs. It would be helpful just to know if and when the problem will be fixed.

sdelamo commented 5 months ago

@sascha-frinken I am going to check this on Monday.

timyates commented 5 months ago

It seems to work when using Java 🤔

https://github.com/grails-core-issues-forks/micronaut-spring-521

timyates commented 5 months ago

It looks like under groovy we are generating AbstractInitializableBeanDefinition classes which relate to AutoConfigurationPackages.Registrar.class. This class is package private, which I believe is the cause of the failure

graemerocher commented 5 months ago

ok so a bug in the Groovy compiler

timyates commented 5 months ago

ok so a bug in the Groovy compiler

Do you mean the compiler itself, or something we are doing?

timyates commented 5 months ago

So adding

diff --git a/spring-annotation/src/main/java/io/micronaut/spring/annotation/beans/ImportAnnotationVisitor.java b/spring-annotation/src/main/java/io/micronaut/spring/annotation/beans/ImportAnnotationVisitor.java
index de4b9c8f..79b83865 100644
--- a/spring-annotation/src/main/java/io/micronaut/spring/annotation/beans/ImportAnnotationVisitor.java
+++ b/spring-annotation/src/main/java/io/micronaut/spring/annotation/beans/ImportAnnotationVisitor.java
@@ -80,7 +80,9 @@ public final class ImportAnnotationVisitor implements TypeElementVisitor<Object,
                     for (AnnotationClassValue<?> a : acv) {
                         String className = a.getName();
                         context.getClassElement(className).ifPresent(typeToImport -> {
-                            handleImport(element, context, typeToImport);
+                            if (typeToImport.isPublic()) {
+                                handleImport(element, context, typeToImport);
+                            }
                         });
                     }
                 }

Makes this work, but I suspect it isn't the fix, and we may need a fix in core somewhere in inject-groovy

We also (under groovy) see

WARNING: Spring ImportSelector [org.springframework.boot.autoconfigure.AutoConfigurationImportSelector] found in @Import declaration on element [boot4groovy.Application] was ignored. Ensure that the type is present on the annotation processor classpath. Note that only simple ImportSelector implementations that do no implement Aware interfaces (which cannot run at build time) are supported.

@SpringBootApplication ^

But I am not currently sure if this is part of the same issue...

dstepanov commented 4 months ago

The only solution is to avoid loading this class or copy and create an alternative of that class registered by:

@Import({AutoConfigurationPackages.Registrar.class})
public @interface AutoConfigurationPackage {

The same problem might be with: ImportAutoConfigurationImportSelector registered by:

@Import({ImportAutoConfigurationImportSelector.class})
public @interface ImportAutoConfiguration 
timyates commented 4 months ago

@sascha-frinken We've just released v5.4.1 of micronaut spring which we believe fixes this issue (by not creating bean definitions for spring's private configuration classes)

sascha-frinken commented 4 months ago

@timyates Thank you very much!

The test project is working now. As soon as we get around to working on our Micronaut 4 migration, I'll let you know if we have any problems.