question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] Code is not generated correctly for allOf.

See original GitHub issue
Description

I am not able to get the following definition to generate java or type script correctly.

Have tried with 4.3.1. In Java, RealCommand is generated as

public class RealCommand extends Command {
...
}

Notice that I did not specify a discriminator in Command. I expect this definition to generate a composition of Command and RealCommand.java and that Command.java would not be generated. Command.java file is not generated, but it is also expected as a base class in RealCommand.java, so this does not compile.

There should not be any inheritance here because there is no discriminator.

openapi-generator version

4.3.1

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • What’s the version of OpenAPI Generator used? - 4.3.1
  • Have you search for related issues/PRs? - yes
  • What’s the actual output vs expected output?
  • [Optional] Bounty to sponsor the fix (example)
OpenAPI declaration file content or url
swagger: "2.0"
info:
  title: Test Command model generation
  description: Test Command model generation
  version: 1.0.0
host: localhost:8080
schemes:
  - https
definitions:
  Command:
    title: Command
    description: The base object for all command objects.
    x-swagger-router-model: CommandDto
    type: object
    properties: {}
  RealCommand:
    title: RealCommand
    description: The real command.
    x-swagger-router-model: RealCommandDto
    allOf:
      - $ref: '#/definitions/Command'
  ApiError:
    description: The base object for API errors.
    x-swagger-router-model: ApiGeneralException
    type: object
    required:
    - code
    - message
    properties:
      code:
        description: The error code. Usually, it is the HTTP error code.
        type: string
        readOnly: true
      message:
        description: The error message.
        type: string
        readOnly: true
    title: ApiError

parameters:
  b_real_command:
    name: real_command
    in: body
    description: A payload for executing a real command.
    required: true
    schema:
      $ref: '#/definitions/RealCommand'

paths:
  /execute:
    post:
      produces: []
      x-swagger-router-controller: FakeController
      operationId: executeRealCommand
      parameters:
      - name: real_command
        in: body
        description: A payload for executing a real command.
        required: true
        schema:
          $ref: '#/definitions/RealCommand'
      responses:
        '204':
          description: Successful request. No content returned.
        '400':
          description: Bad request.
          schema:
            $ref: '#/definitions/ApiError'
        '404':
          description: Not found.
          schema:
            $ref: '#/definitions/ApiError'
        default:
          description: Unknown error.
          schema:
            $ref: '#/definitions/ApiError'
Command line used for generation

openapi-generator generate -i test.yaml -g java --library jersey2 -o java --additional-properties legacyDiscriminatorBehavior=false

Steps to reproduce
Related issues/PRs

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

Suggest a fix

I see that maybe ModelUtils#isFreeFormObject() should also check to see if the object is used in an allOf, anyOf, or oneOf in any other schema in the definition. But this still does not explain why RealCommand is using Command as a base class.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:17 (11 by maintainers)

github_iconTop GitHub Comments

6reactions
gwre-ivancommented, Apr 1, 2021

There is definitely a use-case for being able to express commonalities across multiple generated types, as per comments on this ticket (and other tickets as well).

We have some code that fills / transforms / processes generated data types, and we want to generalize this code in cases where multiple data types share some common structure. I understand there is a some subtlety around “inheritance” and what does it mean for data types. Especially, as it was mentioned above, when you have “multiple” inheritance. I do find “single parent inheritance” (as in this ticket to be quite convenient, but I do agree that it might fail short in more complex scenarios (like multiple allOf).

I mildly disagree with the suggestion that one can just simply add discriminators and be done with it. In our use-cases, we don’t need to express any kind of “inheritance”. My main issue with “just add the discriminators” is that it drives long-term, high cost decisions (structure of one’s APIs / data types) via minutiae of a particular implementation. Clients of my API should not care that in my service implementation I have switched from version 4.x to 5.x of the generator.

Also, rewriting code to introduce a bunch of copy-paste just because new implementation of the generator does not allow us to generalize code in the language of our choice (Java) is also less than ideal. However, I think there is a solution that might work well here: it is possible to extend generator in a way such that it can express commonalities through “interfaces”.

I created a proof-of-concept in my fork where I add support for x-trait: true vendor extension. This extension causes two things:

  1. Java interface is generated for the data type x-trait is declared on (similarly to how POJOs are generated, but without function bodies).
  2. For each data type which directly or indirectly “extends” data type with x-trait (“extends” via allOf references), it adds the interface generated for the x-trait data type to the list of interfaces POJO implements (via x-implements).

It works well for our case. Actually, for Java generator (but not Spring one) it seems like you can manually do those “traits” via x-implements vendor annotation. The main drawback, though, is that you’ll have to manually declare every single common accessor you care about (whereas in my implementation, it is done automatically for x-trait).

What do you think?

1reaction
Kenjeecommented, Aug 19, 2020

i have more less same problem i switched from 4.3.0 to 4.3.1 and since 4.3.1 a simple allOf definition does not generate X extends Y anymore

i put and example project into https://github.com/Kenjee/hello-world << simple maven code generation Readme explains all in details

but using same swagger definition with swagger.io and openapi-generator 4.3.0 generates SubscriptionResponse extends Response but with 4.3.1 it does not anymore

i also was reading https://swagger.io/docs/specification/data-models/inheritance-and-polymorphism/ but i stay with “allOf” should be enough, i dont get the need “discriminator”!

would be nice to get help and how to integrate the “discriminator” to get simple response object generated in the old way.

Why i raise this question: We have a couple of generics in place, so each response is “Response” with 2 fields but some times there is an inhertitad class with more details.

UPDATE: solved by simply adding “discriminator” (feels not correct but works)

Read more comments on GitHub >

github_iconTop Results From Across the Web

if / else errors - learn how to fix these - Codecademy
I've been stuck on 6/9 for an hour with a syntax error that I have not been able to find an answer to....
Read more >
Issues - SonarQube Documentation
While running an analysis, SonarQube raises an issue every time a piece of code breaks a coding rule.
Read more >
Open API generator allOf not generating model correctly
I want to generate our models based on an Openapi spec 3.0 yml definition. In my spec I have a definition using allOf...
Read more >
Known issues with Android Studio and Android Gradle Plugin
Manifest class with custom permission strings is no longer generated by default: If you want to generate the class, set android.generateManifestClass = true...
Read more >
Detect errors in formulas - Microsoft Support
It is not an exhaustive list of methods for correcting every possible formula error. For help on specific errors, you can search for...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found