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

Inexistent 200 response mapped to null appears #1700

Closed dfernandezm closed 1 week ago

dfernandezm commented 2 months ago

Expected Behavior

Using micronaut openapi 6.11.1

Code to generate from spec correctly

Actual Behaviour

NullPointerException when generating POST request

Steps To Reproduce

  1. Mac OSX Sonoma 14.2
  2. Use this API Spec
openapi: 3.0.1
info:
  title: Test
  description: |
    Something
paths:
    post:
      tags:
      - Datasets
      summary: Create empty dataset v5
      description: |+
        Creates a brand new dataset.
      operationId: createDataset
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DatasetCreationRequest"
            examples:
              Example Dataset Request:
                summary: Dataset creation request
                value:
                  datasetName: Example Dataset
                  description: This is an example dataset description
        required: true
      responses:
        "201":
          description: Dataset successfully created
          content:
            application/json:
              schema:
                type: object
                properties:
                  datasetKey:
                    type: string
                  status:
                    type: string
                  datasetName:
                    type: string
                  description:
                    type: string
        "400":
          description: Invalid dataset name or description supplied
        "500":
          description: Internal server error
components:
  schemas:
    DatasetCreationOutput:
      required:
      - datasetCreationProgressUrl
      - datasetKey
      - status
      type: object
      properties:
        datasetKey:
          pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[4][0-9a-fA-F]{3}-[89aAbB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
          type: string
          format: uuid
        status:
          $ref: "#/components/schemas/DatasetCreationStatus"
        datasetCreationProgressUrl:
          type: string
    DatasetCreationRequest:
      required:
      - datasetName
      type: object
      properties:
        datasetName:
          maximum: 30
          minimum: 3
          type: string
          description: The unique dataset name
        description:
          maximum: 150
          minimum: 3
          type: string
          description: The dataset description in plain text
          nullable: true
    DatasetCreationStatus:
      type: string
      description: |+
        Status of dataset creation: 

        * `PENDING` 
        * `PROCESSING`
        * `COMPLETED`
        * `FAILED`

      enum:
      - PENDING
      - PROCESSING
      - COMPLETED
      - FAILED
  1. Execute ./gradlew compileJava
  2. See errors:
> Task :bai-api:compileJava FAILED
Note: Generating OpenAPI Documentation
warning: Error:
  Cannot invoke "io.swagger.v3.oas.models.responses.ApiResponse.getContent()" because "apiResponse" is null
  java.lang.NullPointerException: Cannot invoke "io.swagger.v3.oas.models.responses.ApiResponse.getContent()" because "apiResponse" is null
        at io.micronaut.openapi.visitor.OpenApiNormalizeUtils.normalizeOperation(OpenApiNormalizeUtils.java:136)
        at io.micronaut.openapi.visitor.OpenApiNormalizeUtils.normalizeOpenApi(OpenApiNormalizeUtils.java:70)
        at io.micronaut.openapi.visitor.OpenApiApplicationVisitor.postProcessOpenApi(OpenApiApplicationVisitor.java:698)
        at io.micronaut.openapi.visitor.OpenApiApplicationVisitor.finish(OpenApiApplicationVisitor.java:472)
        at io.micronaut.annotation.processing.TypeElementVisitorProcessor.process(TypeElementVisitorProcessor.java:281)
        at org.gradle.api.internal.tasks.compile.processing.DelegatingProcessor.process(DelegatingProcessor.java:62)
        at org.gradle.api.internal.tasks.compile.processing.DynamicProcessor.process(DynamicProcessor.java:52)
        at org.gradle.api.internal.tasks.compile.processing.DelegatingProcessor.process(DelegatingProcessor.java:62)
        at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.access$401(TimeTrackingProcessor.java:37)
        at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor$5.create(TimeTrackingProcessor.java:99)
        at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor$5.create(TimeTrackingProcessor.java:96)
        at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.track(TimeTrackingProcessor.java:117)
        at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.process(TimeTrackingProcessor.java:96)
        at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:1021)
        at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:937)
        at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1265)
        at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1380)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1271)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:948)
        at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:104)
        at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.invocationHelper(JavacTaskImpl.java:152)
        at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:100)
        at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:94)
        at org.gradle.internal.compiler.java.IncrementalCompileTask.call(IncrementalCompileTask.java:92)
        at org.gradle.api.internal.tasks.compile.AnnotationProcessingCompileTask.call(AnnotationProcessingCompileTask.java:94)
        at org.gradle.api.internal.tasks.compile.ResourceCleaningCompilationTask.call(ResourceCleaningCompilationTask.java:57)
        at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:55)
        at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:39)
        at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors(NormalizingJavaCompiler.java:98)
        at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:52)
        at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:38)
        at org.gradle.api.internal.tasks.compile.AnnotationProcessorDiscoveringCompiler.execute(AnnotationProcessorDiscoveringCompiler.java:51)
        at org.gradle.api.internal.tasks.compile.AnnotationProcessorDiscoveringCompiler.execute(AnnotationProcessorDiscoveringCompiler.java:37)
        at org.gradle.api.internal.tasks.compile.ModuleApplicationNameWritingCompiler.execute(ModuleApplicationNameWritingCompiler.java:46)
        at org.gradle.api.internal.tasks.compile.ModuleApplicationNameWritingCompiler.execute(ModuleApplicationNameWritingCompiler.java:36)
        at org.gradle.jvm.toolchain.internal.DefaultToolchainJavaCompiler.execute(DefaultToolchainJavaCompiler.java:57)
        at org.gradle.api.tasks.compile.JavaCompile.lambda$createToolchainCompiler$3(JavaCompile.java:202)
        at org.gradle.api.internal.tasks.compile.CleaningJavaCompiler.execute(CleaningJavaCompiler.java:53)
        at org.gradle.api.internal.tasks.compile.incremental.IncrementalCompilerFactory.lambda$createRebuildAllCompiler$0(IncrementalCompilerFactory.java:52)
        at org.gradle.api.internal.tasks.compile.incremental.SelectiveCompiler.execute(SelectiveCompiler.java:70)
        at org.gradle.api.internal.tasks.compile.incremental.SelectiveCompiler.execute(SelectiveCompiler.java:44)
        at org.gradle.api.internal.tasks.compile.incremental.IncrementalResultStoringCompiler.execute(IncrementalResultStoringCompiler.java:66)
        at org.gradle.api.internal.tasks.compile.incremental.IncrementalResultStoringCompiler.execute(IncrementalResultStoringCompiler.java:52)
        at org.gradle.api.internal.tasks.compile.CompileJavaBuildOperationReportingCompiler$1.call(CompileJavaBuildOperationReportingCompiler.java:64)
        at org.gradle.api.internal.tasks.compile.CompileJavaBuildOperationReportingCompiler$1.call(CompileJavaBuildOperationReportingCompiler.java:48)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:78)
        at org.gradle.api.internal.tasks.compile.CompileJavaBuildOperationReportingCompiler.execute(CompileJavaBuildOperationReportingCompiler.java:48)
        at org.gradle.api.tasks.compile.JavaCompile.performCompilation(JavaCompile.java:220)
        at org.gradle.api.tasks.compile.JavaCompile.performIncrementalCompilation(JavaCompile.java:161)
        at org.gradle.api.tasks.compile.JavaCompile.compile(JavaCompile.java:146)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
        at java.base/java.lang.reflect.Method.invoke(Method.java:580)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:125)
        at org.gradle.api.internal.project.taskfactory.IncrementalTaskAction.doExecute(IncrementalTaskAction.java:45)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:51)
        at org.gradle.api.internal.project.taskfactory.IncrementalTaskAction.execute(IncrementalTaskAction.java:26)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:29)
        at org.gradle.api.internal.tasks.execution.TaskExecution$3.run(TaskExecution.java:248)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:73)
        at org.gradle.api.internal.tasks.execution.TaskExecution.executeAction(TaskExecution.java:233)
        at org.gradle.api.internal.tasks.execution.TaskExecution.executeActions(TaskExecution.java:216)
        at org.gradle.api.internal.tasks.execution.TaskExecution.executeWithPreviousOutputFiles(TaskExecution.java:199)
        at org.gradle.api.internal.tasks.execution.TaskExecution.execute(TaskExecution.java:166)
        at org.gradle.internal.execution.steps.ExecuteStep.executeInternal(ExecuteStep.java:105)
        at org.gradle.internal.execution.steps.ExecuteStep.access$000(ExecuteStep.java:44)
        at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:59)
        at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:56)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:78)
        at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:56)
        at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:44)
        at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:67)
        at org.gradle.internal.execution.steps.RemovePreviousOutputsStep.execute(RemovePreviousOutputsStep.java:37)
        at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:41)
        at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:74)
        at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:55)
        at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:50)
        at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:28)
        at org.gradle.internal.execution.steps.CaptureStateAfterExecutionStep.executeDelegateBroadcastingChanges(CaptureStateAfterExecutionStep.java:100)
        at org.gradle.internal.execution.steps.CaptureStateAfterExecutionStep.execute(CaptureStateAfterExecutionStep.java:72)
        at org.gradle.internal.execution.steps.CaptureStateAfterExecutionStep.execute(CaptureStateAfterExecutionStep.java:50)
        at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:40)
        at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:29)
        at org.gradle.internal.execution.steps.BuildCacheStep.executeWithoutCache(BuildCacheStep.java:179)
        at org.gradle.internal.execution.steps.BuildCacheStep.lambda$execute$1(BuildCacheStep.java:70)
        at org.gradle.internal.Either$Right.fold(Either.java:175)
        at org.gradle.internal.execution.caching.CachingState.fold(CachingState.java:59)
        at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:68)
        at org.gradle.internal.execution.steps.BuildCacheStep.execute(BuildCacheStep.java:46)
        at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:36)
        at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:25)
        at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:36)
        at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:22)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:91)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$2(SkipUpToDateStep.java:55)
        at java.base/java.util.Optional.orElseGet(Optional.java:364)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:55)
        at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:37)
        at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:65)
        at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:36)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:37)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:27)
        at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:77)
        at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:38)
        at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:108)
        at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:55)
        at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:71)
        at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:45)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.executeWithNonEmptySources(SkipEmptyWorkStep.java:177)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:86)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:53)
        at org.gradle.internal.execution.steps.RemoveUntrackedExecutionStateStep.execute(RemoveUntrackedExecutionStateStep.java:32)
        at org.gradle.internal.execution.steps.RemoveUntrackedExecutionStateStep.execute(RemoveUntrackedExecutionStateStep.java:21)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:38)
        at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:36)
        at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:23)
        at org.gradle.internal.execution.steps.CleanupStaleOutputsStep.execute(CleanupStaleOutputsStep.java:75)
        at org.gradle.internal.execution.steps.CleanupStaleOutputsStep.execute(CleanupStaleOutputsStep.java:41)
        at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.lambda$execute$2(ExecuteWorkBuildOperationFiringStep.java:66)
        at java.base/java.util.Optional.orElseGet(Optional.java:364)
        at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:66)
        at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:38)
        at org.gradle.internal.execution.steps.AssignWorkspaceStep.lambda$execute$0(AssignWorkspaceStep.java:32)
        at org.gradle.api.internal.tasks.execution.TaskExecution$4.withWorkspace(TaskExecution.java:293)
        at org.gradle.internal.execution.steps.AssignWorkspaceStep.execute(AssignWorkspaceStep.java:30)
        at org.gradle.internal.execution.steps.AssignWorkspaceStep.execute(AssignWorkspaceStep.java:21)
        at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:37)
        at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:27)
        at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:47)
        at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:34)
        at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:64)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:145)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:134)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:74)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
        at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
        at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:78)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:331)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:318)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.lambda$execute$0(DefaultTaskExecutionGraph.java:314)
        at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:80)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:314)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:463)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:380)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
        at java.base/java.lang.Thread.run(Thread.java:1583)
