Reputation: 557
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:
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
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