OpenAPITools / OpenAPITools/openapi-generator

[BUG][SPRING-JAVA] Wrong generation result

Open
#18,710 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

I identified several common tags for the API in the specification file

openapi-generator version

7.5.0

OpenAPI declaration file content or url
---
openapi: 3.0.0
info:
  title: Catalog API
  version: 1.0.0
tags:
  - name: Material
    description: List of All materials
  - name: Material Type
    description: List of All material types
  - name: Material Group
    description: List of All material groups
  - name: Status
    description: List of All statuses
  - name: Measurement Unit
    description: List of All measurement units
  - name: Measuring Point
    description: List of All measuring points
  - name: Document
    description: List of All documents
  - name: Document Type
    description: List of All document types

paths:
  /catalog/v1/api/material-types/{id}:
    get:
      tags:
        - Material Type
      description: Get Material Type by id
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MaterialTypeEntity'
  /catalog/v1/api/material-types:
    get:
      tags:
        - Material Type
      description: Get Material Types
      parameters:
        - name: pageNumber
          in: query
          description: page number of the list
          required: false
          schema:
            type: integer
        - name: pageSize
          in: query
          description: amount of elements on a page
          required: false
          schema:
            type: integer
        - name: sort
          in: query
          description: sort parameter
          required: false
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Page'
                  - type: object
                    properties:
                      content:
                        type: array
                        items:
                          $ref: '#/components/schemas/MaterialTypeEntity'
  /catalog/v1/api/material-groups/{id}:
    get:
      tags:
        - Material Group
      description: Get Material Group by id
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MaterialGroupEntity'
  /catalog/v1/api/material-groups:
    get:
      tags:
        - Material Group
      description: Get Material Groups
      parameters:
        - name: pageNumber
          in: query
          description: page number of the list
          required: false
          schema:
            type: integer
        - name: pageSize
          in: query
          description: amount of elements on a page
          required: false
          schema:
            type: integer
        - name: sort
          in: query
          description: sort parameter
          required: false
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Page'
                  - type: object
                    properties:
                      content:
                        type: array
                        items:
                          $ref: '#/components/schemas/MaterialGroupEntity'
  /catalog/v1/api/materials/{id}:
    get:
      tags:
        - Material
      description: Get Material by id
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MaterialEntity'
  /catalog/v1/api/materials:
    get:
      x-spring-paginated: true
      tags:
        - Material
      description: Get list of Materials
      parameters:
        - name: id
          in: query
          description: id of the required material
          required: false
          schema:
            type: string
        - name: statusId
          in: query
          description: exception status of the required material
          required: false
          schema:
            type: string
        - name: pageNumber
          in: query
          description: page number of the list
          required: false
          schema:
            type: integer
        - name: pageSize
          in: query
          description: amount of elements on a page
          required: false
          schema:
            type: integer
        - name: sort
          in: query
          description: sort parameter
          required: false
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Page'
                  - type: object
                    properties:
                      content:
                        type: array
                        items:
                          $ref: '#/components/schemas/MaterialEntity'
    post:
      tags:
        - Material
      description: Create temporal material
      requestBody:
        description: A JSON object of a temporal material
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TemporalMaterialRequest'
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TemporalMaterialResponse'
  /catalog/v1/api/statuses/{id}:
    get:
      tags:
        - Status
      description: Get Status by id
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StatusEntity'
  /catalog/v1/api/statuses:
    get:
      x-spring-paginated: true
      tags:
        - Status
      description: Get list of All statuses
      parameters:
        - name: pageNumber
          in: query
          description: page number of the list
          required: false
          schema:
            type: integer
        - name: pageSize
          in: query
          description: amount of elements on a page
          required: false
          schema:
            type: integer
        - name: category
          in: query
          description: category of the status
          required: true
          schema:
            type: string
        - name: sort
          in: query
          description: sort parameter
          required: false
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Page'
                  - type: object
                    properties:
                      content:
                        type: array
                        items:
                          $ref: '#/components/schemas/StatusEntity'
  /catalog/v1/api/measurement-units/{id}:
    get:
      tags:
        - Measurement Unit
      description: Get Measurement Unit by id
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MeasurementUnitEntity'
  /catalog/v1/api/measurement-units:
    get:
      x-spring-paginated: true
      tags:
        - Measurement Unit
      description: Get list of All Measurement Units
      parameters:
        - name: pageNumber
          in: query
          description: page number of the list
          required: false
          schema:
            type: integer
        - name: pageSize
          in: query
          description: amount of elements on a page
          required: false
          schema:
            type: integer
        - name: sort
          in: query
          description: sort parameter
          required: false
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Page'
                  - type: object
                    properties:
                      content:
                        type: array
                        items:
                          $ref: '#/components/schemas/MeasurementUnitEntity'
  /catalog/v1/api/measuting-points/{id}:
    get:
      tags:
        - Measuring Point
      description: Get Measuring Point by id
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MeasuringPointEntity'
  /catalog/v1/api/measuting-points:
    get:
      x-spring-paginated: true
      tags:
        - Measuring Point
      description: Get list of All Measuring Points
      parameters:
        - name: pageNumber
          in: query
          description: page number of the list
          required: false
          schema:
            type: integer
        - name: pageSize
          in: query
          description: amount of elements on a page
          required: false
          schema:
            type: integer
        - name: sort
          in: query
          description: sort parameter
          required: false
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Page'
                  - type: object
                    properties:
                      content:
                        type: array
                        items:
                          $ref: '#/components/schemas/MeasuringPointEntity'
  /catalog/v1/api/document-types/{id}:
    get:
      tags:
        - Document Type
      description: Get Document Type by id
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentTypeEntity'
  /catalog/v1/api/document-types:
    get:
      x-spring-paginated: true
      tags:
        - Document Type
      description: Get list of All Document Types
      parameters:
        - name: pageNumber
          in: query
          description: page number of the list
          required: false
          schema:
            type: integer
        - name: pageSize
          in: query
          description: amount of elements on a page
          required: false
          schema:
            type: integer
        - name: sort
          in: query
          description: sort parameter
          required: false
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Page'
                  - type: object
                    properties:
                      content:
                        type: array
                        items:
                          $ref: '#/components/schemas/DocumentTypeEntity'
  /catalog/v1/api/documents/{id}:
    get:
      tags:
        - Document
      description: Get Document by id
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentEntity'
  /catalog/v1/api/documents:
    get:
      tags:
        - Document
      description: Get list of All Documents
      parameters:
        - name: search
          in: query
          required: false
          schema:
            type: string
        - name: techPlace
          in: query
          required: false
          schema:
            type: string
        - name: documentKind
          in: query
          required: false
          schema:
            type: string
        - name: documentTypeId
          in: query
          required: false
          schema:
            type: string
        - name: pageNumber
          in: query
          description: page number of the list
          required: false
          schema:
            type: integer
        - name: pageSize
          in: query
          description: amount of elements on a page
          required: false
          schema:
            type: integer
        - name: sort
          in: query
          description: sort parameter
          required: false
          schema:
            type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Page'
                  - type: object
                    properties:
                      content:
                        type: array
                        items:
                          $ref: '#/components/schemas/DocumentEntity'
    post:
      tags:
        - Document
      description: Create document
      requestBody:
        description: An object of a document
        content:
          multipart/form-data:
            schema:
              type: object
              required: [ file,documentKind,documentTypeId, tm/eoCode ]
              properties:
                file:
                  type: array
                  items:
                    type: string
                    format: binary
                documentKind:
                  type: string
                documentTypeId:
                  type: string
                tm/eoCode:
                  type: string
      responses:
        "200":
          description: ""
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentEntity'