error: Error finalizing type visitor [io.micronaut.openapi.visitor.OpenApiApplicationVisitor@24491dc7]: Cannot invoke "io.swagger.v3.oas.models.responses.ApiResponse.getContent()" because "apiResponse" is null
  java.lang.NullPointerException: Cannot invoke "io.swagger.v3.oas.models.responses.ApiResponse.getContent()" because "apiResponse" is null

Environment Information

Example Application

No response

Version

4.5.0

altro3 commented 2 months ago

Can't reproduce this exception with your example. But I see that you have bug in your schema: need to set any path. I tried to generate code by schema with path /, but I can't catch this exception:

изображение

Generated server code and openapi file by this generated code:

изображение

altro3 commented 2 months ago

@dfernandezm ping

altro3 commented 2 months ago

Ok,If you still have a problem, update the example and write about it - we will reopen the ticket

dfernandezm commented 1 month ago

Hi, sorry for late reply @altro3, I've been away.

Thanks for trying to recreate this, all it's a bit confusing but I still get the error my side. It can be environmental, I'll try to add more detail.

I amended the spec to have a minimal failing one and validated it with Swagger editor too.

This is the build.gradle relevant chunk:

plugins {
    id 'io.micronaut.application' version '4.4.0'
    id 'com.google.cloud.tools.jib' version '3.4.3'
    id 'org.openapi.generator' version '7.7.0'
    id 'io.micronaut.openapi' version '4.4.2'
}

