openapi-generator: [BUG] [JAVA] Java generation of 'extra' class with allOf

Description

I am using the pet store example to create java classes with inheritance. In the newest release (4.0.1) I found a bug. When I generate code with the OpenApi declaration file it generates an extra class.

image

The class ‘CatAllOf’ I did not expect. It looks the same as ‘Cat’ except that it does not extends Pet.

OpenAPI declaration file:

openapi: 3.0.1
info:
  title: Article Event
  description: 'Article Event schema'
  version: 1.0.0
paths:
  /:
    get:
      responses:
        200:
          description: OK
          content: {}
components:
  schemas:
    TextChunk:
      type: object
      discriminator:
        propertyName: textChunkType
      properties:
        parent:
          type: string
    Dog:
      allOf: 
      - $ref: '#/components/schemas/TextChunk'
      - type: object
    Cat:
      allOf:
      - $ref: '#/components/schemas/TextChunk'
      - type: object
        properties:
          bark:
            type: string

openapi-generator version I used the gradle plugin with version 4.0.1.

older version I tested the same thing in the version 4.0.0-beta3 and there I did net see the ‘extra’ class. In other words, I got the expected behavior. It seems the bug was introduced with the latest release.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 25
  • Comments: 44 (12 by maintainers)

Most upvoted comments

When you change from:

Cat:
      allOf:
      - $ref: '#/components/schemas/TextChunk'
      - type: object
        properties:
          bark:
            type: string

To:

Cat:
   type: object
   properties:
      bark:
         type: string   
   allOf:
      - $ref: '#/components/schemas/TextChunk'
      

So, if additional properties for Cat are added to the root of Cat, then there is no additional class CatAllOf

That’s treated as an inline schema (which can be replaced with $ref to avoid the additional model generation).

This seems to miss the point entirely. Spec authors understand that these are inline schemas and are used precisely “to avoid the additional model generation”. Replacing with a $ref necessitates the creation of the additional model that spec authors wish to avoid.

If users prefer the old way of not generating this inline schema, technically we can add an option to restore the old behaviour.

It seems clear from the number of bugs raised in this area that many users do “prefer the old way”. What I’m really not clear on is:

  1. What benefits there are to “the new way” - i.e. whether it’s worth keeping both ways as options
  2. Where in the codebase I should be looking to patch in order to address the underlying problem

@wing328 That seems like a strange solution to me. Why would I need to ignore files that shouldn’t have been generated in the first place? Also, as I said, the classes are referenced by an unused import from other classes. Deleting the files, breaks the build.

We rely upon inheritance that the v3.x provided

That’s not going to be restored.

You will need to use discriminator for inheritance: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#models-with-polymorphism-support

(Sorry for the bit delay…)

Sure @wing328 we use the discriminator to allow inheritance on model classes be generated (at least in the generator v3.x). But the whole point is that the v4.x does not generate the inheritance in the Java classes. So this is the behavior that was broken and that we would like to recover back.

Aside of that, and as others state, the new generated classes *AllOf.java in v4.x seems not useful at all and pollutes the generated artifact.

Is there any news for the v5.x you mentioned regarding the inheritance issue? Thanks!! 🙏 😃

      - type: object
        properties:
          bark:
            type: string

That’s treated as an inline schema (which can be replaced with $ref to avoid the additional model generation).

If users prefer the old way of not generating this inline schema, technically we can add an option to restore the old behaviour.

We rely upon inheritance that the v3.x provided

That’s not going to be restored.

You will need to use discriminator for inheritance: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#models-with-polymorphism-support

What about using .openapi-generator-ignore (in the output directory) to skip those files from being generated?

@wing328 That seems like a strange solution to me. Why would I need to ignore files that shouldn’t have been generated in the first place? Also, as I said, the classes are referenced by an unused import from other classes. Deleting the files, breaks the build.

Facing the same issue here, where configuring the generator to ignore these AllOf files causes the classes to not compile due to these AllOf classes being imported (even though they’re unused). Using Java here.

Still seeing this as an issue. Interestingly the swagger-codegen doesn’t produce these extra files.

Is there any hope of getting the fix into the main release any time soon? This parser is unusable for any openapi document that uses “allOf”.

It’s been 3 years, this issue is still open. the swagger-codegen doesn’t produce this extra files. But why openapi-generator still produce this extra files?

Could you please give us explanation / insight wether these extra files useful or no @wing328 ?

There’s the same problem with kotlin and kotlin-server (in 5.0.1)

As a workaround I can suggest adding additionalProperties: true to child schema.
For example, below would not generate additional CatAllOf.java

Cat:
   allOf:
   - $ref: '#/components/schemas/TextChunk'
   - type: object
     additionalProperties: true
     properties:
       bark:
         type: string

That works because composed schema (allOf, oneOf, anyOf) that also defines additionalProperties are considered to be a MapSchema and models are not generated for MapSchemas. I haven’t encountered any problems so far with this solution so far, but I have not tested other generators

