swagger codegen перезаписывает мой пользовательский код в сгенерированных файлах

Я использовал swagger codegen для создания классов на стороне сервера jaxrs, а также классов Java на стороне клиента.

Это команда, которую я использовал для создания классов

java -jar modules/swagger-codegen-distribution/target/swagger-codegen-distribution-2.1.2-M1.jar   -i /Users/me/Workspace/swagger-codegen/samples/yaml/echo.yaml   -l jaxrs   -o samples/server/echo/java

В сгенерированном коде сервера было место для написания моей «магии».

public Response echo(@ApiParam(value = ""  )@HeaderParam("headerParam") String headerParam,
    @ApiParam(value = "",required=true) @QueryParam("message") String message)
      throws NotFoundException {
      // do some magic!
      return Response.ok().entity(new ApiResponseMessage(ApiResponseMessage.OK, "magic!")).build();
  }

Я добавил «магию» в метод «эхо» и перегенерировал код только для того, чтобы увидеть, как он стерся. Один из способов избежать потери пользовательского кода — изменить шаблон codegen для создания интерфейса вместо класса. Тогда я могу иметь весь пользовательский код в реализованном классе.

Я пытаюсь выяснить, есть ли способ сохранить пользовательскую «магию» даже после повторной генерации кода или есть ли лучший способ справиться с этой ситуацией, чем изменение шаблона для создания интерфейсов вместо классов.


person Nikhil S    schedule 25.03.2015    source источник
comment
См. также grokbase.com/t/gg/ swagger-swaggersocket/153s7d49nr/   -  person Martin Schröder    schedule 19.08.2015


Ответы (3)


Последний мастер Swagger Codegen позволяет указывать файлы не для перезаписи в .swagger-codegen-ignore (аналогично .gitignore) во время генерации кода.

Пожалуйста, скачайте последний мастер Swagger Codegen, чтобы попробовать.

ОБНОВЛЕНИЕ: в мае 2018 года около 50 ведущих участников и создателей шаблонов Swagger Codegen решили разветвить Swagger Codegen, чтобы поддерживать управляемую сообществом версию под названием Генератор OpenAPI. Дополнительные сведения см. в разделе Q&A.

person William Cheng    schedule 08.07.2016
comment
Каков ваш рабочий процесс слияния нового шаблонного кода конечной точки после добавления файлов в .swagger-codegen-ignore? - person Matt Kim; 21.06.2017
comment
Он действительно должен генерировать класс с методами, а не только с функциями. Тогда мы могли бы чисто подклассировать его. - person Evgeni Sergeev; 22.03.2018


Здравствуйте,
может быть, через четыре года ответ приходит с небольшим опозданием, но лучше поздно, чем никогда.

Если у вас есть правильный файл swagger (а не только фрагмент), например следующий

openapi: "3.0.0"
:
paths:
  /example:
    get:
      operationId: showIt
:

и вы запускаете генерацию кода в этом объяснении для jaxs-jersey-server без каких-либо значений конфигурации, специфичных для генерации кода (которые вы можете загрузить из редактор Swagger), вы получаете множество классов Java, например:

io.swagger.api.          ExampleApi
io.swagger.api.          ExampleApiService
io.swagger.api.factories.ExampleApiServicefactory
io.swagger.api.impl.     ExampleApiServiceImpl

В реализации конечной точки REST ExampleApiServiceImpl вы видите примерно следующее:

package io.swagger.api.impl;

:
import ... ;
:

@javax.annotation.Generated(...)
public
class   ExampleApiServiceImpl
extends ExampleApiService
{
    // ...
    @Override
    public
    Response showIt( /* additional parameters , */ SecurityContext securityContext)
    throws NotFoundException
    {
        // do some magic!
        return Response.ok()
                       .entity(new ApiResponseMessage( ApiResponseMessage.OK
                                                     , "magic!"
                                                     )
                              )
                       .build();
    }
    // ...
}

Вы теперь обмениваетесь волшебным комментарием

        // do some magic!