micronaut {
    version "4.5.0"
    importMicronautPlatform = true
    processing {
        // Sets whether incremental annotation processing is enabled
        incremental true
    }

    // Filed issue https://github.com/micronaut-projects/micronaut-openapi/issues/1700
    openapi {
        server(file("$rootDir/api/test-issue.yml")) {
            apiPackageName = "com.api.openapi.generated.api"
            modelPackageName = "com.api.openapi.generated.model"
            useReactive = false
            useAuth = true
        }
    }
}

dependencies {
    annotationProcessor("io.micronaut:micronaut-http-validation")
    annotationProcessor("io.micronaut.security:micronaut-security-annotations")
    annotationProcessor("io.micronaut.serde:micronaut-serde-processor")
    annotationProcessor("io.micronaut.validation:micronaut-validation-processor")
    implementation("io.micronaut.validation:micronaut-validation")
    annotationProcessor("io.micronaut:micronaut-inject-java")

    annotationProcessor("io.micronaut.openapi:micronaut-openapi:6.11.1")
    compileOnly("io.micronaut.openapi:micronaut-openapi-annotations:6.11.1")
    implementation("io.micronaut.openapi:micronaut-openapi-annotations:6.11.1")
    implementation("io.micronaut.openapi:micronaut-openapi-common:6.11.1")

    implementation("io.micronaut.serde:micronaut-serde-jackson")
    implementation("org.openapitools:jackson-databind-nullable:0.2.6")

    implementation("io.micronaut:micronaut-http-client")
    implementation("io.micronaut:micronaut-http-server")
    implementation("io.micronaut:micronaut-jackson-databind")

    annotationProcessor("io.micronaut.validation:micronaut-validation-processor")
    implementation("io.micronaut.validation:micronaut-validation")

    implementation("jakarta.annotation:jakarta.annotation-api")
    implementation("io.micronaut.security:micronaut-security")
    implementation("io.micronaut.security:micronaut-security-jwt")
}

