quarkus-openapi-generator
quarkus-openapi-generator copied to clipboard
Reactive server code generation fails
Hey there! I just started using this tool as a means to replace usage of the openapi-generator jax-rs server stub generator. This is necessary because I'd like my REST resources to be reactive. Unfortunately, I encountered an issue with generating the reactive interfaces that is hard to troubleshoot. The following contains, the OpenAPI spec in question, the properties set in my pom.xml , and the PROJECT_GENERATION_FAILED.txt output.
OpenAPI spec:
openapi: 3.0.3
info:
contact:
email: [email protected]
name: Anon
url: 'https://anon.com'
description: |-
API for managing inventory sources and related metadata.
Inventory is comprised of a collection of sources, which are used to generate a list of instances.
title: Inventory
version: '1.0'
termsOfService: 'https://anon.com/legal'
servers:
- url: 'http://localhost:9996/api/inventory'
tags:
- name: Inventory
paths:
'/v1/{org_id}/sources':
parameters:
- $ref: '#/components/parameters/OrgIdPathParam'
get:
summary: Get sources
operationId: list-sources
responses:
'200':
$ref: '#/components/responses/Sources'
description: Return a list of all sources.
tags:
- Inventory
security:
- Auth0: []
'/v1/{org_id}/sources/gcp':
parameters:
- $ref: '#/components/parameters/OrgIdPathParam'
post:
summary: Create or update source
operationId: create-gcp-source
responses:
'200':
description: OK
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/Source'
description: 'Create or update the source identified by a unique ID in the body, parsed by its source type (currently only accepts a service account key for GCP).'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateGCPSourceRequest'
description: Upload JSON source credentials.
parameters: []
tags:
- Inventory
security:
- Auth0: []
'/v1/{org_id}/sources/gcp/{source_id}':
parameters:
- $ref: '#/components/parameters/OrgIdPathParam'
- $ref: '#/components/parameters/SourceIdPathParam'
put:
summary: Put GCP Source
operationId: put-gcp-source
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Source'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/CreateGCPSourceRequest'
tags:
- Inventory
'/v1/{org_id}/sources/{source_id}':
parameters:
- $ref: '#/components/parameters/OrgIdPathParam'
- $ref: '#/components/parameters/SourceIdPathParam'
delete:
summary: Delete source
operationId: delete-source
responses:
'204':
description: No Content
'404':
description: Not Found
tags:
- Inventory
security:
- Auth0: []
get:
summary: Get Source
operationId: getSource
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Source'
security:
- Auth0: []
tags:
- Inventory
'/v1/{org_id}/sources/{source_id}:sync':
post:
operationId: sync-source
responses:
'200':
description: OK
'404':
description: Not Found
summary: Sync a source
tags:
- Inventory
description: Synchronize available instances from the given source.
security:
- Auth0: []
parameters:
- $ref: '#/components/parameters/OrgIdPathParam'
- $ref: '#/components/parameters/SourceIdPathParam'
'/v1/{org_id}/search':
parameters:
- $ref: '#/components/parameters/OrgIdPathParam'
post:
summary: Search instances
operationId: search-instances
description: Search for instances based on a set of filters. Supports pagination based on instance ID cursor. Results are ordered by creation timestamp.
parameters:
- $ref: '#/components/parameters/PageOffsetQueryParam'
- $ref: '#/components/parameters/PageSizeQueryParam'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedSearchInstancesRequest'
examples:
match all:
value:
filters: []
description: Filter criteria.
tags:
- Inventory
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/PaginatedSearchInstancesResponse'
'400':
description: Bad Request
security:
- Auth0: []
'/v1/{org_id}/instance/{instance_id}':
parameters:
- $ref: '#/components/parameters/OrgIdPathParam'
- $ref: '#/components/parameters/InstanceIdPathParam'
get:
summary: Get instance details
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Instance'
operationId: get-instance
description: Get instance details.
tags:
- Inventory
security:
- Auth0: []
'/v1/{org_id}/instances/count':
parameters:
- schema:
type: string
name: org_id
in: path
required: true
get:
summary: Get Org Instance Count
tags:
- Inventory
responses:
'200':
description: OK
content:
application/json:
schema:
type: integer
format: int64
operationId: get-org-instance-count
description: Get the total number of instances in an organization
security:
- Auth0: []
components:
parameters:
OrgIdPathParam:
name: org_id
in: path
required: true
schema:
type: string
description: The tenant ID the resource belongs to
PageOffsetQueryParam:
name: page_offset
in: query
required: false
schema:
type: integer
description: Token for the next page
PageSizeQueryParam:
name: page_size
in: query
required: false
schema:
type: integer
description: Page size
SourceIdPathParam:
name: source_id
in: path
required: true
schema:
type: string
format: uuid
description: id of the source
InstanceIdPathParam:
name: instance_id
in: path
required: true
schema:
type: string
format: uuid
description: ID of the instance to retrieve
requestBodies: {}
schemas:
Source:
title: ''
type: object
properties:
id:
type: string
name:
type: string
last_synced:
type: integer
format: int64
instance_count:
type: integer
credentials_id:
type: string
format: uuid
type:
$ref: '#/components/schemas/SourceType'
required:
- id
- name
- last_synced
- instance_count
- credentials_id
- type
SearchFilter:
title: ''
type: object
properties:
key:
type: string
operator:
type: string
enum:
- lt
- eq
- gt
- contains
- not_contains
value:
type: string
type:
type: string
enum:
- GCP_METADATA
- FACTS
- SOURCE
- ASSIGNED_POLICY
- NODE
required:
- key
- operator
- value
- type
CuratedInstance:
description: ''
type: object
title: ''
properties:
name:
type: string
id:
type: string
source:
$ref: '#/components/schemas/Source'
creation_time:
type: integer
format: int64
internal_ip:
type: string
external_ip:
type: string
operating_system:
type: string
machine_type:
type: string
node_status:
type: string
uptime:
type: integer
format: int64
zone:
type: string
required:
- name
- id
- source
- creation_time
- internal_ip
- external_ip
- operating_system
- machine_type
- node_status
- uptime
- zone
Instance:
title: ''
type: object
properties:
name:
type: string
source:
$ref: '#/components/schemas/Source'
facts:
type: object
metadata:
type: object
required:
- name
- source
- facts
- metadata
GCPServiceAccount:
title: GCPServiceAccount
type: object
properties:
id:
type: string
format: uuid
type:
type: string
project_id:
type: string
private_key_id:
type: string
private_key:
type: string
client_email:
type: string
client_id:
type: string
auth_uri:
type: string
token_uri:
type: string
auth_provider_x509_cert_url:
type: string
client_x509_cert_url:
type: string
required:
- id
- type
- project_id
- private_key_id
- private_key
- client_email
- client_id
- auth_uri
- token_uri
- auth_provider_x509_cert_url
- client_x509_cert_url
CreateGCPSourceRequest:
title: CreateGCPSourceRequest
type: object
properties:
name:
type: string
gather_facts_on_ingest:
type: boolean
default: true
credentials:
$ref: '#/components/schemas/GCPCredential'
required:
- name
- gather_facts_on_ingest
- credentials
PatchGCPSourceRequest:
title: PatchGCPSourceRequest
type: object
properties:
name:
type: string
gather_facts_on_ingest:
type: boolean
PaginatedSearchInstancesRequest:
title: PaginatedSearchInstancesRequest
type: object
properties:
filters:
type: array
items:
$ref: '#/components/schemas/SearchFilter'
PaginatedSearchInstancesResponse:
title: PaginatedSearchInstancesResponse
type: object
properties:
next_page_offset:
type: integer
instances:
type: array
items:
$ref: '#/components/schemas/CuratedInstance'
total_count:
type: integer
format: int64
required:
- next_page_offset
- instances
- total_count
GCPCredential:
title: GCPCredential
type: object
properties:
type:
type: string
project_id:
type: string
private_key_id:
type: string
private_key:
type: string
client_email:
type: string
client_id:
type: string
auth_uri:
type: string
token_uri:
type: string
auth_provider_x509_cert_url:
type: string
client_x509_cert_url:
type: string
required:
- type
- project_id
- private_key_id
- private_key
- client_email
- client_id
- auth_uri
- token_uri
- auth_provider_x509_cert_url
- client_x509_cert_url
SourceType:
type: string
title: SourceType
enum:
- GCP
responses:
Sources:
description: A list of sources
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Source'
Search:
description: 'A list of curated instance details matching the search criteria, with a next cursor if there are more results.'
content:
application/json:
schema:
type: object
properties:
next_cursor:
type: string
instances:
type: array
items:
$ref: '#/components/schemas/CuratedInstance'
required:
- instances
securitySchemes:
Auth0:
type: http
scheme: bearer
bearerFormat: jwt
description: Auth0 token
My pom.xml properties:
<quarkus.openapi.generator.spec>openapi.yaml</quarkus.openapi.generator.spec>
<quarkus.openapi.generator.base-package>com.anon.web.api</quarkus.openapi.generator.base-package>
<quarkus.openapi.generator.reactive>true</quarkus.openapi.generator.reactive>
quarkus-openapi-generator version: 3.0.0-snapshot built from main
Error:
An unexpected server error was encountered while generating the project. See
the details of the error below.
Generation Log:
Generating Bean: com.anon.web.api.beans.Source
Generating Bean: com.anon.web.api.beans.SearchFilter
Generating Bean: com.anon.web.api.beans.CuratedInstance
Generating Bean: com.anon.web.api.beans.Instance
Generating Bean: com.anon.web.api.beans.GCPServiceAccount
Generating Bean: com.anon.web.api.beans.CreateGCPSourceRequest
Generating Bean: com.anon.web.api.beans.PatchGCPSourceRequest
Generating Bean: com.anon.web.api.beans.PaginatedSearchInstancesRequest
Generating Bean: com.anon.web.api.beans.PaginatedSearchInstancesResponse
Generating Bean: com.anon.web.api.beans.GCPCredential
Generating Bean: com.anon.web.api.beans.SourceType
Adding to zip: com/anon/web/api/beans/Source.java
Adding to zip: com/anon/web/api/beans/PaginatedSearchInstancesRequest.java
Adding to zip: com/anon/web/api/beans/Facts.java
Adding to zip: com/anon/web/api/beans/CreateGCPSourceRequest.java
Adding to zip: com/anon/web/api/beans/SourceType.java
Adding to zip: com/anon/web/api/beans/PatchGCPSourceRequest.java
Adding to zip: com/anon/web/api/beans/Metadata.java
Adding to zip: com/anon/web/api/beans/CuratedInstance.java
Adding to zip: com/anon/web/api/beans/PaginatedSearchInstancesResponse.java
Adding to zip: com/anon/web/api/beans/Instance.java
Adding to zip: com/anon/web/api/beans/GCPCredential.java
Adding to zip: com/anon/web/api/beans/SearchFilter.java
Adding to zip: com/anon/web/api/beans/GCPServiceAccount.java
Generating Interface: com.anon.web.api.V1Resource
Server Stack Trace:
java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:266)
at java.base/java.util.Objects.checkIndex(Objects.java:361)
at java.base/java.util.ArrayList.get(ArrayList.java:427)
at java.base/java.util.Collections$UnmodifiableList.get(Collections.java:1347)
at io.apicurio.hub.api.codegen.OpenApi2JaxRs.lambda$parseType$15(OpenApi2JaxRs.java:657)
at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1220)
at io.apicurio.hub.api.codegen.OpenApi2JaxRs.parseType(OpenApi2JaxRs.java:654)
at io.apicurio.hub.api.codegen.OpenApi2JaxRs.generateReactiveTypeName(OpenApi2JaxRs.java:769)
at io.apicurio.hub.api.codegen.OpenApi2JaxRs.lambda$generateJavaInterface$9(OpenApi2JaxRs.java:560)
at java.base/java.util.Optional.map(Optional.java:260)
at io.apicurio.hub.api.codegen.OpenApi2JaxRs.lambda$generateJavaInterface$14(OpenApi2JaxRs.java:560)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at io.apicurio.hub.api.codegen.OpenApi2JaxRs.generateJavaInterface(OpenApi2JaxRs.java:519)
at io.apicurio.hub.api.codegen.OpenApi2JaxRs.generateJavaInterface(OpenApi2JaxRs.java:634)
at io.apicurio.hub.api.codegen.OpenApi2JaxRs.generateAll(OpenApi2JaxRs.java:322)
at io.apicurio.hub.api.codegen.OpenApi2JaxRs.generate(OpenApi2JaxRs.java:216)
at io.quarkiverse.openapi.server.generator.deployment.codegen.ApicurioCodegenWrapper.generate(ApicurioCodegenWrapper.java:69)
at io.quarkiverse.openapi.server.generator.deployment.codegen.ApicurioOpenApiServerCodegen.trigger(ApicurioOpenApiServerCodegen.java:87)
at io.quarkus.deployment.CodeGenerator.lambda$trigger$4(CodeGenerator.java:206)
at io.quarkus.deployment.CodeGenerator.callWithClassloader(CodeGenerator.java:181)
at io.quarkus.deployment.CodeGenerator.trigger(CodeGenerator.java:203)
at io.quarkus.deployment.CodeGenerator.initAndRun(CodeGenerator.java:80)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:569)
at io.quarkus.maven.GenerateCodeMojo.generateCode(GenerateCodeMojo.java:88)
at io.quarkus.maven.GenerateCodeMojo.doExecute(GenerateCodeMojo.java:54)
at io.quarkus.maven.QuarkusBootstrapMojo.execute(QuarkusBootstrapMojo.java:171)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:126)
at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2(MojoExecutor.java:328)
at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute(MojoExecutor.java:316)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:212)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:174)
at org.apache.maven.lifecycle.internal.MojoExecutor.access$000(MojoExecutor.java:75)
at org.apache.maven.lifecycle.internal.MojoExecutor$1.run(MojoExecutor.java:162)
at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute(DefaultMojosExecutionStrategy.java:39)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:159)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:105)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:73)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:53)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:118)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:261)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:173)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:101)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:903)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:280)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:203)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:569)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:255)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:201)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:361)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:314)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:569)
at org.apache.maven.wrapper.BootstrapMainStarter.start(BootstrapMainStarter.java:52)
at org.apache.maven.wrapper.WrapperExecutor.execute(WrapperExecutor.java:161)
at org.apache.maven.wrapper.MavenWrapperMain.main(MavenWrapperMain.java:73)
@ricardozanini @hbelmiro This is being labeled as Stale.
@carlesarnal can you please take a look?
@ricardozanini @hbelmiro This is being labeled as Stale.
Closed by https://github.com/quarkiverse/quarkus-openapi-generator/pull/1015 (waiting new release)