components:
  schemas:
    Page:
      type: object
      properties:
        content:
          type: array
          items:
            type: object
        pageable:
          $ref: '#/components/schemas/Pageable'
        last:
          type: boolean
        totalElements:
          type: integer
        totalPages:
          type: integer
        first:
          type: boolean
        numberOfElements:
          type: integer
        empty:
          type: boolean
    Pageable:
      type: object
      properties:
        pageSize:
          type: integer
        pageNumber:
          type: integer
        sort:
          $ref: '#/components/schemas/Sort'
    Sort:
      type: object
      properties:
        sorted:
          type: boolean
        unsorted:
          type: boolean
    MaterialTypeEntity:
      required:
        - id
        - name
      properties:
        id:
          type: string
        name:
          type: string
      type: object
    MaterialGroupEntity:
      required:
        - id
        - name
      properties:
        id:
          type: string
        name:
          type: string
      type: object
    MaterialEntity:
      required:
        - id
        - name
        - price
        - measurementUnit
        - amount
        - materialTypeId
        - materialType
        - materialGroupId
        - materialGroup
      properties:
        id:
          type: string
        name:
          type: string
        price:
          type: number
        measurementUnit:
          $ref: '#/components/schemas/MeasurementUnitEntity'
        amount:
          type: integer
        materialTypeId:
          type: string
        materialType:
          $ref: '#/components/schemas/MaterialTypeEntity'
        materialGroupId:
          type: string
        materialGroup:
          $ref: '#/components/schemas/MaterialGroupEntity'
      type: object
    TemporalMaterialRequest:
      required:
        - name
        - price
        - measurementUnitId
        - amount
      properties:
        name:
          type: string
        price:
          type: number
        measurementUnitId:
          type: string
        amount:
          type: integer
      type: object
    TemporalMaterialResponse:
      required:
        - id
        - name
        - price
        - measurementUnit
        - amount
      properties:
        id:
          type: string
        name:
          type: string
        price:
          type: number
        measurementUnit:
          $ref: '#/components/schemas/MeasurementUnitEntity'
        amount:
          type: integer
      type: object
    StatusEntity:
      required:
        - id
        - name
      properties:
        id:
          type: string
        name:
          type: string
      type: object
    MeasurementUnitEntity:
      required:
        - id
        - name
      properties:
        id:
          type: string
        name:
          type: string
      type: object
    MeasuringPointEntity:
      required:
        - id
        - measuringPointKind
        - name
        - position
        - description
        - codeGroup
        - nodeId
        - type
      properties:
        id:
          type: string
        measuringPointKind:
          type: string
        name:
          type: string
        position:
          type: string
        description:
          type: string
        codeGroup:
          type: string
        nodeId:
          type: string
        type:
          type: string
      type: object
    DocumentTypeEntity:
      required:
        - id
        - name
      properties:
        id:
          type: string
        name:
          type: string
      type: object
    DocumentEntity:
      required:
        - id
        - name
        - status
        - date
        - documentKind
        - documentType
        - tm/eoCode
        - link
      properties:
        id:
          type: string
        name:
          type: string
        status:
          $ref: '#/components/schemas/StatusEntity'
        date:
          type: string
        documentKind:
          type: string
        documentType:
          $ref: '#/components/schemas/DocumentTypeEntity'
        tm/eoCode:
          type: string
        link:
          type: string
      type: object