The spec I'm using:

openapi: 3.0.1
info:
  title: Test
  description: |
    Something
paths:
  /predictions/models/{modelKey}:
    post:
      tags:
        - Predictions
      summary: Create a prediction
      description: |
        Creates a new prediction using the dataset and model specified
        for the blind CSV
      operationId: createPrediction
      parameters:
        - name: modelKey
          in: path
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        content:
          text/csv:
            schema:
              type: string
              format: binary
          multipart/form-data:
            schema:
              type: string
              format: binary
        required: true
      responses:
        "200":
          description: Prediction created successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PredictionCreationOutput"
              examples:
                Successful prediction creation:
                  summary: Successful prediction creation
                  value:
                    predictionKey: 3a1a9a83-d549-4f25-b7ed-8174e0c955de
                    status: "RUNNING"
                    predictionCreationProgressUrl: 2b0a9a83-d549-4f25-b7ed-8174e0c955cd
        "400":
          description: Invalid prediction submission
        "500":
          description: Internal server error
components:
  schemas:
    DatasetCreationOutput:
      required:
        - datasetCreationProgressUrl
        - datasetKey
        - status
      type: object
      properties:
        datasetKey:
          pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[4][0-9a-fA-F]{3}-[89aAbB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
          type: string
          format: uuid
        status:
          $ref: "#/components/schemas/DatasetCreationStatus"
        datasetCreationProgressUrl:
          type: string
    DatasetCreationRequest:
      required:
        - datasetName
      type: object
      properties:
        datasetName:
          maximum: 30
          minimum: 3
          type: string
          description: The unique dataset name
        description:
          maximum: 150
          minimum: 3
          type: string
          description: The dataset description in plain text
          nullable: true
    PredictionCreationOutput:
      required:
        - predictionCreationProgressUrl
        - predictionKey
        - status
      type: object
      properties:
        predictionKey:
          pattern: "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[4][0-9a-fA-F]{3}-[89aAbB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
          type: string
          format: uuid
        status:
          $ref: "#/components/schemas/DatasetCreationStatus"
        predictionCreationProgressUrl:
          type: string
    DatasetCreationStatus:
      type: string
      description: |+
        Status of dataset creation: 

        * `PENDING` 
        * `PROCESSING`
        * `COMPLETED`
        * `FAILED`

      enum:
        - PENDING
        - PROCESSING
        - COMPLETED
        - FAILED

Codegen seems to work, but compileJava fails badly:

> Task :bai-api:generateServerOpenApiApis
Missing required field info version. Default appVersion set to 1.0.0
Missing required field info version. Default version set to 1.0.0
################################################################################
# Thanks for using OpenAPI Generator.                                          #
# Please consider donation to help us maintain this project 🙏                 #
# https://opencollective.com/openapi_generator/donate                          #
################################################################################

> Task :bai-api:generateServerOpenApiModels
Missing required field info version. Default appVersion set to 1.0.0
Missing required field info version. Default version set to 1.0.0
Validation 'minimum' has no effect on schema 'string'. Ignoring!
Validation 'maximum' has no effect on schema 'string'. Ignoring!
Validation 'minimum' has no effect on schema 'string'. Ignoring!
Validation 'maximum' has no effect on schema 'string'. Ignoring!
################################################################################
# Thanks for using OpenAPI Generator.                                          #
# Please consider donation to help us maintain this project 🙏                 #
# https://opencollective.com/openapi_generator/donate                          #
################################################################################

> Task :bai-api:compileJava FAILED
Note: Generating OpenAPI Documentation
warning: Error:
  Cannot invoke "io.swagger.v3.oas.models.responses.ApiResponse.getContent()" because "apiResponse" is null
  java.lang.NullPointerException: Cannot invoke "io.swagger.v3.oas.models.responses.ApiResponse.getContent()" because "apiResponse" is null
        at io.micronaut.openapi.visitor.OpenApiNormalizeUtils.normalizeOperation(OpenApiNormalizeUtils.java:136)
        at io.micronaut.openapi.visitor.OpenApiNormalizeUtils.normalizeOpenApi(OpenApiNormalizeUtils.java:70)
        at io.micronaut.openapi.visitor.OpenApiApplicationVisitor.postProcessOpenApi(OpenApiApplicationVisitor.java:698)
        at io.micronaut.openapi.visitor.OpenApiApplicationVisitor.finish(OpenApiApplicationVisitor.java:472)
        at io.micronaut.annotation.processing.TypeElementVisitorProcessor.process(TypeElementVisitorProcessor.java:281)
        at org.gradle.api.internal.tasks.compile.processing.DelegatingProcessor.process(DelegatingProcessor.java:62)
        at org.gradle.api.internal.tasks.compile.processing.DynamicProcessor.process(DynamicProcessor.java:52)
        at org.gradle.api.internal.tasks.compile.processing.DelegatingProcessor.process(DelegatingProcessor.java:62)
        at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.access$401(TimeTrackingProcessor.java:37)
        at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor$5.create(TimeTrackingProcessor.java:99)
        at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor$5.create(TimeTrackingProcessor.java:96)
        at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.track(TimeTrackingProcessor.java:117)
        at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.process(TimeTrackingProcessor.java:96)
        at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:1021)
        at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:937)
        at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1265)
        at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1380)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1271)
        at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:948)
        at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:104)
        at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.invocationHelper(JavacTaskImpl.java:152)
        at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:100)
        at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:94)
        at org.gradle.internal.compiler.java.IncrementalCompileTask.call(IncrementalCompileTask.java:92)
        at org.gradle.api.internal.tasks.compile.AnnotationProcessingCompileTask.call(AnnotationProcessingCompileTask.java:94)
        at org.gradle.api.internal.tasks.compile.ResourceCleaningCompilationTask.call(ResourceCleaningCompilationTask.java:57)
        at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:55)
        at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:39)
        at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.delegateAndHandleErrors(NormalizingJavaCompiler.java:98)
        at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:52)
        at org.gradle.api.internal.tasks.compile.NormalizingJavaCompiler.execute(NormalizingJavaCompiler.java:38)
        at org.gradle.api.internal.tasks.compile.AnnotationProcessorDiscoveringCompiler.execute(AnnotationProcessorDiscoveringCompiler.java:51)
        at org.gradle.api.internal.tasks.compile.AnnotationProcessorDiscoveringCompiler.execute(AnnotationProcessorDiscoveringCompiler.java:37)
        at org.gradle.api.internal.tasks.compile.ModuleApplicationNameWritingCompiler.execute(ModuleApplicationNameWritingCompiler.java:46)
        at org.gradle.api.internal.tasks.compile.ModuleApplicationNameWritingCompiler.execute(ModuleApplicationNameWritingCompiler.java:36)
        at org.gradle.jvm.toolchain.internal.DefaultToolchainJavaCompiler.execute(DefaultToolchainJavaCompiler.java:57)
        at org.gradle.api.tasks.compile.JavaCompile.lambda$createToolchainCompiler$3(JavaCompile.java:202)
        at org.gradle.api.internal.tasks.compile.CleaningJavaCompiler.execute(CleaningJavaCompiler.java:53)
        at org.gradle.api.internal.tasks.compile.incremental.IncrementalCompilerFactory.lambda$createRebuildAllCompiler$0(IncrementalCompilerFactory.java:52)