возможно через следующее

        String className = this.getClass().getSimpleName();
        System.out.println("Entered REST endpoint: path=|" + className.substring(0, className.length() - 14) + "| operationId=|showId|");

вы должны увидеть сообщение в журнале, если вы вызываете конечную точку из своего браузера после того, как вы выполнили mvn clean package jetty:run. Но это не очень хорошая идея, как вы поняли, потому что после следующего поколения ваше изменение исчезнет.

В этом контексте никогда не рекомендуется изменять сгенерированный код вручную, потому что это ДОЛЖНО быть затем настолько хорошо задокументировано, что будущий коллега (которым через несколько месяцев или лет может быть даже вы ) даже в полудреме по воскресеньям ночи понедельника снова вносит изменения после очередной генерации кода. Но мой более чем 20-летний опыт работы с разными генераторами кода говорит по этому поводу только одно: Забудьте об этом! По той же причине нецелесообразно предотвращать дальнейшее поколение после первого поколения, потому что это тоже должно быть подробно задокументировано. В противном случае час отладки за час отладки может привести к устранению неполадок, почему новая функция не работает.

Но это совсем не обязательно.
В сгенерированном классе io.swagger.api.ExampleApi вы найдете конструктор, подобный следующему (Хорошо, это состояние на 17 мая 2019 г. Я не знаю, было ли это так же (или похоже) четыре года назад)

package io.swagger.api;

:
import ... ;
:

@Path("/example")

@javax.annotation.Generated(...)
public class ExampleApi
{
   private final ExampleApiService delegate;

   public ExampleApi(@Context ServletConfig servletContext)
   {
      // ...
      if (servletContext != null) {
         String implClass = servletContext.getInitParameter("ExampleApi.implementation");
         if (implClass != null && !"".equals(implClass.trim()))
         {
            try
            {
               delegate = (ExampleApiService) Class.forName(implClass).newInstance();
            }
            catch (Exception e)
            {
               throw new RuntimeException(e);
            }
         } 
      }
      // ...
    }
// ...
}

Важным фрагментом кода является файл servletContext.getInitParameter("..."). Если теперь вы укажете в конфигурации сервлета ключ с именем ExampleApi.implementation с полным квалифицированным именем класса Java, полученным из ExampleApiService, вы реализуете свой собственный код конечной точки, который защищен от перезаписи в будущих поколениях кода.

Для завершения примера эта спецификация должна быть сделана в (дополнительно сгенерированном, оууууу, извините, вы не можете иметь все) web.xml файле. Этот файл содержит что-то вроде:

    <servlet>
        <servlet-name>jersey</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        ...
        <load-on-startup>1</load-on-startup>
    </servlet>

В этом XML-фрагменте вы должны вставить после точек (которые обозначают другие параметры конфигурации сервлета) следующее:

        <init-param>
            <param-name>ExampleApi.implementation</param-name>
            <param-value>my.swagger.api.MyExample</param-value>
        </init-param>

Смотри,
кем бы ты ни был!

person Chris    schedule 17.05.2019
comment
не могли бы вы дать некоторые ответы на мой вопрос stackoverflow.com/q/58521289/1700711 - person saravanakumar; 23.10.2019
comment
На самом деле это также работает с плагином codegen maven openapi! .openapi-generator-ignore будет сгенерирован в каталоге target/generated-sources и не может/не должен обновляться, так что это лучшее решение для пользователей mvn. - person Almer; 25.06.2020

Вы можете указать файлы, которые хотите игнорировать, в .swagger-codegen-ignore файле

Вот пример понятного автоматически сгенерированного кода для файла .swagger-codegen-ignore.

# Swagger Codegen Ignore
# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen

# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.

# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line:
#ApiClient.cs

# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux

# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux

# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

Вы можете добавить несколько строк ниже этого, чтобы игнорировать, например. Я хочу игнорировать все файлы в папке impl, поэтому для этого я добавил следующую строку

**/impl/*
person Asad Shakeel    schedule 02.01.2019