Generation Details

I use configuration in the mvn pom.xml

<plugin>
                <groupId>org.openapitools</groupId>
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <version>7.5.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <skipValidateSpec>false</skipValidateSpec>
                            <inputSpec>./src/main/resources/catalogAPI.yaml</inputSpec>
                            <generatorName>spring</generatorName>
                            <importMappings>
                                <importMapping>Pageable=org.springframework.data.domain.Pageable</importMapping>
                                <importMapping>Page=org.springframework.data.domain.PageImpl</importMapping>
                                <importMapping>Sort=org.springframework.data.domain.Sort</importMapping>
                            </importMappings>
                            <configOptions>
                                <useSpringBoot3>true</useSpringBoot3>
                                <openApiNullable>false</openApiNullable>
                                <interfaceOnly>true</interfaceOnly>
                            </configOptions>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

And I see result of

@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.5.0")
@Validated
@Tag(name = "Document Type", description = "List of All document types")
public interface CatalogApi {

And it makes for every request additional tag of Document Type when only several requests belong to it

Steps to reproduce

execution of mvn clean package

Related issues/PRs

Didn't found any

Suggest a fix

I didn't find workaround for that

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing generation with the inline OpenAPI declaration using OpenAPI Generator 7.5.0 and the Spring Java generator. Compare the generated result with the intended handling of the declared tags, then document the actual and expected output and verify the corrected generation behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, openapi, spring
Domain
api, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.