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
21.58k stars 6.52k forks source link

[BUG] Migrating Swagger-code-gen to openapi-generator-maven-plugin with Mustache: Illegal start of expression ',', ')', or '[' expected #14914

Open reinaldoneves opened 1 year ago

reinaldoneves commented 1 year ago

[Migrating Swagger-code-gen to openapi-generator-maven-plugin with Mustache: Illegal start of expression ',', ')', or '[' expected]

Console output: Illegal start of expression ',', ')', or '[' expected

Description

I'm trying to migrate application with a several of other libaries from Java 11, Spring-Boot 2.7.x to Java 17, Spring-Boot 3 We also need to migrate swagger-codegen-maven-plugin to openapi-generator-maven-plugin, because we use .yaml files with Swagger specifications. However, when we run a mvn clean package or mvn clean install, we are facing this issue: [Illegal start of expression ',', ')', or '' expected

We know that swagger-codegen-maven-plugin use the mustache file via tag, but openapi-generator-maven-plugin supports it either? With the same tag? We notice yet that the comma are missing when the classes are generated, after the migration.

All swagger .yamls where converted from version 2.0 to version 3.0.1 via https://editor-next.swagger.io/

openapi-generator version

openapi-generator-maven-plugin 6.3.0

This is my pom.xml execution for the specified swagger file:
<execution>
    <id>crosscore</id>
    <goals>
        <goal>generate</goal>
    </goals>
    <configuration>
        <inputSpec>src/main/resources/feign/swagger/crosscore.yaml</inputSpec>
        <templateDirectory>src/main/resources/feign/templates</templateDirectory>
        <generatorName>spring</generatorName>
        <library>spring-cloud</library>
        <modelPackage>br.com.experian.api.crosscore.model</modelPackage>
        <apiPackage>br.com.experian.api.crosscore.api</apiPackage>
        <generateSupportingFiles>false</generateSupportingFiles>
        <configOptions>
            <sourceFolder>gen</sourceFolder>
            <useJakartaEe>true</useJakartaEe>
            <useSpringBoot3>true</useSpringBoot3>
            <java7>true</java7>
            <dateLibrary>joda</dateLibrary>
            <title>crosscore</title> <!-- Used for feign bean name and uri property-->
        </configOptions>
    </configuration>
</execution>
OpenAPI declaration file content or url
<execution>
    <id>crosscore</id>
    <goals>
        <goal>generate</goal>
    </goals>
    <configuration>
        <inputSpec>src/main/resources/feign/swagger/crosscore.yaml</inputSpec>
        <templateDirectory>src/main/resources/feign/templates</templateDirectory>
        <generatorName>spring</generatorName>
        <library>spring-cloud</library>
        <modelPackage>br.com.experian.api.crosscore.model</modelPackage>
        <apiPackage>br.com.experian.api.crosscore.api</apiPackage>
        <generateSupportingFiles>false</generateSupportingFiles>
        <configOptions>
            <sourceFolder>gen</sourceFolder>
            <useJakartaEe>true</useJakartaEe>
            <useSpringBoot3>true</useSpringBoot3>
            <java7>true</java7>
            <dateLibrary>joda</dateLibrary>
            <title>crosscore</title> <!-- Used for feign bean name and uri property-->
        </configOptions>
    </configuration>
