OpenAPITools / OpenAPITools/openapi-generator

[BUG][JavaSpring] Multipart request regression in 6.x

Open
#12,498 16 comments 9 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

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

It seems the PR #11449 breaks with some multipart requests.

With an endpoint:

  • Consuming multipart/form-data
  • File as parameter
  • A second parameter consisting of an object

and the generator settings:

  • skipFormModel set to false to use the second parameter
  • interfaceOnly set to true to only generate models & interfaces

The generated API causes an error while spring tries to convert the request part to the object:

Resolved [org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'com.example.demo.api.model.TestObjectPart'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'com.example.demo.api.model.TestObjectPart': no matching editors or conversion strategy found]
openapi-generator version

It's a regression introduced with openapi-generator 6.x.
With the 5.x version the generated code behaves as expected.

OpenAPI declaration file content or url

Or see the reproduction repo: https://github.com/cc-ju/openapi-genrator-spring-error-reproduction/blob/main/openapi.yaml

openapi: 3.0.2
info:
  version: 1.0.0
  title: test

paths:
  /test:
    post:
      requestBody:
        content:
          multipart/form-data:
            encoding:
              file:
                contentType: "application/octet-stream"
              content:
                contentType: "application/json"
            schema:
              type: object
              required:
                - file
                - content
              properties:
                file:
                  type: string
                  format: binary
                content:
                  $ref: "#/components/schemas/testObjectPart"
      responses:
        200:
          description: OK

components:
  schemas:
    testObjectPart:
      type: object
      required:
        - foo
      properties:
        foo:
          type: string
        bar:
          type: number
Generation Details
Actual output
    default ResponseEntity<Void> testPost(
        @Parameter(name = "file", description = "", required = true) @RequestPart(value = "file", required = true) MultipartFile file,
        @Parameter(name = "content", description = "", required = true) @Valid @RequestParam(value = "content", required = true) TestObjectPart content
    ) {
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);

    }
Expected output

Note that this would re-introduce the problem #11449 tried to fix

    default ResponseEntity<Void> testPost(
        @Parameter(name = "file", description = "", required = true) @RequestPart(value = "file", required = true) MultipartFile file,
        @Parameter(name = "content", description = "", required = true) @Valid @RequestPart(value = "content", required = true) TestObjectPart content
    ) {
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);

    }
Steps to reproduce

check out the reproduction repo: https://github.com/cc-ju/openapi-genrator-spring-error-reproduction

run ./gradlew check --info

To switch to the older generator just change:

Related issues/PRs

As mentioned above this regression is caused by #11449

Suggest a fix

Obviously #11449 resolved another problem. But broke this use case.
Currently I don't have a solution which does not break either this use case or the use case from the PR.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked reproduction repository, its openapi.yaml, and the ./gradlew check --info command. Compare generated output with generator 5.x and 6.x, then trace the change from PR #11449. Done means multipart file and object parameters are converted correctly without regressing the use case addressed by that PR.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, openapi, spring-boot
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.