Вступление
Если есть сервер, то у него есть api и нужно писать клиент к нему.
Конечно, лучше если клиент пишется автоматически: тогда он актуален и содержит меньше ошибок.
Клиенты для HTTP-протокола сейчас принято писать из OpenAPI-спецификаций. Благо они так же в большинстве случаев генерируются сервером автоматически. А когда почему-то генератор не используют, то содержат ошибки и устарели: не надо так.
Swagger-codegen vs openapi-generator
Есть 2 основных генератора swagger-codegen (изначальный) и openapi-generator (его форк).
Если посравнивать:
И посмотреть сколько скачали:
- https://hub.docker.com/r/openapitools/openapi-generator-cli (10M)
- https://hub.docker.com/r/swaggerapi/swagger-codegen-cli-v3 (0.5M)
то однозначно видно, что openapi-generator более популярен и более активно разрабатывается.
Как же сгенерировать клиентскую библиотеку?
docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate \
-i /local/specs/simple.json \
-g kotlin \
--additional-properties enumPropertyNaming=UPPERCASE \
--additional-properties library=jvm-spring-webclient \
--additional-properties useSpringBoot3=true \
--additional-properties serializationLibrary=jackson \
-o /local/clients/simple
Мы хотим клиент для spring 3 на Котлине.
Чем не устраивает клиент на Java?
- теряем информацию о null
- на нужны корутины
Устраивает ли то, что нагенерировано?
Нет:
- не используются корутины, а значит код перехода на корутины будет в основном приложении – самый большой минус
- не используются интерфейсы клиентов из Spring 3: хуже читабельность
- куча какого-то левого кода в infrastructure пакете – лучше использовать внешнюю зависимость (при желании ее легко можно заменить на свою в файлах сборки основного приложения)
- почему-то ktlint не положили в докер образ и выдают warning об этом (из-за этого неформатированный код)
- странный подход к типам: почему для котлина пишут kotlin.String, а для java не пишут java.lang.String?
А может в другом проекте лучше?
Нет, там примерно то же самое.
Что же делать?
Дописываем.
Новые параметры:
--library=jvm-spring-http-interface --additional-properties useCoroutines=true
– включает генерацию интерфейсов с корутинами--global-property apiTests=false,modelTests=false
– не генерируем тесты (мусор, т.к. мы не собираемся их запускать)--additional-properties omitInfrastructureClasses=true
– не генерируем инфраструктурный код (подключим зависимость к основному проекту)- подумал, что не имеет особого смысла подключать зависимость к клиенту, лучше к основному проекту, чтобы потом не заниматься ее исключением
- добавил ktlint в docker-образ
- удалил генерацию стандартных имен классов с префиксом
kotlin.*
Сборка образа:
cd openapi-generator
docker build . -f .hub.cli.dockerfile -t stepin/openapi-generator-cli
#or
./run-in-docker.sh mvn package
cp docker-entrypoint.sh modules/openapi-generator-cli
cd modules/openapi-generator-cli
docker build . -t stepin/openapi-generator-cli
Запуск образа:
docker run --rm -v ${PWD}:/local stepin/openapi-generator-cli generate \
-i /local/specs/simple.json \
-g kotlin \
--library=jvm-spring-http-interface \
--additional-properties groupId=name.stepin \
--additional-properties artifactId=simple-client \
--additional-properties artifactVersion=0.2.0 \
--additional-properties packageName=name.stepin.client.simple \
--additional-properties useSpringBoot3=true \
--additional-properties useCoroutines=true \
--additional-properties serializationLibrary=jackson \
--additional-properties omitInfrastructureClasses=true \
--additional-properties enumPropertyNaming=UPPERCASE \
--global-property apiTests=false,modelTests=false \
-o /local/clients/simple
Пока что это имеет бета-статус: вроде как для меня все работает, но наверняка найдутся какие-то краевые случаи. Плюс, библиотека подключения http interface клиентов в проект понятна и в черновике написана, но еще не опубликована.