</execution>
OpenAPI declaration file content or url
//more code ommited
  paths:
    /DefaultRequestListener:
      post:
        tags:
          - CrossCore
        summary: CrossCore API Submit Request
        description: This API requires SSL, using the Security Certificate provided
          by Experian, and SHA-256 HMAC-signature using the HMAC key provided by Experian.
          Also, please inform the IP addresses to be allowed to connect to CrossCore.
        operationId: submit
        parameters:
          - name: workflow
            in: query
            description: ?RedBoxCPF
            schema:
              type: string
        requestBody:
          description: CrossCore Request
          content:
            application/json; charset=utf-8:
              schema:
                $ref: '#/components/schemas/RequestMessage'
          required: true
        responses:
          200:
            description: successful operation
            content:
              application/json:
                schema:
                  $ref: '#/components/schemas/ResponseMessage'
        x-codegen-request-body-name: body
  components:
    schemas:
      RequestMessage:
        required:
          - header
          - payload
        type: object
        properties:
          header:
            $ref: '#/components/schemas/RequestHeader'
          payload:
            $ref: '#/components/schemas/RequestPayload'
      RequestHeader:
        type: object
        properties:
          tenantId:
            maxLength: 8
            type: string
            description: Client Identifier as provided by Experian  Delivery Team.
            example: ABCD1234
          clientReferenceId:
            maxLength: 90
            type: string
            description: Unique client reference for each submission. This is provided
              by the client.
            example: YourRequestUniqueID
          messageTime:
            type: string
            description: Time message is submitted to the API, in UTC-0. The Time Zone
              Designator (TZD) value must be Z
            format: date-time
            example: 2019-10-23T14:20:04Z
          requestType:
            maxLength: 40
            type: string
            description: Used to determine the workflow and strategy manager as provided
              by Experian Delivery Team.
            example: KQO
          options:
            $ref: '#/components/schemas/Options'
          expRequestId:
            maxLength: 90
            type: string
            description: Experian generated unique Id
            example: RB000043766204
        description: Section for all control parameters for the submit API.
      Options:
        type: object
      RequestPayload:
        required:
          - application
          - contacts
        type: object
        properties:
          contacts:
            type: array
            description: The contacts object contains all contact information [Email(s)]
              for any email associated to an event. You can include any number of contacts'
              information in the message.
            items:
              $ref: '#/components/schemas/Contact'
          application:
            $ref: '#/components/schemas/Application'
          device:
            $ref: '#/components/schemas/Device'
      Contact:
        required:
          - emails
          - id
          - names
          - person
        type: object
        properties:
          id:
            maxLength: 40
            type: string
            description: Value used to cross-reference pieces of data to other objects
              within the message. When you need to reference this object, you will use
              this id value in the target object to associate this object to the target
              object
            example: MAINCONTACT_1
          person:
            $ref: '#/components/schemas/Person'
          names:
            $ref: '#/components/schemas/Names'
          emails:
            type: array
            items:
              $ref: '#/components/schemas/ContactEmail'
        description: The contacts object contains all contact information [Person(s),
          identityDocuments, organizations, addresses, telephones, etc.] for any person
          associated to an event. You can include any number of contacts' information
          in the message
      Person:
        required:
          - personIdentifier
          - typeOfPerson
        type: object
        properties:
          typeOfPerson:
            maxLength: 20
            type: string
            description: Indicator for the person type. Enum field values must be all
              CAPS. Please check the "Enum List" tab for a listing of all enumerations
            example: APPLICANT
            enum:
              - APPLICANT
          personIdentifier:
            maxLength: 20
            type: string
            description: Unique client identifier for the person. --Usar CPF do proponente--
            example: "12345678901"
        description: Single person defined for the submit request
      Names:
        type: object
        properties:
          id:
            type: string
            description: '...'
            example: MAINPERSONNAME_1
          firstName:
            type: string
            description: '...'
            example: JUSTINO
      ContactEmail:
        type: object
        properties:
          id:
            type: string
            description: '...'
            example: EMAIL_1
          email:
            type: string
            description: '...'
            format: email
            example: admin@nowhere.net
      Application:
        required:
          - applicants
        type: object
        properties:
          applicationId:
            maxLength: 26
            type: string
            description: ""
            example: APPLICATION_1
          applicants:
            type: array
            items:
              $ref: '#/components/schemas/Applicant'
      Applicant:
        type: object
        properties:
          id:
            maxLength: 40
            type: string
            description: ""
            example: MAINAPPLICANT_1
          applicantType:
            maxLength: 26
            type: string
            description: ""
            example: APPLICANT
            enum:
              - APPLICANT
          contactId:
            maxLength: 40
            type: string
            description: ""
            example: MAINCONTACT_1
          type:
            maxLength: 40
            type: string
            description: ""
            example: INDIVIDUAL
      Device:
        type: object
        properties:
          id:
            maxLength: 40
            type: string
            description: '...'
            example: DEVICEID_1
          ipAddress:
            maxLength: 40
            type: string
            description: '...'
            example: 10.0.0.1
      ResponseMessage:
        required:
          - clientResponsePayload
          - responseHeader
        type: object
        properties:
          responseHeader:
            $ref: '#/components/schemas/ResponseHeader'
          clientResponsePayload:
            $ref: '#/components/schemas/ClientResponsePayload'
          originalRequestData:
            $ref: '#/components/schemas/RequestPayload'
        description: Error, Warning, or Informational message describing the response.
        //more code ommited
