OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.49k stars 6.5k forks source link

[BUG][JAVA] Regression in v7.6.0 creating incorrect `generateName=spring` code #18739

Open alexec opened 4 months ago

alexec commented 4 months ago

Bug Report Checklist

Description

I've just upgrade from v6.2.1 to v7.6.0 and I've encountered a problem where a path parameter that is a string has generated code that is an Object (incorrect) when in v6.2.1 it was a String (correct).

openapi-generator version

v7.6.0, this is a regression.

OpenAPI declaration file content or url
  /v1/documents/{id}:
    get:
      summary: Get document
      description: Get a document by providing its unique ID in the path parameter.
      operationId: getDocument
      tags:
        - documents
      parameters:
        - description: The unique identifier of the document
          name: id
          required: true
          in: path
          schema:
            # IDs MUST be strings.
            type: string
            # 36 is the size of a RFC4122 UUID.
            maxLength: 36
          example: abc123

            <plugin>
                <groupId>org.openapitools</groupId>
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <version>7.6.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <inputSpec>${project.basedir}/api/openapi/openapi.yaml</inputSpec>
                            <skipValidateSpec>true</skipValidateSpec>
                            <generatorName>spring</generatorName>
                            <generateApis>true</generateApis>
                            <generateApiDocumentation>false</generateApiDocumentation>
                            <generateModels>true</generateModels>
                            <generateModelDocumentation>false</generateModelDocumentation>
                            <supportingFilesToGenerate>false</supportingFilesToGenerate>
                            <configOptions>
                                <modelPackage>{{packageName}}.models</modelPackage>
                                <apiPackage>{{packageName}}.rest.controllers</apiPackage>
                                <!-- do not generate implementations -->
                                <interfaceOnly>true</interfaceOnly>
                                <!-- do not annotate with custom nullable annotation -->
                                <openApiNullable>false</openApiNullable>
                                <!-- don't generate stub implementations, you always must implement them -->
                                <skipDefaultInterface>true</skipDefaultInterface>
                                <!-- generate one interface per tag -->
                                <useTags>true</useTags>
                                <documentationProvider>none</documentationProvider>
                                <useSwaggerUI>false</useSwaggerUI>
                                <useJakartaEe>true</useJakartaEe>
                                <useSpringBoot3>true</useSpringBoot3>
                            </configOptions>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

