micronaut-core icon indicating copy to clipboard operation
micronaut-core copied to clipboard

Micronaut fails to correctly generate Definition class and fails with ClassNotFoundException: <any>

Open stepanv opened this issue 2 years ago • 0 comments

Expected Behavior

When using Micronaut with Lombok, when injecting a class that uses a builder class generated by Lombok's @SuperBuilder, Micronaut should be able to correctly generate its $Definition classes so that it doesn't fail during the runtime.

Actual Behaviour

Micronaut may generate invalid $Definition class file. In particular it may contain an invalid call

Argument.ofTypeVariable(<any>.class,"B")

which is what I see in the decompiled .class file.

The reality is that the Java classloader tries to load a class of a classname <any> which fails with exception

Caused by: io.micronaut.context.exceptions.BeanContextException: Error loading bean [io.micronaut.inject.generics.WildCardWithInheritanceLombokInject]: <any>
	at io.micronaut.context.DefaultBeanContext.findBeanCandidates(DefaultBeanContext.java:2096)
	at io.micronaut.context.DefaultApplicationContext.findBeanCandidates(DefaultApplicationContext.java:256)
	...
	... 1 more
Caused by: java.lang.NoClassDefFoundError: <any>
	at io.micronaut.context.AbstractInitializableBeanDefinitionReference.load(AbstractInitializableBeanDefinitionReference.java:145)
	at io.micronaut.context.DefaultBeanContext.findBeanCandidates(DefaultBeanContext.java:2094)
	... 9 more
Caused by: java.lang.ClassNotFoundException: <any>
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 11 more

Steps To Reproduce

See my PR with a test that's failing with the reported error at: https://github.com/micronaut-projects/micronaut-core/pull/7974

where Micronaut for class

public class WildCardWithInheritanceLombokInject {
    // tests injecting field
    @Inject
    protected Action<?> action;

    interface Action<B extends MyDto.MyDtoBuilder<?, ?>> {
    }

    @Singleton
    static class IntegerAction implements Action<MyDto.MyDtoBuilder<?, ?>> {

    }

    @SuperBuilder
    static class MyDto {

    }

}

generates $WildCardWithInheritanceLombokInject$Definition.class containing

new Argument[] {
   Argument.ofTypeVariable(<any>.class, "B")
}

Interestingly, when I manually define the builder class in the MyDto class, the problem doesn't occur:

    @SuperBuilder
    static class MyDto {
        public static abstract class MyDtoBuilder<C extends MyDto, B extends MyDtoBuilder<C, B>> {
        }
    }

as Micronaut correctly generates

new Argument[] {
    Argument.ofTypeVariable(
        WildCardWithInheritanceLombokInject.MyDto.MyDtoBuilder.class,
        "B", 
        (AnnotationMetadata) null, 
        new Argument[] {
            Argument.ofTypeVariable(WildCardWithInheritanceLombokInject.MyDto.class, "C"),
            Argument.ofTypeVariable(
                WildCardWithInheritanceLombokInject.MyDto.MyDtoBuilder.class, 
                "B",
                (AnnotationMetadata) null, 
                Argument.ZERO_ARGUMENTS)
        })
}

Environment Information

JDK:

openjdk 17.0.3 2022-04-19 LTS
OpenJDK Runtime Environment Zulu17.34+19-CA (build 17.0.3+7-LTS)
OpenJDK 64-Bit Server VM Zulu17.34+19-CA (build 17.0.3+7-LTS, mixed mode, sharing)

Example Application

https://github.com/micronaut-projects/micronaut-core/pull/7974

Version

3.6.2

stepanv avatar Sep 09 '22 15:09 stepanv