Codegen seems to work well (I can see apis and models) but compileJava task is throwing this obscure exception. Any guidance is appreciated

altro3 commented 1 month ago

@dfernandezm Hm.. I still can't reproduce this bug.

Could you create a sample application to reproduce this bug?

The current information is not enough, because I can't reproduce your problem.

Also, try using the latest version of micronaut-openapi . Right now you are using a very old version 6.11.1

altro3 commented 1 month ago

Unlikely, but possible: you're on a Mac and I'm on Windows, so it works for me and not for you.

It's extremely important that you create a complete, simple application to reproduce the problem.

dfernandezm commented 1 month ago

Hi, thanks for the time again.

I've put 6.11.1 and still get the issue. The problem happens after code generation, and it's a gradle exception. It's likely I need to park this for a bit, but I'll attach a minimal application that reproduces the problem at the earliest. Thank you.

altro3 commented 1 month ago

@dfernandezm Once again:

  1. Please provide a working application with a reproduction of your bug - create a repository on github, add everything you need and tell me how to run it - I'll check everything.

  2. Try updating the micronaut-openapi version to the latest. The latest version is 6.12.3 . Change 6.11.1 to 6.12.3. 6.11.1 is a very old version.

I can't help you any other way.

dfernandezm commented 1 month ago

HI @altro3 I finally found the issue. The clue was something about annotation processing in the exception. If there's classes in the project annotated with OpenAPI/Swagger annotations already, looks like there's a conflict of some sorts and the indicated Gradle exception happens.