This is my mustache file
package {{package}};
{{#imports}}import {{import}};
{{/imports}}
{{#jdk8-no-delegate}}
import com.fasterxml.jackson.databind.ObjectMapper;
{{/jdk8-no-delegate}}
import io.swagger.annotations.*;
{{#jdk8-no-delegate}}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
{{/jdk8-no-delegate}}
import org.springframework.http.ResponseEntity;
{{#useBeanValidation}}
import org.springframework.validation.annotation.Validated;
{{/useBeanValidation}}
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;

{{#jdk8-no-delegate}}
import javax.servlet.http.HttpServletRequest;
{{/jdk8-no-delegate}}
{{#useBeanValidation}}
import javax.validation.Valid;
import javax.validation.constraints.*;
{{/useBeanValidation}}
{{#jdk8-no-delegate}}
import java.io.IOException;
{{/jdk8-no-delegate}}
import java.util.List;
{{#jdk8-no-delegate}}
import java.util.Optional;
{{/jdk8-no-delegate}}
{{^jdk8-no-delegate}}
    {{#useOptional}}
import java.util.Optional;
    {{/useOptional}}
{{/jdk8-no-delegate}}
{{#async}}
import java.util.concurrent.{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture{{/jdk8}};
{{/async}}

import io.swagger.annotations.*;
import org.springframework.cloud.openfeign.FeignClient;
import br.com.experian.configuration.feign.config.FeignClientConfig;

{{=<% %>=}}
@FeignClient(name="<%title%>", url="${api.<%title%>.uri}", configuration = FeignClientConfig.class)
<%={{ }}=%>
{{#operations}}
public interface {{classname}}Client {

{{#operation}}
    @RequestMapping(value = "{{{path}}}",{{#singleContentTypes}}{{#hasProduces}}
        produces = "{{{vendorExtensions.x-accepts}}};charset=UTF-8", {{/hasProduces}}{{#hasConsumes}}
        consumes = "{{{vendorExtensions.x-contentType}}};charset=UTF-8",{{/hasConsumes}}{{/singleContentTypes}}{{^singleContentTypes}}{{#hasProduces}}
        produces = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}}{{#hasConsumes}}
        consumes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} },{{/hasConsumes}}{{/singleContentTypes}}
        method = RequestMethod.{{httpMethod}})
    {{>returnTypes}} {{operationId}}(@RequestHeader(value = "hmac-signature") String authorization, {{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{/allParams}});

{{/operation}}
}
{{/operations}}
Steps to reproduce

You have to run via mvn package/install the generate step of openapi-generator-maven-plugin, using a mustache template file.

This is my class generated via mvn clean package:

CrossCoreApiCliente

Related issues/PRs

I haven't found similar issues, but I asked at stack overflow: link

Suggest a fix

Debug and try to reproduce the step within a mustache template, and see how it deals with the multiple parameters, splited with a comma.

I don't know exactly why the guy who wrote this tried to do using mustache and swagger. Someone can help us? Thank you!

I'm expecting to understand if open-api-generator use the same tag for templates, and why we are facing a Illegal start of expression. Why is there a missing comma? Is this a bug of open-api-generator when using mustache templates?

wing328 commented 1 year ago

Illegal start of expression ',', ')', or '[' expected

looks like the spec is invalid

openapi generator also supports openapi/swagger spec 2.0 so you can use it directly without using any converter.