The incorrect generated code (where id is Object not String:

    ResponseEntity<Void> updateDocument(
        @Size(max = 36)  @PathVariable("id") Object id,
         @Valid @RequestBody(required = false) Document document
    );
Generation Details
mvn generate-sources
Steps to reproduce

This is a internal code base. I'd have to create a new code base to test. This isn't my top priority right now, but I'm I can't be the only person affected.

Related issues/PRs

Old (2022) issue might be related:

https://github.com/OpenAPITools/openapi-generator/issues/9976

Suggest a fix

TODO

alexec commented 4 months ago

This is actually worse than I thought, everything appears to be an object:

public class Document {

  private Object id = null;

  private Object createdAt = null;

  private Object username = null;

  private Object content = null;
wing328 commented 4 months ago

can you please share the full spec for us to troubleshoot the issue?

alexec commented 4 months ago

openapi: 3.1.0
info:
  title: Documents API

  description: |
    The Documents API allows you to manage documents in a simple and efficient way. 
    It provides various operations such as listing, creating, updating, and deleting documents. 
    To use the API, you need to authenticate using either BearerAuth or OAuth2. 
    The API supports webhooks for document updates.

    Use cases:

    - Document sharing. You can share documents with other users by providing them with the document ID.
    - Document curation. You can curate documents by updating their content or metadata. The API allows you to query documents based on various criteria such as creation date or user.
  version: 0.1.0
  contact: { }
servers:

  - description: Local development
    url: https://localhost:8443
  - description: QAL
    url: https://service-qal.api.example.com
  - description: E2E
    url: https://service-e2e.api.example.com
  - description: Sandbox
    url: https://service-sandbox.api.example.com
  - description: ProductionX
    url: https://service.api.example.com
tags:
  - name: documents

security:
  - BearerAuth: [ ]
webhooks:

  "namespace.document.updated.v1":
    post:
      requestBody:
        description: Document updated
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/DocumentUpdatedEvent"
      responses:
        "200":
          description: OK
paths:

  /v1/documents:
    get:
      summary: List documents
      description: Returns a list of documents with optional pagination.

      operationId: listDocuments
      tags:
        - documents

      parameters:
        - name: cursor
          description: Pagination cursor
          schema:
            type: string
            maxLength: 64
          in: query
          example: abc123
        - name: limit
          description: The max number of paginated results.
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 100
          example: 100
          in: query
      responses:
        "200":
          description: A list of documents
          content:
            application/json:
              schema:
                $ref: "
              examples:
                ListExample:
                  value:
                    data:
                      - id: abc123
                        created_at: "2023-01-01T00:00:00.000Z"
                        username: whoami
                        content: Hello APIs!
                    metadata:
                      cursor: abc123
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "
              examples:
                ErrorExample:
                  value:
                    code: BAD_REQUEST
                    message: Bad request
    post:
      summary: Create document
      description: Create a document based on the payload.
      operationId: createDocument
      tags:
        - documents
      requestBody:
        content:
          application/json:
            schema:
              $ref: "
      responses:
        "201":
          description: Created
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                ErrorExample:
                  value:
                    code: BAD_REQUEST
                    message: Bad request
  /v1/documents/{id}:
    get:
      summary: Get document
      description: Get a document by providing its unique ID in the path parameter.
      operationId: getDocument
      tags:
        - documents
      parameters:
        - description: The unique identifier of the document
          name: id
          required: true
          in: path
          schema:

            type: string

            maxLength: 36
          example: abc123
      responses:
        "200":
          description: The document
          content:
            application/json:
              schema:
                $ref: "
              examples:
                GetExample:
                  value:
                    id: abc123
                    created_at: "2023-01-01T00:00:00.000Z"
                    username: whoami
                    content: Hello APIs!
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "
              examples:
                ErrorExample:
                  value:
                    code: BAD_REQUEST
                    message: Bad request
    put:
      summary: Update document
      description: Update an existing document by providing its unique ID in the path parameter and the updated information in the request body.
      operationId: updateDocument
      tags:
        - documents
      parameters:
        - description: The unique identifier of the document
          name: id
          required: true
          in: path
          schema:
            type: string
            maxLength: 36
          example: abc123
      requestBody:
        content:
          application/json:
            schema:
              $ref: "
            examples:
              PutExample:
                value:
                  id: abc123
                  created_at: "2023-01-01T00:00:00.000Z"
                  username: whoami
                  content: Hello APIs!
      responses:
        "204":
          description: Updated
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    delete:
      summary: Delete document
      description: Delete a specific document by providing its unique ID in the path parameter.
      operationId: deleteDocument
      tags:
        - documents
      parameters:
        - description: The unique identifier of the document
          name: id
          required: true
          in: path
          schema:
            type: string
            maxLength: 36
          example: abc123
      responses:
        "204":
          description: Deleted
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                ErrorExample:
                  value:
                    code: BAD_REQUEST
                    message: Bad request
components:

  securitySchemes:

    BearerAuth:
      type: http
      scheme: bearer
    BasicAuth:
      type: http
      scheme: basic
  schemas:

    Error:
      description: An error response which may be shown to the end user
      type: object
      required:
        - code
      properties:
        code:
          description: Machine-readable code
          type: string
          maxLength: 64

          pattern: ^[A-Z][A-Z0-9_]*$
          example: BAD_REQUEST
        message:
          description: Human-readable message
          type: string
          maxLength: 256
          example: Bad request

        detail:
          description: Detailed human-readable information
          type: string
          maxLength: 4096
          example: The request body was malformed.
      example:
        code: BAD_REQUEST
        message: Bad request
    ListMetaData:
      description: Metadata for paginated responses
      type: object
      required:
        - cursor
      properties:
        cursor:
          description: The pagination cursor
          type: string
          maxLength: 64
          example: abc123
      example:
        cursor: abc123

    Document:
      description: A document
      type: object
      required:
        - content
      properties:
        id:
          description: The unique identifier of the document
          type: string
          example: abc123
          maxLength: 36

        created_at:
          description: When the document was created
          type: string

          format: date-time
          example: 2023-01-01T00:00:00.000Z
        username:
          description: The username of the document creator
          type: string
          maxLength: 64
          example: whoami
        content:
          description: The content of the document
          type: string
          maxLength: 256
          example: Hello APIs!
      example:
        id: abc123
        created_at: "2023-01-01T00:00:00.000Z"
        username: whoami
        content: Hello APIs!

    ListDocumentsResponse:
      description: A list of documents with metadata
      required:
        - data
        - metadata
      properties:
        data:
          description: A list of documents
          type: array
          items:
            $ref: "
        metadata:
          $ref: "
      example:
        data:
          - id: abc123
            created_at: "2023-01-01T00:00:00.000Z"
            username: whoami
            content: Hello APIs!
        metadata:
          cursor: abc123

    DocumentUpdatedEvent:
      description: A document updated event
      required:
        - specversion
        - source
        - id
        - type
        - datacontenttype
        - data
      properties:
        specversion:
          description: The version of the CloudEvents specification. Always 1.0.
          type: string
          example: "1.0"
        source:
          description: The source of the event.
          type: string
          example: example
        id:
          description: The unique identifier of the event.
          type: string
          example: abc123

        type:
          description: The type of the event.
          type: string
          example: namespace.document.updated.v1
        datacontenttype:
          description: The content type of the data field. Always application/json.
          type: string
          example: application/json
        data:
          $ref: "#/components/schemas/Document"
      example:
        specversion: "1.0"
        source: example
        id: abc123
        type: namespace.document.updated.v1
        datacontenttype: application/json
        data:
          id: abc123
          created_at: "2023-01-01T00:00:00.000Z"
          username: whoami
          content: Hello APIs!