micronaut-projects / micronaut-openapi

Generates OpenAPI / Swagger Documentation for Micronaut projects
https://micronaut-projects.github.io/micronaut-openapi/latest/guide/index.html
Apache License 2.0
80 stars 94 forks source link

Kotlin: When controller request parameter is a collection of enum and different from Array #1131

Closed roar-skinderviken closed 1 year ago

roar-skinderviken commented 1 year ago

Expected Behavior

When upgrading to MN:4.0.0 and micronaut-openapi:5.0.1, builds in Azure Pipeline started to fail, and the problem was located to a specific controller that had one request parameter of type Collection. This worked fine with MN:3.9.4 and micronaut-openapi:4.9.2.

Example controller

@Controller("/hello")
class HelloController {

    @Get
    @Produces(MediaType.TEXT_PLAIN)
    fun index(@Nullable @QueryValue("channels") channels: Collection<Channel>?) = "Hello World"

    @Introspected
    enum class Channel {
        SYSTEM1,
        SYSTEM2
    }
}

Replacing Collection with Array solved the issue.

I'm not able to reproduce this issue on localhost.

Actual Behaviour

We were getting this stack trace in Azure Pipelines build log:

2023-07-14T10:58:07.8566490Z [INFO] Note: Generating OpenAPI Documentation 2023-07-14T10:58:07.9204815Z [ERROR] java.lang.IllegalStateException: failed to analyze: java.lang.reflect.InvocationTargetException 2023-07-14T10:58:07.9205292Z at org.jetbrains.kotlin.analyzer.AnalysisResult.throwIfError(AnalysisResult.kt:56) 2023-07-14T10:58:07.9206027Z at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:92) 2023-07-14T10:58:07.9206494Z at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:47) 2023-07-14T10:58:07.9206860Z at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:168) 2023-07-14T10:58:07.9207196Z at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:53) 2023-07-14T10:58:07.9207654Z at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:100) 2023-07-14T10:58:07.9208219Z at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:46) 2023-07-14T10:58:07.9208523Z at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) 2023-07-14T10:58:07.9208839Z at org.jetbrains.kotlin.maven.KotlinCompileMojoBase.execCompiler(KotlinCompileMojoBase.java:239) 2023-07-14T10:58:07.9209174Z at org.jetbrains.kotlin.maven.K2JVMCompileMojo.execCompiler(K2JVMCompileMojo.java:240) 2023-07-14T10:58:07.9209522Z at org.jetbrains.kotlin.maven.kapt.KaptJVMCompilerMojo.execCompiler(KaptJVMCompilerMojo.java:154) 2023-07-14T10:58:07.9209861Z at org.jetbrains.kotlin.maven.kapt.KaptJVMCompilerMojo.execCompiler(KaptJVMCompilerMojo.java:46) 2023-07-14T10:58:07.9210202Z at org.jetbrains.kotlin.maven.KotlinCompileMojoBase.execute(KotlinCompileMojoBase.java:220) 2023-07-14T10:58:07.9210624Z at org.jetbrains.kotlin.maven.K2JVMCompileMojo.execute(K2JVMCompileMojo.java:225) 2023-07-14T10:58:07.9210981Z at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137) 2023-07-14T10:58:07.9211361Z at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2(MojoExecutor.java:370) 2023-07-14T10:58:07.9211712Z at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute(MojoExecutor.java:351) 2023-07-14T10:58:07.9212068Z at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:215) 2023-07-14T10:58:07.9212413Z at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:171) 2023-07-14T10:58:07.9212748Z at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:163) 2023-07-14T10:58:07.9213116Z at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117) 2023-07-14T10:58:07.9213523Z at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81) 2023-07-14T10:58:07.9213951Z at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56) 2023-07-14T10:58:07.9214352Z at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128) 2023-07-14T10:58:07.9214686Z at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:299) 2023-07-14T10:58:07.9214996Z at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193) 2023-07-14T10:58:07.9215275Z at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106) 2023-07-14T10:58:07.9215558Z at org.apache.maven.cli.MavenCli.execute(MavenCli.java:963) 2023-07-14T10:58:07.9215832Z at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:296) 2023-07-14T10:58:07.9216101Z at org.apache.maven.cli.MavenCli.main(MavenCli.java:199) 2023-07-14T10:58:07.9216380Z at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 2023-07-14T10:58:07.9216697Z at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) 2023-07-14T10:58:07.9217061Z at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 2023-07-14T10:58:07.9217379Z at java.base/java.lang.reflect.Method.invoke(Method.java:568) 2023-07-14T10:58:07.9217677Z at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282) 2023-07-14T10:58:07.9218002Z at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225) 2023-07-14T10:58:07.9218328Z at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406) 2023-07-14T10:58:07.9218653Z at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347) 2023-07-14T10:58:07.9218923Z Caused by: java.lang.reflect.InvocationTargetException 2023-07-14T10:58:07.9219184Z at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 2023-07-14T10:58:07.9219505Z at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) 2023-07-14T10:58:07.9219857Z at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 2023-07-14T10:58:07.9220244Z at java.base/java.lang.reflect.Method.invoke(Method.java:568) 2023-07-14T10:58:07.9220561Z at org.jetbrains.kotlin.kapt3.base.AnnotationProcessingKt.doAnnotationProcessing(annotationProcessing.kt:90) 2023-07-14T10:58:07.9220930Z at org.jetbrains.kotlin.kapt3.base.AnnotationProcessingKt.doAnnotationProcessing$default(annotationProcessing.kt:31) 2023-07-14T10:58:07.9221307Z at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.runAnnotationProcessing(Kapt3Extension.kt:234) 2023-07-14T10:58:07.9221643Z at org.jetbrains.kotlin.kapt3.AbstractKapt3Extension.analysisCompleted(Kapt3Extension.kt:197) 2023-07-14T10:58:07.9221986Z at org.jetbrains.kotlin.kapt3.ClasspathBasedKapt3Extension.analysisCompleted(Kapt3Extension.kt:104) 2023-07-14T10:58:07.9222420Z at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM$analyzeFilesWithJavaIntegration$2.invoke(TopDownAnalyzerFacadeForJVM.kt:104) 2023-07-14T10:58:07.9222855Z at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(TopDownAnalyzerFacadeForJVM.kt:114) 2023-07-14T10:58:07.9223327Z at org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration$default(TopDownAnalyzerFacadeForJVM.kt:88) 2023-07-14T10:58:07.9223752Z at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:256) 2023-07-14T10:58:07.9224149Z at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler$analyze$1.invoke(KotlinToJVMBytecodeCompiler.kt:42) 2023-07-14T10:58:07.9224535Z at org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport.analyzeAndReport(AnalyzerWithCompilerReport.kt:115) 2023-07-14T10:58:07.9224928Z at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.analyze(KotlinToJVMBytecodeCompiler.kt:247) 2023-07-14T10:58:07.9225307Z at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:87) 2023-07-14T10:58:07.9225595Z ... 36 more 2023-07-14T10:58:07.9225907Z Caused by: com.sun.tools.javac.processing.AnnotationProcessingError: java.lang.NullPointerException: Cannot invoke "io.swagger.v3.oas.models.media.Schema.setName(String)" because "schema" is null 2023-07-14T10:58:07.9226335Z at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:1035) 2023-07-14T10:58:07.9226727Z at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:939) 2023-07-14T10:58:07.9227117Z at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1267) 2023-07-14T10:58:07.9227517Z at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1382) 2023-07-14T10:58:07.9227876Z at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1234) 2023-07-14T10:58:07.9228134Z ... 53 more 2023-07-14T10:58:07.9228401Z Caused by: java.lang.NullPointerException: Cannot invoke "io.swagger.v3.oas.models.media.Schema.setName(String)" because "schema" is null 2023-07-14T10:58:07.9228762Z at io.micronaut.openapi.visitor.AbstractOpenApiVisitor.processSuperTypes(AbstractOpenApiVisitor.java:1946) 2023-07-14T10:58:07.9229129Z at io.micronaut.openapi.visitor.AbstractOpenApiVisitor.getSchemaDefinition(AbstractOpenApiVisitor.java:1847) 2023-07-14T10:58:07.9229482Z at io.micronaut.openapi.visitor.AbstractOpenApiVisitor.resolveSchema(AbstractOpenApiVisitor.java:907) 2023-07-14T10:58:07.9229837Z at io.micronaut.openapi.visitor.AbstractOpenApiVisitor.resolveSchema(AbstractOpenApiVisitor.java:852) 2023-07-14T10:58:07.9230211Z at io.micronaut.openapi.visitor.AbstractOpenApiEndpointVisitor.processParameter(AbstractOpenApiEndpointVisitor.java:769) 2023-07-14T10:58:07.9230603Z at io.micronaut.openapi.visitor.AbstractOpenApiEndpointVisitor.processParameters(AbstractOpenApiEndpointVisitor.java:554) 2023-07-14T10:58:07.9231027Z at io.micronaut.openapi.visitor.AbstractOpenApiEndpointVisitor.visitMethod(AbstractOpenApiEndpointVisitor.java:452) 2023-07-14T10:58:07.9231421Z at io.micronaut.annotation.processing.TypeElementVisitorProcessor$ElementVisitor.visitExecutable(TypeElementVisitorProcessor.java:521) 2023-07-14T10:58:07.9231795Z at jdk.compiler/com.sun.tools.javac.code.Symbol$MethodSymbol.accept(Symbol.java:2247) 2023-07-14T10:58:07.9232115Z at java.compiler@17.0.7/javax.lang.model.util.ElementScanner6.scan(ElementScanner6.java:153) 2023-07-14T10:58:07.9232487Z at io.micronaut.annotation.processing.TypeElementVisitorProcessor$ElementVisitor.visitType(TypeElementVisitorProcessor.java:436) 2023-07-14T10:58:07.9232893Z at jdk.compiler/com.sun.tools.javac.code.Symbol$ClassSymbol.accept(Symbol.java:1573) 2023-07-14T10:58:07.9233228Z at io.micronaut.annotation.processing.TypeElementVisitorProcessor.process(TypeElementVisitorProcessor.java:272) 2023-07-14T10:58:07.9233597Z at org.jetbrains.kotlin.kapt3.base.incremental.IncrementalProcessor.process(incrementalProcessors.kt:90) 2023-07-14T10:58:07.9233940Z at org.jetbrains.kotlin.kapt3.base.ProcessorWrapper.process(annotationProcessing.kt:197) 2023-07-14T10:58:07.9234306Z at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:1023) 2023-07-14T10:58:07.9234580Z ... 57 more

