OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.35k stars 6.46k forks source link

[BUG] [kotlin-spring] MissingKotlinParameterException instead of BeanValidation exception for missing required property #5121

Open cthiebault opened 4 years ago

cthiebault commented 4 years ago

Bug Report Checklist

Description

I defined a required property but instead of getting a bean validation exception, I get a MissingKotlinParameterException:

com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class dto.Component] value failed for JSON property type due to missing (therefore NULL) value for creator parameter type which is a non-nullable type
 at [Source: (PushbackInputStream); line: 1, column: 2] (through reference chain: dto.Component["type"])

Here is the generated DTO:

data class Component (
        @get:NotNull 
        @ApiModelProperty(required = true, value = "")
        @JsonProperty("type") val type: kotlin.String,

        @ApiModelProperty(value = "")
        @JsonProperty("model") val model: kotlin.String? = null
) 

It seems validation is done after the dto is instantiated... and as a required field is null, it can't create a new instance of this dto.

openapi-generator version

kotlin-spring with 4.2.2

OpenAPI declaration file content or url
Component:
  type: object
  required:
    - type
  properties:
    type:
      type: string
    model:
      type: string
auto-labeler[bot] commented 4 years ago

👍 Thanks for opening this issue! 🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

ackintosh commented 4 years ago

Thanks for the issue!


I've confirmed the steps below reproduces the issue:

issue5121.yaml ```yaml openapi: 3.0.2 servers: - url: 'http://localhost:8080' info: version: 1.0.0 title: OpenAPI Petstore paths: /pet: post: description: test operationId: findPets requestBody: content: application/json: schema: $ref: '#/components/schemas/Component' description: test requestBody required: true responses: '200': description: successful operation content: application/json: schema: type: string components: schemas: Component: type: object required: - type properties: type: type: string model: type: string ```
# Generate `kotlin-spring` server
$ java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar \
  generate \
  -g kotlin-spring \
  -i issue5121.yaml \
  -o /tmp/issue5121 \
  --additional-properties swaggerAnnotations=true

# Run the generated server
$ cd /tmp/issue5121
$ gradle bootRun

# Send a POST request w/o `type` which is required field.
$ curl -v -X POST "http://localhost:8080/pet" \
    -H "accept: application/json" \
    -H "Content-Type: application/json" \
    -d "{\"model\":\"string\"}" | jq

...
...

{
  "timestamp": "2020-02-05T02:24:59.628+0000",
  "status": 400,
  "error": "Bad Request",
  "message": "JSON parse error: Instantiation of [simple type, class org.openapitools.model.Component] value failed for JSON property type due to missing (therefore NULL) value for creator parameter type which is a non-nullable type; nested exception is com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class org.openapitools.model.Component] value failed for JSON property type due to missing (therefore NULL) value for creator parameter type which is a non-nullable type\n at [Source: (PushbackInputStream); line: 1, column: 18] (through reference chain: org.openapitools.model.Component[\"type\"])",
  "path": "/pet"
}
yutaka0m commented 4 years ago

If declear nullable and embed @field:Notnull :

data class Component(

    @field:NotNull
    @ApiModelProperty(example = "null", required = true, value = "")
    @JsonProperty("type") val type: kotlin.String?,

    @ApiModelProperty(example = "null", value = "")
    @JsonProperty("model") val model: kotlin.String? = null
)

This issue will be solved. What do you think about this solution? @ackintosh @cthiebault

cthiebault commented 4 years ago

It would work... but it's too bad to have a poor model with non null field becoming nullable because of validation :( Maybe related to https://stackoverflow.com/a/41994512/386713 ?

ackintosh commented 4 years ago

Hmm... I can't think of other way. 🤔 💦

Technical Committee (Kotlin): @jimschubert @dr4ke616 @karismann @Zomzog @andrewemery @4brunu

Do you have any ideas?

jimschubert commented 4 years ago

Seems like a secondary constructor with and JsonCreator might work best, maybe also Delegates.notNull.

I'm not sure when I'd have time to look into, though.

kodai-shirafuta-skl commented 2 years ago

I think you can set empty string as default value. Jackson should be able to parse it successfully.

@field:NotNull
    @ApiModelProperty(example = "null", required = true, value = "")
    @JsonProperty("type") val type: kotlin.String = '',
zipper2110 commented 7 months ago

Guys please pay attention to this one, it messes up the validation flow and makes us devs do weird things to make it work.

wing328 commented 7 months ago

@zipper2110 may I know if you can contribute a PR to start with?

aldex32 commented 4 months ago

quite an old story, any update on this?