I’ve just realized that I have been confused on all my previous assertions regarding inheritance. The inheritance is not actually broken and seems never was (I’ve tried again with several generator versions 4.0, 4.02, 4.0.3, 4.1, 4.3.1) and Java inheritance is still fine. So I apologize if I introduced noise. I think other commenter stated the inheritance was broken as well.

So the actual problem is only about the extra unuseful AllOf generated classes (this ones are the ones that has no inheritance, but for the sake of the issue are the ones we want to remove).

The main point is that this pollutes the generated JAR with unnecessary, unused classes, so breaks the point of a sane API artifact.

I’ve just tried using the .openapi-generator-ignore file with **/*AllOf.java in output directory, and as others already said, classes are not generated, BUT the unused imports in other classes (say Cat.java) prevents the code to compile.

Maybe I could hack the POM of my generator (here using openapi-generator-maven-plugin) to remove all ^import.*AllOf;$ using sed or something similar but this is not the right way to go. Could work as a patch at most.

I’m facing this issue as well. But when I have realized the version 4 of generator working this way I asked myself if this was intended or really a weird bug. Could someone clarify it? I was pretty happy with 3.3.4 so I will go back to it for now. I rely on Java inheritance. @wing328

@wing328 why can’t you just have the old behavior? I think a lot of folks are disappointed with the new behavior. We are supposed to make things better not worse.

Thanks!

I’ve filed https://github.com/OpenAPITools/openapi-generator/pull/13498 to improve how the allOf inline schemas are created. Please give it a try as follows:

git clone -b inline-schema-improve3 https://github.com/OpenAPITools/openapi-generator
cd openapi-generator
mvn clean package
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java  -i /var/tmp/your_spec.yaml -o /var/tmp/java/

(if you’re using mvn wrapper that comes with the project, just replace mvn with mvnw (Mac/Linux) or mvnw.cmd (Windows))

I tested with java, csharp-netcore and the result is good - no longer seeing those *AllOf files created.

Since I annotate the @Schema directly in my java code and even generate openapi.yml out of it, I cannot influence the positioning of :allOf ref much (as in the nice hack above 😉 Therefore I created another silly hack class CatAllOf to please the non-understandable import without being used in the generated class code at all, just like:

package pet.model;
/**
 * Just an unnecessary generated "import" compiler workaround class
 * @see <a href="https://github.com/OpenAPITools/openapi-generator/issues/3100">*AllOf imports</a>
 * @see Cat
 */
@Deprecated
public class CatPlaceAllOf {}

To OpenApi developers:

  • I suggest you clean up generated code within the plugin (for e.g. like IntellJ’s feature to remove unneccessary imports), that would do it in that case (as a quick fix)
  • of course such usage for continuous quality comparison of generated code, would be more handy within your unit-tests
  • I can follow the missunderstandings above, but I did not find any explanation, whether it is ok to remove the “silly import” or if there is another fault in my annotation or in the generated code

Thanks for fixing soon and appreciate your work!


I am not sure if I understood the inheritance spec well, but my Java implementation looks as follows:

io.swagger.v3.oas.annotations.media.Schema;

@Schema(name = "Pet", 
        discriminatorProperty = "petType",
        subTypes = {Cat.class, Dog.class})
public /*TODO make abstract */ class  Pet {
  @Schema(type = "string", required = true)
  String petType;
}
@Schema(name = "Cat",allOf = Pet.class)
public class Cat extends Pet {..}
@Schema(name = "Dog",allOf = Pet.class)
public class Dog extends Pet {..}

Besides I am using:

<plugin>
                <groupId>org.openapitools</groupId>
                <!-- see https://openapi-generator.tech/docs/generators/java/ -->
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <version>5.1.0</version>
..

Very nice Workaround @milczarekIT I have tested it with openapi-generator version 5.0.0-beta2.

Does anyone know if this behavior is intended? I could not find any documentation for this.

Can someone explain why these *AllOf.java files are being generated in the first place?

Good news to listen about restoring to the original behavior. We rely upon inheritance that the v3.x provided, i.e. class Cat extends Animal (or as per OP example Cat extends TextChunk), which seems missing in v4.x.

Are there any news about this? Is it on the roadmap for the upcoming 5.x release?

Even the examples have this issue. For example, the Java RestEasy example has several files with AllOf, like this one https://github.com/OpenAPITools/openapi-generator/blob/v4.3.0/samples/client/petstore/java/resteasy/src/main/java/org/openapitools/client/model/CatAllOf.java

These files are not used at all by the API. The only reference to this class is an unused import from Cat and the testcase CatAllOfTest. The same is true for the other AllOf classes.

Guys, I’d be happy to help if there’s any way I can, but this is a huge blocker for me. Any hope of getting a fix soon?

@milczarekIT Nice workaround. It allowed me to generate the intended client code without the dummy classes (I’m using csharp-netcore 5.0.0-SNAPSHOT).

Does anyone know if this is still valid OpenAPI syntax though? I haven’t found any official examples with this structure.