openapi-generator
openapi-generator copied to clipboard
[BUG][KOTLIN-SPRING] Constructor call generated for interface supertypes if using inheritance/discriminator
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
If the parent of a type is generated as interface the subtype is generated with a constructor call to the parent interface which doesn't compile:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
@JsonSubTypes(
JsonSubTypes.Type(value = SubtypeA::class, name = "subtypeA"),
JsonSubTypes.Type(value = SubtypeB::class, name = "subtypeB")
)
interface ParentSchema{
val id: kotlin.String
val type: DiscriminatingType
}
data class SubtypeA(
@get:NotNull
@field:JsonProperty("id") override val id: kotlin.String,
@get:NotNull
@field:Valid
@field:JsonProperty("type") override val type: DiscriminatingType,
@field:JsonProperty("subtypeAproperty") val subtypeAproperty: kotlin.Int? = null
) : ParentSchema(){
}
Note: ParentSchema()
. The ()
prevent compilation
openapi-generator version
openapi-generator-maven-plugin:5.0.0
OpenAPI declaration file content or url
Related issues/PRs
Similar: #3587
Suggest a fix
I worked around it by removing the ()
from dataClass.mustache
. This wouldn't work if the parent is a class.
Thank you for the workaround! 🥳 If others are using openapi-generator-maven-plugin:
- copy dataClass.mustache and remove ().
- In the project root add a folder called
openapi-generator-templates
with the corrected mustache template. - In the plugin configuration (NOT configOptions) add:
<templateDirectory>${project.basedir}/openapi-generator-templates</templateDirectory>
This is fixed in 5.4.0
. See #11166 and #8687.
The problem with the fix is that it doesn't seem to work for when "additionalProperties": true
makes it so that the parent class is kotlin.collections.HashMap<String, kotlin.Any>
which does need the ()
in order to compile.
openapi.json
{
"openapi": "3.0.3",
"info": {
"title": "Hyperledger Cactus Plugin - Connector Corda",
"description": "Can perform basic tasks on a Corda ledger",
"version": "v2.0.0-alpha.2",
"license": {
"name": "Apache-2.0",
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
}
},
"paths": {},
"components": {
"schemas": {
"JarFile": {
"type": "object",
"required": ["filename", "contentBase64", "hasDbMigrations"],
"additionalProperties": true,
"properties": {
"filename": {
"type": "string",
"nullable": false,
"minLength": 1,
"maxLength": 255
},
"hasDbMigrations": {
"description": "Indicates whether the cordapp jar in question contains any embedded migrations that Cactus can/should execute between copying the jar into the cordapp directory and starting the node back up.",
"type": "boolean",
"nullable": false
},
"contentBase64": {
"type": "string",
"format": "base64",
"nullable": false,
"minLength": 1,
"maxLength": 1073741824
}
}
}
}
}
}
JarFile.kt
package org.hyperledger.cactus.plugin.ledger.connector.corda.server.model
import java.util.Objects
import com.fasterxml.jackson.annotation.JsonProperty
import javax.validation.constraints.DecimalMax
import javax.validation.constraints.DecimalMin
import javax.validation.constraints.Email
import javax.validation.constraints.Max
import javax.validation.constraints.Min
import javax.validation.constraints.NotNull
import javax.validation.constraints.Pattern
import javax.validation.constraints.Size
import javax.validation.Valid
import io.swagger.v3.oas.annotations.media.Schema
/**
*
* @param filename
* @param hasDbMigrations Indicates whether the cordapp jar in question contains any embedded migrations that Cactus can/should execute between copying the jar into the cordapp directory and starting the node back up.
* @param contentBase64
*/
data class JarFile(
@get:Size(min=1,max=255)
@Schema(example = "null", required = true, description = "")
@get:JsonProperty("filename", required = true) val filename: kotlin.String,
@Schema(example = "null", required = true, description = "Indicates whether the cordapp jar in question contains any embedded migrations that Cactus can/should execute between copying the jar into the cordapp directory and starting the node back up.")
@get:JsonProperty("hasDbMigrations", required = true) val hasDbMigrations: kotlin.Boolean,
@get:Size(min=1,max=1073741824)
@Schema(example = "null", required = true, description = "")
@get:JsonProperty("contentBase64", required = true) val contentBase64: kotlin.String
) : kotlin.collections.HashMap<String, kotlin.Any>{
}
Resulting compiler error
/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/model/JarFile.kt: (34, 5): This type has a constructor, and thus must be initialized here
I'm not an expert in the generator's internals. My naive idea for a more robust solution is to have an additional context variable added by the generator before the template rendering happens. Something that could be called parentCtorCallNeeded
or similar which then would allow us to update dataClass.mustache to use that boolean to render ()
or not with 100% certainty. I'm assuming here that the generator internally should be able to figure out whether the parent class is an interface or not, but this also might be a non-trivial thing to determine, I wouldn't know.