Basically I had a controller like this:


@SuppressWarnings("unused")
@Controller("/predictions")
public interface PredictionOpenApiController extends OpenApiController {

    static final String UUID_REGEX = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[4][0-9a-fA-F]{3}-[89aAbB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$";

    @Tags({@Tag(name="Predictions")})
    @Operation(
            operationId = "createPrediction",
            summary = "Create a prediction",
            description = "Creates a new prediction using the dataset and model specified for the blind CSV")
    @ApiResponses({
            @ApiResponse(responseCode = "201", description = "Prediction created successfully",
                    content = @Content(schema = @Schema(implementation = PredictionCreationOutput.class),
                            examples = @ExampleObject(
                                    name = "Successful prediction creation response",
                                    summary = "Successful prediction creation response",
                                    value = """
                                    {
                                      "predictionKey": "3a1a9a83-d549-4f25-b7ed-8174e0c955de",
                                      "modelKey": "6a1a9a83-d549-4f25-b7ed-8174e0c955b",
                                      "datasetKey": "2b0a9a83-d549-4f25-b7ed-8174e0c955cd"
                                      "status": "PENDING",
                                      "predictionProgressUrl": "http://server/api/predictions/3a1a9a83-d549-4f25-b7ed-8174e0c955de/progress"
                                    }
                                    """

                            ))),
            @ApiResponse(responseCode = "400", description = "Invalid prediction submission"),
            @ApiResponse(responseCode = "500", description = "Internal server error")
    })

...

Before codegen , I was generating the spec from the code annotations (as it helps reason about outputs etc.). Now I use the base spec to do spec-first and iterate on it.

I don't think it's common at all gen code from spec and also have controllers annotated, so this issue won't happen to 99.9% of people. I can create a reproducer easily, but I wonder of its value given the extreme edge case. The error is very misleading though.

Thanks for the help!

altro3 commented 1 month ago

Of course it is valuable because somehow you managed to add null to the list of responses - I am very curious how it works and I want to fix this error. So please create a simple reproducer.

dfernandezm commented 1 month ago

To manage expectations, it might take some time for me to generate this reproducer, as I need to progress with the project. But I will definitely do it so please leave the issue opened.

On a separate topic (can post question?) I find it hard to find docs on the basics of codegen from spec. I have a strong use case to generate server Micronaut from spec and I'm struggling to find many of the settings/features as seen at https://openapi-generator.tech/, I see that the Micronaut codegen moved to this project so I would've expected same features here? (for example additionalModelTypeAnnotations from https://openapi-generator.tech/docs/generators/java-micronaut-server/)

altro3 commented 1 month ago

That's right, the generator was moved here. So, regarding the settings that are supported, unfortunately, no one has written normal documentation for code generation.

But here you can find all the settings that can be set at the moment:

https://github.com/micronaut-projects/micronaut-openapi/blob/6.12.x/openapi-generator/src/main/java/io/micronaut/openapi/generator/MicronautCodeGeneratorOptionsBuilder.java

dfernandezm commented 1 month ago

Thanks for the core info. Checking what's there, unfortunately I'll be stuck with OpenAPI generator core plugin with custom templates for a while then, as I need to heavily customise the models mainly (add extra annotations etc.) and don't see a way to override templates or use more configOptions that currently supported in the moved Micronaut Server generator (I'll keep an eye for updates though).

Regardless I'll provide the reproducer for the original issue as soon as I can, but with low priority as I need to make progress proving codegen / spec-first for this project.

altro3 commented 1 month ago

If you see that there are some features that are supported in the main openapi generator, but they are not supported in the generator from micronaut - just create an issue.

I add features as requests come in.

altro3 commented 1 month ago

@dfernandezm Please write in a separate issue a list of features that you need and that are not currently available - I will add them in the very near future.

altro3 commented 1 month ago

@dfernandezm added support for additional annotations here: https://github.com/micronaut-projects/micronaut-openapi/pull/1771

altro3 commented 2 weeks ago

@dfernandezm any news?