OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
22.02k stars 6.6k forks source link

[BUG][SPRING] multipart/form with optional parameters does not produce "Optional" in API interface, only in API Delagate #9530

Open sparmboy opened 3 years ago

sparmboy commented 3 years ago

Bug Report Checklist

Description

When defining an endpoint that consumes multipart/form-data that contains optional parameters, the generated XXXApi.java interface class does not produce a parameter wrapped in Optional whereas the accompanying XXXXApiDelegate.java does, thus where the Api calls the Delegate, the compiler rightly throws the error:

incompatible types: java.lang.String cannot be converted to java.util.Optional<java.lang.String>

Generated API

  default ResponseEntity<Void> upload(
@ApiParam(value = "", required=true) @Valid @RequestPart(value = "name", required = true)  String name,
@ApiParam(value = "") @Valid @RequestPart(value = "data", required = true) MultipartFile data,
@ApiParam(value = "") @Valid @RequestPart(value = "description", required = false)  String description) {
        return getDelegate().upload(name, data, description);
    }

Generated API Delegate

    default ResponseEntity<Void> upload(String name,
        MultipartFile data,
        Optional<String> description) {
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);

    }
openapi-generator version

5.1.1

swagger version

2.0

OpenAPI declaration file content or url
{
  "swagger": "2.0",
  "info": {
    "description": "Example swagger definition for an application API",
    "version": "1.0.0-SNAPSHOT",
    "title": "App Template"
  },
  "host": "localhost:8080",
  "tags": [
    {
      "name": "test-controller"
    }
  ],
  "paths": {
    "/templates": {
      "post": {
        "tags": [
          "test-controller"
        ],
        "summary": "Upload",
        "operationId": "upload",
        "consumes": [
          "multipart/form-data"
        ],
        "produces": [
          "application/json"
        ],
        "parameters": [
          {
            "in": "body",
            "name": "uploadRequest",
            "required": true,
            "schema":{
              "type": "object",
              "title": "UploadRequest",
              "required": [
                "name",
                "data"
              ],
              "properties": {
                "name": {
                  "type": "string"
                },
                "data": {
                  "type": "string",
                  "format": "binary"
                },
                "description": {
                  "type": "string"
                }
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        },
        "deprecated": false
      }
    }
  }
}

pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>spring-boot-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.1.1.RELEASE</version>
    </parent>
    <artifactId>open-api-bug</artifactId>
    <name>0.0.1</name>

    <properties>
        <java.version>1.8</java.version>
        <openapi-generator-maven-plugin.version>5.1.1</openapi-generator-maven-plugin.version>
        <springfox-version>2.9.2</springfox-version>
        <swagger.version>1.5.21</swagger.version>
    </properties>

    <dependencyManagement>
        <dependencies>

        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml</groupId>
                    <artifactId>classmate</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-spring-web</artifactId>
            <version>${springfox-version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${springfox-version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${springfox-version}</version>
            <exclusions>
                <exclusion>
                    <groupId>io.swagger</groupId>
                    <artifactId>swagger-models</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
            <version>${swagger.version}</version>
        </dependency>

        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>${swagger.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-commons</artifactId>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
        </dependency>
        <dependency>
            <groupId>org.openapitools</groupId>
            <artifactId>jackson-databind-nullable</artifactId>
            <version>0.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>${hibernate-validator.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.openapitools</groupId>
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <version>${openapi-generator-maven-plugin.version}</version>
                <executions>

                    <!-- Generate the spring controllers -->
                    <execution>
                        <id>generate-java</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <inputSpec>${basedir}/swagger.json</inputSpec>
                            <generatorName>spring</generatorName>
                            <ignoreFileOverride>${project.basedir}/.openapi-generator-ignore</ignoreFileOverride>
                            <modelPackage>${project.groupId}.model</modelPackage>
                            <apiPackage>${project.groupId}.controllers</apiPackage>
                            <generateModels>true</generateModels>
                            <configOptions>
                                <basePackage>${project.groupId}</basePackage>
                                <configPackage>${project.groupId}.config</configPackage>
                                <java8>true</java8>
                                <dateLibrary>java8</dateLibrary>
                                <performBeanValidation>true</performBeanValidation>
                                <useTags>true</useTags>
                                <useOptional>true</useOptional>
                                <generateApiTests>true</generateApiTests>
                                <generateApiDocumentation>false</generateApiDocumentation>
                                <supportingFiles>false</supportingFiles>
                                <serializableModel>true</serializableModel>
                                <delegatePattern>true</delegatePattern>
                                <supportingFilesToGenerate>ApiUtil.java</supportingFilesToGenerate>
                            </configOptions>
                            <additionalProperties>name=value</additionalProperties>

                        </configuration>
                    </execution>

                </executions>
            </plugin>

        </plugins>
    </build>
</project>
Generation Details

Run:

mvn clean compile
Steps to reproduce

Run:

mvn clean compile
Related issues/PRs
Suggest a fix

Need to have the API define optional parameters as Optional

fc-smohr commented 2 years ago

This case with useOptional=true and delegatePattern=true generates this error. If one of this switches is set to false, the compilation is successful. We are running into the same issue. Does anyone have a better workaround?