OpenAPITools / OpenAPITools/openapi-generator

[BUG][JAVA] Java Spring generator fails to generate working models with multiple inheritance layers

Open
#15,796 0 comments 1 reaction 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?
Description

Hello everyone,

I'm currently upgrading from OpenAPI Generator v5.4.0 to v6.6.0 and I've run into an issue with schemas that define multiple levels of inheritance using two separate discriminators. It seems that for models that have more than one level of inheritance depth the generated Java classes are a bit broken. There are two issues that I have encountered:

  • Child classes don't have all required parameters needed to pass to the parents in the constructor which results in compilation errors.
public class Poodle extends Dog {

  private String hairType;

  /**
   * Default constructor
   * @deprecated Use {@link Poodle#Poodle(String)}
   */
  @Deprecated
  public Poodle() {
    super();
  }

  /**
   * Constructor with only required parameters
   */
  public Poodle(String type) {
    super(race, type); <- race parameter is not a constructor param for the Poodle class nor it is a field of this class
  }
}

public class Dog extends Pet {

  private Integer tails;

  private String race;

  /**
   * Default constructor
   * @deprecated Use {@link Dog#Dog(String, String)}
   */
  @Deprecated
  public Dog() {
    super();
  }

  /**
   * Constructor with only required parameters
   */
  public Dog(String race, String type) {
    super(type);
    this.race = race;
  }
}
  • Grandparent class has too many mappings using @JsonSubTypes. It seems that JsonSubTypes are generated for all classes that inherit from the grandparent class instead only for the explicitly configured classes using the mapping property in the discriminator. I would expect only the first two mappings to appear (CAT and DOG). Parent classes have their @JsonSubTypes set properly.
@JsonIgnoreProperties(
  value = "type", // ignore manually set type, it will be automatically generated by Jackson during serialization
  allowSetters = true // allows the type to be set during deserialization
)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
@JsonSubTypes({
  @JsonSubTypes.Type(value = Cat.class, name = "CAT"),
  @JsonSubTypes.Type(value = Dog.class, name = "DOG"),
  @JsonSubTypes.Type(value = Labrador.class, name = "Labrador"),
  @JsonSubTypes.Type(value = MaineCoon.class, name = "MaineCoon"),
  @JsonSubTypes.Type(value = Persian.class, name = "Persian"),
  @JsonSubTypes.Type(value = Poodle.class, name = "Poodle")
})

@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2023-06-09T14:33:49.208185800+02:00[Europe/Warsaw]")
public class Pet {

  private String name;

  private String type;

  /**
   * Default constructor
   * @deprecated Use {@link Pet#Pet(String)}
   */
  @Deprecated
  public Pet() {
    super();
  }

  /**
   * Constructor with only required parameters
   */
  public Pet(String type) {
    this.type = type;
  }
}

Using v5.4.0 JsonSubTypes are properly set

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type", visible = true)
@JsonSubTypes({
  @JsonSubTypes.Type(value = Cat.class, name = "CAT"),
  @JsonSubTypes.Type(value = Dog.class, name = "DOG"),
})
@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2023-06-09T14:40:51.917945+02:00[Europe/Warsaw]")
public class Pet   {

  @JsonProperty("name")
  private String name;

  @JsonProperty("type")
  private String type;
}

I'm able to circumvent the first issue using --additional-properties=generatedConstructorWithRequiredArgs=false as a workaround although it would be nice to have all the constructors. Second one is something that I could not work out.

openapi-generator version

I'm using version 6.6.0, previously I've used 5.4.0 and this structure worked as expected.

OpenAPI declaration file content or url

Yaml

Generation Details

Generated using openapi generator gradle plugin

Steps to reproduce
Related issues/PRs

#15148

Suggest a fix

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 with the linked YAML reproduction and the generated Pet, Dog, and Poodle classes, then compare Java Spring output from Generator 6.6.0 with 5.4.0. Review the Gradle plugin generation path and related issue #15148; done means the inheritance constructors compile and the grandparent's @JsonSubTypes contains only the configured mappings.

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
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.