-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Open
Labels
Description
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?
- Have you validated the input using an OpenAPI validator?
- 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
Using a multipart request body which has additional-properties as part generates invalid code for the java-resttemplate client. It was introduced in version 7.5.0 before this version it worked correctly
Spec below creates following for example:
package org.openapitools.client.api;
import org.openapitools.client.ApiClient;
import org.openapitools.client.BaseApi;
import java.io.File;
import org.openapitools.client.model.StructuredType;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.19.0-SNAPSHOT")
public class FileApi extends BaseApi {
public FileApi() {
super(new ApiClient());
}
public FileApi(ApiClient apiClient) {
super(apiClient);
}
/**
*
*
* <p><b>201</b> - File created successfully
* @param documentBytes (required)
* @param documentType (required)
* @param properties (required)
* @param structured (optional)
* @throws RestClientException if an error occurs while attempting to invoke the API
*/
public void createFile(File documentBytes, String documentType, Map<String, String> properties, StructuredType structured) throws RestClientException {
createFileWithHttpInfo(documentBytes, documentType, properties, structured);
}
/**
*
*
* <p><b>201</b> - File created successfully
* @param documentBytes (required)
* @param documentType (required)
* @param properties (required)
* @param structured (optional)
* @return ResponseEntity<Void>
* @throws RestClientException if an error occurs while attempting to invoke the API
*/
public ResponseEntity<Void> createFileWithHttpInfo(File documentBytes, String documentType, Map<String, String> properties, StructuredType structured) throws RestClientException {
Object localVarPostBody = null;
// verify the required parameter 'documentBytes' is set
if (documentBytes == null) {
throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter 'documentBytes' when calling createFile");
}
// verify the required parameter 'documentType' is set
if (documentType == null) {
throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter 'documentType' when calling createFile");
}
// verify the required parameter 'properties' is set
if (properties == null) {
throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter 'properties' when calling createFile");
}
final MultiValueMap<String, String> localVarQueryParams = new LinkedMultiValueMap<String, String>();
final HttpHeaders localVarHeaderParams = new HttpHeaders();
final MultiValueMap<String, String> localVarCookieParams = new LinkedMultiValueMap<String, String>();
final MultiValueMap<String, Object> localVarFormParams = new LinkedMultiValueMap<String, Object>();
if (documentBytes != null)
localVarFormParams.add("documentBytes", new FileSystemResource(documentBytes));
if (documentType != null)
localVarFormParams.add("documentType", documentType);
if (structured != null)
localVarFormParams.add("structured", structured);
if (properties != null)
localVarFormParams.addAll("properties", properties);
final String[] localVarAccepts = { };
final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
final String[] localVarContentTypes = {
"multipart/form-data"
};
final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
String[] localVarAuthNames = new String[] { };
ParameterizedTypeReference<Void> localReturnType = new ParameterizedTypeReference<Void>() {};
return apiClient.invokeAPI("/api/v1/file", HttpMethod.POST, Collections.<String, Object>emptyMap(), localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localReturnType);
}
@Override
public <T> ResponseEntity<T> invokeAPI(String url, HttpMethod method, Object request, ParameterizedTypeReference<T> returnType) throws RestClientException {
String localVarPath = url.replace(apiClient.getBasePath(), "");
Object localVarPostBody = request;
final Map<String, Object> uriVariables = new HashMap<String, Object>();
final MultiValueMap<String, String> localVarQueryParams = new LinkedMultiValueMap<String, String>();
final HttpHeaders localVarHeaderParams = new HttpHeaders();
final MultiValueMap<String, String> localVarCookieParams = new LinkedMultiValueMap<String, String>();
final MultiValueMap<String, Object> localVarFormParams = new LinkedMultiValueMap<String, Object>();
final String[] localVarAccepts = { };
final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
final String[] localVarContentTypes = {
"multipart/form-data"
};
final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
String[] localVarAuthNames = new String[] { };
return apiClient.invokeAPI(localVarPath, method, uriVariables, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, returnType);
}
}but should look like
package org.openapitools.client.api;
import org.openapitools.client.ApiClient;
import org.openapitools.client.BaseApi;
import java.io.File;
import org.openapitools.client.model.StructuredType;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.19.0-SNAPSHOT")
public class FileApi extends BaseApi {
public FileApi() {
super(new ApiClient());
}
public FileApi(ApiClient apiClient) {
super(apiClient);
}
/**
*
*
* <p><b>201</b> - File created successfully
* @param documentBytes (required)
* @param documentType (required)
* @param properties (required)
* @param structured (optional)
* @throws RestClientException if an error occurs while attempting to invoke the API
*/
public void createFile(File documentBytes, String documentType, Map<String, String> properties, StructuredType structured) throws RestClientException {
createFileWithHttpInfo(documentBytes, documentType, properties, structured);
}
/**
*
*
* <p><b>201</b> - File created successfully
* @param documentBytes (required)
* @param documentType (required)
* @param properties (required)
* @param structured (optional)
* @return ResponseEntity<Void>
* @throws RestClientException if an error occurs while attempting to invoke the API
*/
public ResponseEntity<Void> createFileWithHttpInfo(File documentBytes, String documentType, Map<String, String> properties, StructuredType structured) throws RestClientException {
Object localVarPostBody = null;
// verify the required parameter 'documentBytes' is set
if (documentBytes == null) {
throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter 'documentBytes' when calling createFile");
}
// verify the required parameter 'documentType' is set
if (documentType == null) {
throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter 'documentType' when calling createFile");
}
// verify the required parameter 'properties' is set
if (properties == null) {
throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Missing the required parameter 'properties' when calling createFile");
}
final MultiValueMap<String, String> localVarQueryParams = new LinkedMultiValueMap<String, String>();
final HttpHeaders localVarHeaderParams = new HttpHeaders();
final MultiValueMap<String, String> localVarCookieParams = new LinkedMultiValueMap<String, String>();
final MultiValueMap<String, Object> localVarFormParams = new LinkedMultiValueMap<String, Object>();
if (documentBytes != null)
localVarFormParams.add("documentBytes", new FileSystemResource(documentBytes));
if (documentType != null)
localVarFormParams.add("documentType", documentType);
if (structured != null)
localVarFormParams.add("structured", structured);
if (properties != null)
localVarFormParams.add("properties", properties);
final String[] localVarAccepts = { };
final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
final String[] localVarContentTypes = {
"multipart/form-data"
};
final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
String[] localVarAuthNames = new String[] { };
ParameterizedTypeReference<Void> localReturnType = new ParameterizedTypeReference<Void>() {};
return apiClient.invokeAPI("/api/v1/file", HttpMethod.POST, Collections.<String, Object>emptyMap(), localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, localReturnType);
}
@Override
public <T> ResponseEntity<T> invokeAPI(String url, HttpMethod method, Object request, ParameterizedTypeReference<T> returnType) throws RestClientException {
String localVarPath = url.replace(apiClient.getBasePath(), "");
Object localVarPostBody = request;
final Map<String, Object> uriVariables = new HashMap<String, Object>();
final MultiValueMap<String, String> localVarQueryParams = new LinkedMultiValueMap<String, String>();
final HttpHeaders localVarHeaderParams = new HttpHeaders();
final MultiValueMap<String, String> localVarCookieParams = new LinkedMultiValueMap<String, String>();
final MultiValueMap<String, Object> localVarFormParams = new LinkedMultiValueMap<String, Object>();
final String[] localVarAccepts = { };
final List<MediaType> localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
final String[] localVarContentTypes = {
"multipart/form-data"
};
final MediaType localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
String[] localVarAuthNames = new String[] { };
return apiClient.invokeAPI(localVarPath, method, uriVariables, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarCookieParams, localVarFormParams, localVarAccept, localVarContentType, localVarAuthNames, returnType);
}
}openapi-generator version
7.17.0
OpenAPI declaration file content or url
openapi: 3.0.3
info:
title: Minimal
description: Api to reproduce bug
version: 0.5.1-SNAPSHOT.0
tags:
- name: test
servers:
- url: http://localhost:8080
paths:
"/api/v1/file":
post:
tags:
- file
operationId: createFile
requestBody:
required: true
content:
multipart/form-data:
schema:
$ref: "#/components/schemas/FileUploadRequest"
encoding:
documentBytes:
contentType: "*/*"
properties:
contentType: application/json
responses:
"201":
description: File created successfully
components:
schemas:
FileUploadRequest:
type: object
properties:
documentBytes:
type: string
format: binary
documentType:
type: string
properties:
$ref: '#/components/schemas/TypeMap'
required:
- documentBytes
- documentType
- properties
TypeMap:
type: object
additionalProperties:
type: string<--
(for YAML code) or
(here your code)(for JSON code), so it becomes more readable. If it is longer than about ten lines,
please create a Gist (https://gist.github.com) or upload it somewhere else and
link it here.
-->
Generation Details
{
"$schema": "https://raw.githubusercontent.com/OpenAPITools/openapi-generator-cli/refs/heads/master/apps/generator-cli/src/config.schema.json",
"spaces": 2,
"generator-cli": {
"version": "7.18.0",
"generators": {
"java-client-sdk": {
"generatorName": "java",
"library": "resttemplate",
"inputSpec": "api-specification.yml",
"output": "#{cwd}/sdks/java-client-sdk",
"globalProperty": {
"apiTests": false,
"apiDocs": false,
"modelTests": false,
"modelDocs": false
},
"additionalProperties": {
"serializationLibrary": "jackson",
"useJakartaEe": true,
"hideGenerationTimestamp": true,
"useAbstractionForFiles": true,
"sourceFolder": "src/gen/java",
"booleanGetterPrefix": "is",
"enumUnknownDefaultCase": true
}
}
}
}
}
npx @openapitools/openapi-generator-cli generate
Steps to reproduce
See config and spec above.
Related issues/PRs
Suggest a fix
I am going to prepare a PR.