[BUG] [JAVA] Broken constructors in subclasses when superclass has read only properties
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
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.
I'm also having this problem. Can't use openapi-generator because of this.
I created a different template that generates calls to the constructors but I am not sure it fixes all issues
Additional info: The Spring generator handles this correctly.
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.