openapi-generator icon indicating copy to clipboard operation
openapi-generator copied to clipboard

[BUG] [JAVA] Broken constructors in subclasses when superclass has read only properties

Open pbarnes-tibco opened this issue 3 years ago • 4 comments

Bug Report Checklist

  • [x] Have you provided a full/minimal spec to reproduce the issue?
  • [x] Have you validated the input using an OpenAPI validator (example)?
  • [x] Have you tested with the latest master to confirm the issue still exists?
  • [x] Have you searched for related issues/PRs?
  • [x] What's the actual output vs expected output?
  • [ ] [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

With the Java client generator, models which have read only properties and which are used as superclasses via allOf polymorphism do not have setters generated, which makes sense, and the properties are of course private. However subclasses are generated incorrectly. Their constructors, which take all read only properties as arguments, contain code to set the private members of the superclass, and hence will not compile.

I am using the jersey2 library; issue may be present in others as well (did not test others.)

openapi-generator version

Using 5.4.0. Issue also exists in 6.0.1 as well as in latest master.

OpenAPI declaration file content or url
components:
  schemas:

    # Pet has a readonly name property 
    Pet:
      type: object
      discriminator:
        propertyName: discriminator
      required:
        - name
        - discriminator
      properties:
        name:
          type: string
          readOnly: true
        discriminator:
          type: string

    # Dog has a readonly packSize property.
    # Readonly properties do not get setters, and all properties are private in the implementing class.
    # Dog's generated constructor sets the name property, but it is private in Pet superclass.
    Dog:
      description: A representation of a dog
      allOf:
      - $ref: '#/components/schemas/Pet'
      - type: object
        properties:
          packSize:
            type: integer
            format: int32
            description: the size of the pack the dog is from
            default: 1
            minimum: 1
            readOnly: true
        required:
        - packSize

full openapi.yaml for repro available here: https://gist.github.com/pbarnes-tibco/b284210a1670b30fc60a6e7db3a9637a

Generation Details

openapi-generator-cli generate -g java --library jersey2 -i ./openapi.yaml -o ./generated/openapiclient

Steps to reproduce

Create a model which has read only properties, and a second model inheriting from the first via allOf polymorphism as in the above yaml. Generate Java client stubs with jersey2 library. Observe the generated code for the Dog class constructor:

public class Dog extends Pet {
    // ... 
    @JsonCreator
    public Dog(
      @JsonProperty(JSON_PROPERTY_PACK_SIZE) Integer packSize, 
      @JsonProperty(JSON_PROPERTY_NAME) String name) {
       this();
       this.packSize = packSize;
       this.name = name;  // <<<<< name is private in Pet class
    }
Related issues/PRs

None

Suggest a fix

Ideally, the derived class would call the appropriate superclass constructor. Alternatively, could generate protected setters for read only properties and call them instead.

To workaround, I'm using a custom template which generates protected setters and calls them instead, available here: https://gist.github.com/pbarnes-tibco/9bfe44e0a6998456005de577cf1f625e

pbarnes-tibco avatar Aug 22 '22 18:08 pbarnes-tibco

Would like to confirm that I am seeing this issue with the resttemplate library as well in version 6.2.0 unfortunately. I haven't tried the workaround mentioned in the original post but removing "readOnly: true" obviously fixes the issue, but that is a shoddy workaround at best so it'd be great to see a fix for this.

Killianoc avatar Sep 29 '22 11:09 Killianoc

I'm also having this problem. Can't use openapi-generator because of this.

jessebarnum avatar Apr 06 '23 02:04 jessebarnum

I created a different template that generates calls to the constructors but I am not sure it fixes all issues

pojo.zip

Additional info: The Spring generator handles this correctly.

LupusMKW avatar Apr 11 '23 16:04 LupusMKW

I'm having a similar problem in that subclass properties are added as fields in the superclass and are on the subclass constructor. This is plainly wrong. I think this may need another bug submitted as mine at least compiles.

KangoV avatar Jun 29 '24 23:06 KangoV