Steps To Reproduce

Apache Maven 3.8.8 Checkstyle analysis is enabled. PMD analysis is enabled.

Environment Information

micronaut-openapi:5.0.1 swagger-annotations:2.2.15 Kotlin 1.9.0 OS name: "linux", version: "5.15.0-1041-azure", arch: "amd64", family: "unix" Java version: 17.0.7, vendor: Eclipse Adoptium, runtime: /usr/lib/jvm/temurin-17-jdk-amd64

Example Application

No response

Version

4.0.0

altro3 commented 1 year ago

@roar-skinderviken Hi! Could you give me example to reproduce this bug?

roar-skinderviken commented 1 year ago

@altro3 I wish I could, but as I wrote, I can't reproduce this on localhost with Temurin 17.0.7.

@Parameter(
    description = "Some description here",
    required = false
)
@Nullable @QueryValue("channels") channels: Collection<Channel>?

@Introspected
enum class Channel {
    SYSTEM1,
    SYSTEM2
}

Changed to

@Parameter(
    description = "Some description here",
    required = false
)
@Nullable @QueryValue("channels") channels: Array<Channel>?
altro3 commented 1 year ago

hm... ok, I'll check it tomorrow

roar-skinderviken commented 1 year ago

I believe that the issue is about that Array is a class and Collection, Setand Listare interfaces.

altro3 commented 1 year ago

@roar-skinderviken bug in micronaut 4 core: https://github.com/micronaut-projects/micronaut-core/issues/9571

altro3 commented 1 year ago

@roar-skinderviken Looks like I'm not quite right. Yes, the behavior of the kernel has changed in the 4th version, but the bug still exists in micronaut-openapi:

The problem is identifying the generic in the collection, before micronaut returned the Channel class in your case (TypeElement instance), and now it returns the wildcard element, i.e. understands as if written ? extends Channel is already another component in java terms - this is the so-called WildcardElement

That's why everything stopped working. But I checked what happens if you change your example and explicitly specify a wildcard, i.e. write like this (but in java):

    @Get
    @Produces(MediaType.TEXT_PLAIN)
    public String index(@Nullable @QueryValue("channels") Collection<? extends Channel> channels) {
        return "Hello World";
    }

and i got the same error