openapi-generator-maven-plugin добавляет кавычки в перечисление, а swagger-ui использует их, вызывая ошибку

У нас есть такие услуги, как:

openapi: "3.0.0"
info:
  version: 1.0.0
  title: UVZ Reg
paths:
  /enumerationRequestApproval/{requestId}/{approvalStatus}:
    post:
      tags: 
        - EnumerationApprovalController
      parameters:
       - in: path
         name: requestId
         schema:
           type: integer
           format: int64
         required: true
       - in: path
         name: approvalStatus
         schema:
           $ref: "#/components/schemas/enumerationApprovalStatusEnum"
         required: true
      responses:
        200:
          description: status of enumeration approval changed
components:
  schemas:
    enumerationApprovalStatusEnum:
      type: string
      enum:
        - WAITING_APPROVAL
        - APPROVED
        - NOT_APPROVED

С помощью openapi-generator-maven-plugin мы генерируем сервис весенней загрузки:

@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2020-07-30T09:35:26.969160+02:00[Europe/Bratislava]")

@Validated
@Api(value = "enumerationRequestApproval", description = "the enumerationRequestApproval API")
public interface EnumerationRequestApprovalApi {

    default Optional<NativeWebRequest> getRequest() {
        return Optional.empty();
    }

    /**
     * POST /enumerationRequestApproval/{requestId}/{approvalStatus}
     *
     * @param requestId  (required)
     * @param approvalStatus  (required)
     * @return status of enumeration approval changed (status code 200)
     */
    @ApiOperation(value = "", nickname = "enumerationRequestApprovalRequestIdApprovalStatusPost", notes = "", tags={ "EnumerationApprovalController", })
    @ApiResponses(value = { 
        @ApiResponse(code = 200, message = "status of enumeration approval changed") })
    @RequestMapping(value = "/enumerationRequestApproval/{requestId}/{approvalStatus}",
        method = RequestMethod.POST)
    default ResponseEntity<Void> enumerationRequestApprovalRequestIdApprovalStatusPost(@ApiParam(value = "",required=true) @PathVariable("requestId") Long requestId,@ApiParam(value = "",required=true, allowableValues = "\"WAITING_APPROVAL\", \"APPROVED\", \"NOT_APPROVED\"") @PathVariable("approvalStatus") EnumerationApprovalStatusEnum approvalStatus) {
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);

    }

}

Теперь, когда мы пытаемся вызвать службу из swagger-ui (http: // localhost: 8080 / swagger-ui), это не сработает:

org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'sk.uvzsr.is.reg.be.rest.model.EnumerationApprovalStatusEnum'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@io.swagger.annotations.ApiParam @org.springframework.web.bind.annotation.PathVariable sk.uvzsr.is.reg.be.rest.model.EnumerationApprovalStatusEnum] for value '"WAITING_APPROVAL"'; nested exception is java.lang.IllegalArgumentException: No enum constant sk.uvzsr.is.reg.be.rest.model.EnumerationApprovalStatusEnum."WAITING_APPROVAL"
    at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:133)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at sk.uvzsr.is.reg.config.CorsFilter.doFilter(CorsFilter.java:43)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1594)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@io.swagger.annotations.ApiParam @org.springframework.web.bind.annotation.PathVariable sk.uvzsr.is.reg.be.rest.model.EnumerationApprovalStatusEnum] for value '"WAITING_APPROVAL"'; nested exception is java.lang.IllegalArgumentException: No enum constant sk.uvzsr.is.reg.be.rest.model.EnumerationApprovalStatusEnum."WAITING_APPROVAL"
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:191)
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:129)
    at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:73)
    at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:53)
    at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:693)
    at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:125)
    ... 50 more
Caused by: java.lang.IllegalArgumentException: No enum constant sk.uvzsr.is.reg.be.rest.model.EnumerationApprovalStatusEnum."WAITING_APPROVAL"
    at java.base/java.lang.Enum.valueOf(Enum.java:266)
    at org.springframework.core.convert.support.StringToEnumConverterFactory$StringToEnum.convert(StringToEnumConverterFactory.java:52)
    at org.springframework.core.convert.support.StringToEnumConverterFactory$StringToEnum.convert(StringToEnumConverterFactory.java:38)
    at org.springframework.core.convert.support.GenericConversionService$ConverterFactoryAdapter.convert(GenericConversionService.java:436)
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41)
    ... 56 more

Ясно, что проблема заключается в кавычках вокруг значения перечисления. Когда я изменился

allowableValues = "\"WAITING_APPROVAL\", \"APPROVED\", \"NOT_APPROVED\"")

to

allowableValues = "WAITING_APPROVAL, APPROVED, NOT_APPROVED")

все работает, но поскольку это сгенерированный API, я не могу каждый раз менять его вручную.

Вот как выглядит API при проектировании (без кавычек):  API показан в плагине Visual Studio, без кавычек Вот как API выглядит развернутым (цитаты добавлены):  API, показанное в развернутом swagger-  ui, в кавычках

Я тестировал это с

  • openapi-generator-maven-plugin версии 4.2.3 и 4.3.1.
  • springfox-swagger-ui 2.9.2 и 3.0.0 (артефакт maven springfox-boot-starter)

Это проблема с openapi-generator-maven-plugin, swagger-ui или моим определением OpenApi3? Как я могу исправить это, чтобы оно работало?


person Piro says Reinstate Monica    schedule 30.07.2020    source источник


Ответы (2)


Чтобы исправить это, нам просто нужно было исправить некорректную аннотацию @ApiParam в контроллере, реализующем сгенерированный интерфейс. Итак, в контроллере, где сгенерированный метод переопределен и реализован, мы указываем @ApiParam с правильными значениями:

@Override
public ResponseEntity<sk.uvzsr.is.reg.be.rest.model.EnumerationRequest> enumerationRequestApprovalRequestIdApprovalStatusPost(Long requestId, @ApiParam(value = "",required=true, allowableValues = "WAITING_APPROVAL, APPROVED, NOT_APPROVED") @PathVariable("approvalStatus") EnumerationApprovalStatusEnum approvalStatus) {
    // implementation
}
person Piro says Reinstate Monica    schedule 25.10.2020

Мы исправили это, настроив способ генерации кода плагином maven openapi-generator. Мы просто заменили файл шаблона по умолчанию pathParams.mustache нашей собственной копией, а здесь мы просто удалили целую часть {{#allowableValues}} ..... {{/allowableValues}}

это приводит к тому, что в сгенерированном методе контроллера больше нет разрешенных значений для параметров перечисления. После этого swagger-ui показывает это правильно.

дополнительная информация о настройке шаблона усов: настройка генератора openapi

person Ondrej Barci    schedule 10.06.2021