Openapi-generator: [BUG] [java] resttemplate library doesn't support API with response type:string and format:binary

Created on 22 Mar 2019  路  10Comments  路  Source: OpenAPITools/openapi-generator

Description

When using the resttemplate library for a java client with an endpoint to download a binary file the generated code does not work. It throws and error that no converter can be found. Taking from https://github.com/swagger-api/swagger-codegen-generators/issues/287

The client is not correctly generated to support the file download using Spring Rest Template framework.

ResponseEntity responseEntity = restTemplate.exchange(requestEntity, returnType);

Where T is File and returnType is ParameterizedTypeReference(). In this way File is treated as a json object to be mapped to the response.

Which is consistent with what i found. If i change the ParameterizedTypeReference to be a ByteArrayResource it get the bytes. And if i use the default java library it works properly.

openapi-generator version

Using the Gradle plugin 3.3.4 using a generator configured like:
task buildClient(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask){
generatorName = "java"
library = "resttemplate"
inputSpec = "${project.rootDir}/swagger.yaml".toString()
configOptions = [
dateLibrary: "java8"
]
}

OpenAPI declaration file content or url
openapi: 3.0.2
info:
  description: Api Documentation
  version: '2.0'
  title: Api Documentation
  termsOfService: 'urn:tos'
  contact: {}
  license:
    name: Apache 2.0
    url: 'http://www.apache.org/licenses/LICENSE-2.0'

paths:
  '/download/{_id}':
    get:
      tags:
        - encounter-controller
      summary: downloadFile
      operationId: downloadFile
      parameters:
        - name: _id
          in: path
          description: _id
          required: true
          schema:
            type: string
      responses:
        '200':
          description: The File
          content:
            '*/*':
              schema:
                type: string
                format: binary
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
        '404':
          description: Not Found
Steps to reproduce

Generate the client and server and when the Client requests the File it will throw an error like:
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class java.io.File] and content type [application/octet-stream] at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:110) at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:917) at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:901) at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:655) at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:628) at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:602)

Related issues/PRs

Using a inputStream like requested in https://github.com/OpenAPITools/openapi-generator/pull/995 would fix it.

The issue i happening in the swagger-api repo also https://github.com/swagger-api/swagger-codegen-generators/issues/287

Suggest a fix

Using a ByteResource or just a inputStream over returning a java.io.File

Java Bug

All 10 comments

馃憤 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.

Yes, I saw this bug, I can contribute to fix it.

Hi, I'm seeing the same problem with the openapi-generator running against an OpenAPI spec 2 yaml file. Tested against openapi-generator tags v3.3.4, v4.0.0-beta3, and master at 561c1e064641db2d36c9a8a1e53b66ca010e5fa2 and it's still a problem. The only notable difference from the example posted above is the response type is declared differently and I added produces: application/octet-stream to match OpenAPI spec 2.

paths:
  /data/{id}:
    get:
      summary: Get the data
      description: Returns a binary form of the data
      tags:
        - Data
      operationId: getDataByID
      produces:
        - application/octet-stream
      parameters:
        - in: path
          name: id
          description: the id of the data
          required: true
          type: string
      responses:
        '200':
          description: Successfully retrieved data
          schema:
            type: string
            format: binary
        '404':
          description: Data not found

In addition to the swagger issue mentioned above, there is another swagger bug that is similar: https://github.com/swagger-api/swagger-codegen/issues/9025 I would also consider this ticket related to openapi-generator #994 though that is not specific to RestTemplate and is for performance, not basic functionality.

Has there been any update on this issue? I am experiencing this issue as well, 10 months since the last post.

I found a solution to this problem. Implement a custom HttpMessageConverter:
public class FileMessageConverter implements HttpMessageConverter<File> {}
And add it to the RestTemplate's converters (I added it as first converters, not sure it is important), either by instanciating your RestTemplate or modifying the existing one (with BeanPostProcessor for instance).
This would be great to have a such converter added automatically to the default RestTemplate.

On the other hand, what I would expect is to have the choice to get the InputStream to have better performance (avoiding using a temporary file) but maybe I'm asking too much :) (I'm actually a newly user of OpenAPI generator so, I'm not mastering all mechanism).
Maybe using an higher abstract ? (Path, InputStreamSource, Resource, ...)

Hello, a simple solution is to add in your configuration :
<typeMappings> <typeMapping>File=org.springframework.core.io.Resource</typeMapping> </typeMappings>

Adding the typeMapping results in a compilation error:
java: no suitable constructor found for FileSystemResource(org.springframework.core.io.Resource)

Hope this can help you. My full configuration using openapi-generator-maven-plugin version 3.3.4 with a java 11 project is below :

<execution> <id>generate-sources-client</id> <phase>generate-sources</phase> <goals> <goal>generate</goal> </goals> <configuration> <inputSpec>${project.basedir}/../../api/v1/api.yml</inputSpec> <modelPackage>api.v1.client.model</modelPackage> <apiPackage>api.v1.client</apiPackage> <language>java</language> <library>resttemplate</library> <generateApiDocumentation>true</generateApiDocumentation> <generateModelDocumentation>true</generateModelDocumentation> <generateApiTests>false</generateApiTests> <typeMappings> <typeMapping>File=org.springframework.core.io.Resource</typeMapping> </typeMappings> <configOptions> <sourceFolder>src/gen/java/main</sourceFolder> <interfaceOnly>true</interfaceOnly> <dateLibrary>java8-localdatetime</dateLibrary> <java8>true</java8> <serializableModel>true</serializableModel> <generateSupportingFiles>true</generateSupportingFiles> </configOptions> </configuration> </execution>

@CHITOU's solution worked for me using version 5.0.0-beta2.

OpenAPI3 , swagger-codegen-cli-3.0.23.jar , byte replace binary . resttemplate return byte[] .

This could be a solution.

Was this page helpful?
0 / 5 - 0 ratings