Skip to content

[BUG][Kotlin][kotlin-spring] Multi-level inheritance doesn't work #18206

@taviLaies

Description

@taviLaies

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

When using multi-level inheritance, the kotlin-spring generator produces non-compiling code.

> Task :compileKotlin FAILED
e: .../src/main/kotlin/org/openapitools/model/BigDog.kt: (21, 1): Function 'component1' generated for the data class conflicts with member of supertype 'Dog'
e: .../src/main/kotlin/org/openapitools/model/BigDog.kt: (21, 1): Function 'component2' generated for the data class conflicts with member of supertype 'Dog'
e: .../src/main/kotlin/org/openapitools/model/BigDog.kt: (21, 1): Function 'component3' generated for the data class conflicts with member of supertype 'Dog'
e: .../src/main/kotlin/org/openapitools/model/BigDog.kt: (31, 32): 'breed' in 'Dog' is final and cannot be overridden
e: .../src/main/kotlin/org/openapitools/model/BigDog.kt: (32, 5): This type is final, so it cannot be inherited from
e: .../src/main/kotlin/org/openapitools/model/BigDog.kt: (32, 5): This type has a constructor, and thus must be initialized here

It's especially unfortunate because Java does support this. We must use mechanisms that work across Java & Kotlin and therefore we have to go with the least common denominator preventing us from using multi-level polymorphism.

openapi-generator version
% openapi-generator --version
openapi-generator-cli 7.0.1
  commit : 5b720de
  built  : -999999999-01-01T00:00:00+18:00
  source : https://github.com/openapitools/openapi-generator
  docs   : https://openapi-generator.tech/
OpenAPI declaration file content or url
openapi: 3.0.0
info:
  title: Sample API
  description: API description in Markdown.
  version: 1.0.0
paths:
  /animals:
    get:
      summary: Returns all animals.
      description: Optional extended description in Markdown.
      responses:
        200:
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Animal'
components:
  schemas:
    Dog:
      allOf:
        - $ref: '#/components/schemas/Animal'
        - type: object
          properties:
            breed:
              type: string
    Cat:
      allOf:
        - $ref: '#/components/schemas/Animal'
        - type: object
          properties:
            breed:
              type: string
    BigDog:
      allOf:
        - $ref: '#/components/schemas/Dog'
        - type: object
          required:
            - dogType
          properties:
            dogType:
              type: string
            declawed:
              type: boolean
    Animal:
      type: object
      discriminator:
        propertyName: className
      required:
        - className
      properties:
        className:
          type: string
        color:
          type: string
          default: red
Generation Details
openapi-generator generate -g kotlin-spring -i spec.yaml --additional-properties documentationProvider=none --additional-properties useSpringBoot3=true
Steps to reproduce
  1. run generation command above
  2. run gradle build
Related issues/PRs

Similar issue has been submitted for Java a long time ago: #3058.

Suggest a fix

Unfortunately Kotlin doesn't support data class inheritance.

So the options I can think of:

  • generate an interface hierarchy and use data classes for the "leaf" DTOs: e.g. interfaces: IAnimal, IDog : IAnimal, data classes: Cat : IAnimal, Dog: IDog, BigDog: IDog not very pretty but most times you work with the DTOs.
  • move away from data classes - use regular classes, however this would prevent usage of data class capabilities (e.g. copy) which I personally find very useful

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions