Nandan
Nandan

Reputation: 557

swagger-codegen-maven-plugin generates multipart form-data request api with @RequestParam instead of @RequestPart

I am using a request object [FileMetadata] for uploading files metadata information and send it as a part of the file upload multipart form-data request. But the swagger-codegen-maven-plugin generates the code with @RequestParam as the first part of the form-data request. Due to this I have to register a 'JSON to object' converter in the WebMvcConfigurer to convert the request part to FileMetadata, Otherwise it will through the following error:

o.s.w.s.m.s.DefaultHandlerExceptionResolver:208 - Resolved [org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'com.upload.file.generated.model.FileMetadata'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'com.upload.file.generated.model.FileMetadata': no matching editors or conversion strategy found]

I have the following questions:

  1. Is there any option to generate both request parameters annotated with @RequestPart?
  2. How to generate @Valid annotation for FileMetadata request param ?

Configuration details below:

Open API spec:

openapi: 3.0.3
...
...
paths:
  /api/v1/upload:
    post:
      tags:
      - File upload
      summary: Upload a file
      operationId: uploadFile
      requestBody:
        description: File that needs to be uploaded
        required: true
        content:
          multipart/form-data: # Media type 
            schema:
              required:
              - metadata
              - file
              type: object
              properties:
                metadata:
                  $ref: '#/components/schemas/FileMetadata'
                file:
                  type: string
                  format: binary
            encoding:
              metadata: 
                contentType: application/json
              file: 
                contentType: application/octet-stream
      responses:
        201:
          description: OK
        400:
          description: Invalid input
        401:
          description: Unauthorized
        403:
          description: Forbidden       
        404:
          description: Not Found

Generated API code:

        @Operation(summary = "Upload a file", description = "", tags={ "File upload" })
    @ApiResponses(value = {... })
    @RequestMapping(value = "/api/v1/upload",
        produces = { "application/json" }, 
        consumes = { "multipart/form-data" }, 
        method = RequestMethod.POST)
    ResponseEntity<Void> uploadFile(@Parameter(in = ParameterIn.DEFAULT, description = "", required=true,schema=@Schema()) @RequestParam(value="metadata", required=true)  FileMetadata metadata, @Parameter(description = "file detail") @Valid @RequestPart("file") MultipartFile file);

Pom.xml:

                <plugin>
                <groupId>io.swagger.codegen.v3</groupId>
                <artifactId>swagger-codegen-maven-plugin</artifactId>
                <version>3.0.33</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <inputSpec>${project.basedir}/openapi.yaml</inputSpec>
                            <language>spring</language>                         
                            <output>${project.basedir}</output>
                            <modelPackage>com.file.upload.generated.model</modelPackage>
                            <apiPackage>com.file.upload.generated.api</apiPackage>
                            <generateModels>true</generateModels>
                            <generateModelDocumentation>false</generateModelDocumentation>
                            <generateApis>true</generateApis>
                            <generateApiDocumentation>false</generateApiDocumentation>
                            <generateApiTests>false</generateApiTests>
                            <generateSupportingFiles>false</generateSupportingFiles>
                            <configOptions>
                                <performBeanValidation>true</performBeanValidation>
                                <useBeanValidation>true</useBeanValidation>
                                <hideGenerationTimestamp>true</hideGenerationTimestamp>
                                <dateLibrary>java11-localdatetime</dateLibrary>
                            </configOptions>
                            <importMappings>
                                <importMapping>Date=java.time.LocalDate</importMapping>                             
                            </importMappings>
                            <typeMappings>
                                <typeMapping>Date=LocalDate</typeMapping>
                            </typeMappings>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

Upvotes: 1

Views: 2001

Answers (1)

SoSayethSimon
SoSayethSimon

Reputation: 1

The cleanest way to achieve both of your goals would be to provide custom mustache templates in your project. You can find them in the Swagger Codegen Generators Repository -> or more precisely, you can find the Spring Templates in this folder for Version 3.0.33 of the generator.

For your case, the corresponding template would be formParams.mustache, where i would suggest to alter the line from:

[...] defaultValue="{{{defaultValue}}}"{{/defaultValue}})){{/useOas2}} @RequestParam(value="{{baseName}}"{{#required}}, required=true [...]

To:

defaultValue="{{{defaultValue}}}"{{/defaultValue}})){{/useOas2}}{{#useBeanValidation}} @Valid{{/useBeanValidation}} @RequestPart(value="{{baseName}}"{{#required}}, required=true{{/required}}[...]

To use those custom templates just add the template directory to your plugin configuration:

<configuration>
     [...]
     <templateDirectory>src/main/resources/mustache/handlebars/JavaSpring</templateDirectory>
     [...]
</configuration>

For a more extensive Guide on using mustache templates i can recommend the guide from the openapi-generator on this topic.

Upvotes: 0

Related Questions