Skip to content

[BUG] [Spring] [4.3.0] allOf forces inheritance #5876

@ondrakucera

Description

@ondrakucera

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?
  • Have you search for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Bounty to sponsor the fix (example)
Description

When trying to switch from 4.2.3 to 4.3.0 in our existing project, I've noticed different behavior when it comes to allOf. I'm not even sure it's a bug, maybe it's intentional but quickly going through release notes of 4.3.0, I didn't see it mentioned and for me it's even a breaking change (though the fix in our project shouldn't be too hard).

To be brief: when having a structure Foo with a few attributes and a structure Bar referencing allOf Foo and then having additional attributes of its own, with version 4.2.3, attributes of Foo would be just "copied" (or mixed-in) into the Bar class but otherwise Bar would have nothing to do with Foo. With version 4.3.0, Bar extends Foo.

Besides this being slightly unexpected (the specification of Swagger 2.0, which we're currently using, states that "[composition] does not imply a hierarchy between the models", it is a bit inconvenient when using fluent syntax to build objects because methods of Foo return Foo (of course).

If Foo has attributes foo1 and foo2 and Bar has attributes bar1 and bar2, previously it was possible to write

return new Bar().bar1("a").bar2("b").foo1("c").foo2("d");

Now something like this must be done:

Bar bar = new Bar().bar1("a").bar2("b");
bar.setFoo1("c");
bar.setFoo2("d");
return bar;
openapi-generator version

4.3.0

OpenAPI declaration file content or url
swagger: "2.0"
info:
    title: Regression test
    version: "1.0"
paths:
    /bars:
        get:
            responses:
                200:
                    description: Success
                    schema:
                        type: array
                        items:
                            $ref: '#/definitions/Bar'
definitions:
    Foo:
        type: object
        properties:
            foo1:
                type: string
            foo2:
                type: string
    Bar:
        allOf:
            -
                $ref: '#/definitions/Foo'
            -
                type: object
                properties:
                    bar1:
                        type: string
                    bar2:
                        type: string

With 4.3.0, three model classes are created: Bar, BarAllOf, and Foo. Interesting parts of the files are:

Bar.java:

public class Bar extends Foo  {
  @JsonProperty("bar1")
  private String bar1;
  @JsonProperty("bar2")
  private String bar2;

  public Bar bar1(String bar1) {
    this.bar1 = bar1;
    return this;
  }

  /**
   * Get bar1
   * @return bar1
  */
  @ApiModelProperty(value = "")
  public String getBar1() {
    return bar1;
  }
  public void setBar1(String bar1) {
    this.bar1 = bar1;
  }
  public Bar bar2(String bar2) {
    this.bar2 = bar2;
    return this;
  }
  /**
   * Get bar2
   * @return bar2
  */
  @ApiModelProperty(value = "")
  public String getBar2() {
    return bar2;
  }
  public void setBar2(String bar2) {
    this.bar2 = bar2;
  }
  ...
}

BarAllOf.java:

public class BarAllOf   {
  @JsonProperty("bar1")
  private String bar1;
  @JsonProperty("bar2")
  private String bar2;

  public BarAllOf bar1(String bar1) {
    this.bar1 = bar1;
    return this;
  }

  /**
   * Get bar1
   * @return bar1
  */
  @ApiModelProperty(value = "")
  public String getBar1() {
    return bar1;
  }
  public void setBar1(String bar1) {
    this.bar1 = bar1;
  }
  public BarAllOf bar2(String bar2) {
    this.bar2 = bar2;
    return this;
  }
  /**
   * Get bar2
   * @return bar2
  */
  @ApiModelProperty(value = "")
  public String getBar2() {
    return bar2;
  }
  public void setBar2(String bar2) {
    this.bar2 = bar2;
  }
  ...
}

Foo.java:

public class Foo   {
  @JsonProperty("foo1")
  private String foo1;

  @JsonProperty("foo2")
  private String foo2;

  public Foo foo1(String foo1) {
    this.foo1 = foo1;
    return this;
  }

  /**
   * Get foo1
   * @return foo1
  */
  @ApiModelProperty(value = "")
  public String getFoo1() {
    return foo1;
  }
  public void setFoo1(String foo1) {
    this.foo1 = foo1;
  }
  public Foo foo2(String foo2) {
    this.foo2 = foo2;
    return this;
  }
  /**
   * Get foo2
   * @return foo2
  */
  @ApiModelProperty(value = "")
  public String getFoo2() {
    return foo2;
  }
  public void setFoo2(String foo2) {
    this.foo2 = foo2;
  }
  ...
}

With version 4.2.3, the same three model classes are generated. Foo and BarAllOf have pretty much the same contents (as with version 4.3.0) but this is how Bar.java looks like:

public class Bar   {
  @JsonProperty("foo1")
  private String foo1;

  @JsonProperty("foo2")
  private String foo2;

  @JsonProperty("bar1")
  private String bar1;

  @JsonProperty("bar2")
  private String bar2;

  public Bar foo1(String foo1) {
    this.foo1 = foo1;
    return this;
  }

  /**
   * Get foo1
   * @return foo1
  */
  @ApiModelProperty(value = "")
  public String getFoo1() {
    return foo1;
  }
  public void setFoo1(String foo1) {
    this.foo1 = foo1;
  }
  public Bar foo2(String foo2) {
    this.foo2 = foo2;
    return this;
  }
  /**
   * Get foo2
   * @return foo2
  */
  @ApiModelProperty(value = "")
  public String getFoo2() {
    return foo2;
  }
  public void setFoo2(String foo2) {
    this.foo2 = foo2;
  }
  public Bar bar1(String bar1) {
    this.bar1 = bar1;
    return this;
  }
  /**
   * Get bar1
   * @return bar1
  */
  @ApiModelProperty(value = "")
  public String getBar1() {
    return bar1;
  }
  public void setBar1(String bar1) {
    this.bar1 = bar1;
  }
  public Bar bar2(String bar2) {
    this.bar2 = bar2;
    return this;
  }
  /**
   * Get bar2
   * @return bar2
  */
  @ApiModelProperty(value = "")
  public String getBar2() {
    return bar2;
  }
  public void setBar2(String bar2) {
    this.bar2 = bar2;
  }
  ...
}
Command line used for generation
java -jar openapi-generator-cli.jar generate -g spring
Steps to reproduce
Related issues/PRs
Suggest a fix

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