OpenAPI кодогенерация
Модуль для создания декларативных HTTP-обработчиков HTTP сервера либо создания декларативных HTTP клиентов из OpenAPI контрактов с использованием OpenAPI Generator плагином.
Подключение¶
Зависимость генератора build.gradle
:
Зависимость плагина build.gradle
:
Зависимость build.gradle.kts
:
Зависимость плагина build.gradle.kts
:
Требует подключения HTTP сервера либо HTTP клиента.
Конфигурация¶
Конфигурировать требуется параметры плагина OpenAPI Generator:
- Настройка параметров Gradle плагина в документации.
- Настройка
configOptions
параметра плагина в документации. - Настройка
openapiNormalizer
параметра плагина в документации.
Клиент¶
Минимальный пример настройки плагина для создания декларативного HTTP клиента:
Доступные Kora параметры плагина (configOptions
):
clientConfigPrefix
- префикс конфигурации созданных HTTP-клиентовtags
- возможность проставлять дополнительные теги на созданные HTTP-клиентыinterceptors
- возможность указывать перехватчики для HTTP-клиентовprimaryAuth
- указать какой механизм авторизации использовать как основной если указано несколько securitySchemes в OpenAPIsecurityConfigPrefix
- префикс конфигурации механизм авторизации Basic/ApiKey (путь конфигурации будет заданный префикс + имя securitySchemes в OpenAPI, либо просто имя в OpenAPI если префикс не задан)authAsMethodArgument
- возможность указывать авторизацию как аргумент метода HTTP клиента, а не через перехватчикadditionalContractAnnotations
- возможность указывать дополнительные аннотации над методами HTTP-клиентаenableJsonNullable
- обрабатыватьnullable=true
иrequired=false
поля схем как JsonNullable оберткуmode
в каком режиме работать генератору, доступные значения:java-client
- создание синхронного клиентаjava-async-client
- создание CompletionStage клиентаjava-reactive-client
- создание реактивного клиента, требуется подключить Project Reactor самостоятельно.
openApiGenerate {
generatorName = "kora"
group = "openapi tools"
inputSpec = "$projectDir/src/main/resources/openapi/openapi.yaml" //(1)!
outputDir = "$buildDir/generated/openapi" //(2)!
apiPackage = "ru.tinkoff.kora.example.openapi.api" //(3)!
modelPackage = "ru.tinkoff.kora.example.openapi.model" //(4)!
invokerPackage = "ru.tinkoff.kora.example.openapi.invoker" //(5)!
openapiNormalizer = [
DISABLE_ALL: "true"
]
configOptions = [
mode: "java-client", //(6)!
clientConfigPrefix: "httpClient.myclient" //(7)!
]
}
- Путь до OpenAPI файла из которого будут созданы классы
- Директория куда буду создаваться файлы
- Пакет от классов делегатов, контроллеров, преобразователей и тп.
- Пакет от классов моделей, DTO и тп.
- Пакет от классов вызова
- Режим работы плагина (создание Java клиента / Kotlin / Java сервера и тп)
- Префикс путь к файлу конфигурации клиента
Доступные Kora параметры плагина (configOptions
):
clientConfigPrefix
- префикс конфигурации созданных HTTP-клиентовtags
- возможность проставлять дополнительные теги на созданные HTTP-клиентыinterceptors
- возможность указывать перехватчики для HTTP-клиентовprimaryAuth
- указать какой механизм авторизации использовать как основной если указано несколько securitySchemes в OpenAPIsecurityConfigPrefix
- префикс конфигурации механизм авторизации Basic/ApiKey (путь конфигурации будет заданный префикс + имя securitySchemes в OpenAPI, либо просто имя в OpenAPI если префикс не задан)authAsMethodArgument
- возможность указывать авторизацию как аргумент метода HTTP клиента, а не через перехватчикadditionalContractAnnotations
- возможность указывать дополнительные аннотации над методами HTTP-клиентаenableJsonNullable
- обрабатыватьnullable=true
иrequired=false
поля схем как JsonNullable оберткуmode
в каком режиме работать генератору, доступные значения:kotlin-client
- создание синхронного клиентаkotlin-suspend-client
- создание suspend клиента
openApiGenerate {
generatorName = "kora"
group = "openapi tools"
inputSpec = "$projectDir/src/main/resources/openapi/openapi.yaml" //(1)!
outputDir = "$buildDir/generated/openapi" //(2)!
apiPackage = "ru.tinkoff.kora.example.openapi.api" //(3)!
modelPackage = "ru.tinkoff.kora.example.openapi.model" //(4)!
invokerPackage = "ru.tinkoff.kora.example.openapi.invoker" //(5)!
openapiNormalizer = mapOf(
"DISABLE_ALL" to "true"
)
configOptions = mapOf(
"mode" to "kotlin-client", //(6)!
"clientConfigPrefix" to "httpClient.myclient" //(7)!
)
}
- Путь до OpenAPI файла из которого будут созданы классы
- Директория куда буду создаваться файлы
- Пакет от классов делегатов, контроллеров, преобразователей и тп.
- Пакет от классов моделей, DTO и тп.
- Пакет от классов вызова
- Режим работы плагина (создание Java клиента / Kotlin / Java сервера и тп)
- Префикс путь к файлу конфигурации клиента
После создания HTTP-клиент будет доступен для внедрения как зависимость по созданному интерфейсу.
Перехватчики¶
Есть возможность на созданные клиенты с @HttpClient
аннотацией поставить перехватчики.
Значение - Json объект, ключом которого выступает тег апи из контракта, а значением объект с полями type
и tag
,
можно указывать как оба поля одновременно, так и опционально одно из них на выбор где:
type
- класс реализации конкретного перехватчикаtag
- теги перехватчика (можно указать как массив строк)
Для этого необходимо установить параметр configOptions.interceptors
:
openApiGenerate {
generatorName = "kora"
group = "openapi tools"
inputSpec = "$projectDir/src/main/resources/openapi/openapi.yaml"
outputDir = "$buildDir/generated/openapi"
apiPackage = "ru.tinkoff.kora.example.openapi.api"
modelPackage = "ru.tinkoff.kora.example.openapi.model"
invokerPackage = "ru.tinkoff.kora.example.openapi.invoker"
openapiNormalizer = [
DISABLE_ALL: "true"
]
configOptions = [
mode: "java-client",
interceptors: """
{
"*": [
{
"tag": "ru.tinkoff.example.MyTag"
}
],
"pet": [
{
"type": "ru.tinkoff.example.MyInterceptor"
}
],
"shop": [
{
"type": "ru.tinkoff.example.MyInterceptor",
"tag": "ru.tinkoff.example.MyTag"
}
]
}
"""
]
}
openApiGenerate {
generatorName = "kora"
group = "openapi tools"
inputSpec = "$projectDir/src/main/resources/openapi/openapi.yaml"
outputDir = "$buildDir/generated/openapi"
apiPackage = "ru.tinkoff.kora.example.openapi.api"
modelPackage = "ru.tinkoff.kora.example.openapi.model"
invokerPackage = "ru.tinkoff.kora.example.openapi.invoker"
openapiNormalizer = mapOf(
"DISABLE_ALL" to "true"
)
configOptions = mapOf(
"mode" to "kotlin-client",
"interceptors" to """{
"*": [
{
"tag": "ru.tinkoff.example.MyTag"
}
],
"pet": [
{
"type": "ru.tinkoff.example.MyInterceptor"
}
],
"shop": [
{
"type": "ru.tinkoff.example.MyInterceptor",
"tag": "ru.tinkoff.example.MyTag"
}
]
}
"""
)
}
Теги¶
Есть возможность на созданные клиенты с @HttpClient
аннотацией поставить параметры httpClientTag
и telemetryTag
.
Значение - Json объект, ключом которого выступает тег апи из контракта, а значением объект с полями httpClientTag
и telemetryTag
.
Для этого необходимо установить параметр configOptions.tags
:
openApiGenerate {
generatorName = "kora"
group = "openapi tools"
inputSpec = "$projectDir/src/main/resources/openapi/openapi.yaml"
outputDir = "$buildDir/generated/openapi"
apiPackage = "ru.tinkoff.kora.example.openapi.api"
modelPackage = "ru.tinkoff.kora.example.openapi.model"
invokerPackage = "ru.tinkoff.kora.example.openapi.invoker"
openapiNormalizer = [
DISABLE_ALL: "true"
]
configOptions = [
mode: "java-client",
clientConfigPrefix: "httpClient.myclient",
tags: """
{
"*": { // применится для всех тегов, кроме явно указанных (в данном случае instrument)
"httpClientTag": "some.tag.Common",
"telemetryTag": "some.tag.Common"
},
"instrument": { // применится для instrument
"httpClientTag": "some.tag.Instrument",
"telemetryTag": "some.tag.Instrument"
}
}
"""
]
}
openApiGenerate {
generatorName = "kora"
group = "openapi tools"
inputSpec = "$projectDir/src/main/resources/openapi/openapi.yaml"
outputDir = "$buildDir/generated/openapi"
apiPackage = "ru.tinkoff.kora.example.openapi.api"
modelPackage = "ru.tinkoff.kora.example.openapi.model"
invokerPackage = "ru.tinkoff.kora.example.openapi.invoker"
openapiNormalizer = mapOf(
"DISABLE_ALL" to "true"
)
configOptions = mapOf(
"mode" to "kotlin-client",
"clientConfigPrefix" to "httpClient.myclient",
"tags" to """{
"*": { // применится для всех тегов, кроме явно указанных (в данном случае instrument)
"httpClientTag": "some.tag.Common",
"telemetryTag": "some.tag.Common"
},
"instrument": { // применится для instrument
"httpClientTag": "some.tag.Instrument",
"telemetryTag": "some.tag.Instrument"
}
}
"""
)
}
Сервер¶
Минимальный пример настройки плагина для создания обработчиков HTTP-сервера:
Доступные Kora параметры плагина (configOptions
):
enableServerValidation
- создавать ли валидаторы по описанию OpenAPI сецификации для сервера и включать ли валидацию на HTTP-обработчиках:true, false
requestInDelegateParams
- прокидывать лиHttpServerRequest
принудительно как аргумент метода:true, false
interceptors
- возможность указывать перехватчики для HTTP-контроллеровadditionalContractAnnotations
- возможность указывать дополнительные аннотации над методами контроллераenableJsonNullable
- обрабатыватьnullable=true
иrequired=false
поля схем как JsonNullable оберткуmode
в каком режиме работать генератору, доступные значения:java-server
- создание синхронного сервераjava-async-server
- создание CompletionStage сервераjava-reactive-server
- создание реактивного сервера, требуется подключить Project Reactor самостоятельно.
openApiGenerate {
generatorName = "kora"
group = "openapi tools"
inputSpec = "$projectDir/src/main/resources/openapi/openapi.yaml" //(1)!
outputDir = "$buildDir/generated/openapi" //(2)!
apiPackage = "ru.tinkoff.kora.example.openapi.api" //(3)!
modelPackage = "ru.tinkoff.kora.example.openapi.model" //(4)!
invokerPackage = "ru.tinkoff.kora.example.openapi.invoker" //(5)!
openapiNormalizer = [
DISABLE_ALL: "true"
]
configOptions = [
mode: "java-server" //(6)!
]
}
- Путь до OpenAPI файла из которого будут созданы классы
- Директория куда буду создаваться файлы
- Пакет от классов делегатов, контроллеров, преобразователей и тп.
- Пакет от классов моделей, DTO и тп.
- Пакет от классов вызова
- Режим работы плагина (создание Java клиента / Kotlin / Java сервера и тп)
Доступные Kora параметры плагина (configOptions
):
enableServerValidation
- создавать ли валидаторы по описанию OpenAPI сецификации для сервера и включать ли валидацию на HTTP-обработчиках:true, false
requestInDelegateParams
- прокидывать лиHttpServerRequest
принудительно как аргумент метода:true, false
interceptors
- возможность указывать перехватчики для HTTP-контроллеровadditionalContractAnnotations
- возможность указывать дополнительные аннотации над методами контроллераenableJsonNullable
- обрабатыватьnullable=true
иrequired=false
поля схем как JsonNullable оберткуmode
в каком режиме работать генератору, доступные значения:kotlin-server
- создание синхронного сервераkotlin-suspend-server
- создание suspend сервера
openApiGenerate {
generatorName = "kora"
group = "openapi tools"
inputSpec = "$projectDir/src/main/resources/openapi/openapi.yaml" //(1)!
outputDir = "$buildDir/generated/openapi" //(2)!
apiPackage = "ru.tinkoff.kora.example.openapi.api" //(3)!
modelPackage = "ru.tinkoff.kora.example.openapi.model" //(4)!
invokerPackage = "ru.tinkoff.kora.example.openapi.invoker" //(5)!
openapiNormalizer = mapOf(
"DISABLE_ALL" to "true"
)
configOptions = mapOf(
"mode" to "kotlin-server" //(6)!
)
}
- Путь до OpenAPI файла из которого будут созданы классы
- Директория куда буду создаваться файлы
- Пакет от классов делегатов, контроллеров, преобразователей и тп.
- Пакет от классов моделей, DTO и тп.
- Пакет от классов вызова
- Режим работы плагина (создание Java клиента / Kotlin / Java сервера и тп)
После создания обработчики будут автоматически зарегистрированы.
Валидация¶
Для генерации моделей и контроллеров с аннотациями из модуля валидации необходимо установить опцию enableServerValidation
:
openApiGenerate {
generatorName = "kora"
group = "openapi tools"
inputSpec = "$projectDir/src/main/resources/openapi/openapi.yaml"
outputDir = "$buildDir/generated/openapi"
apiPackage = "ru.tinkoff.kora.example.openapi.api"
modelPackage = "ru.tinkoff.kora.example.openapi.model"
invokerPackage = "ru.tinkoff.kora.example.openapi.invoker"
openapiNormalizer = [
DISABLE_ALL: "true"
]
configOptions = [
mode: "java-server",
enableServerValidation: "true" //(1)!
]
}
- Включение валидации на стороне контроллера HTTP сервера
openApiGenerate {
generatorName = "kora"
group = "openapi tools"
inputSpec = "$projectDir/src/main/resources/openapi/openapi.yaml"
outputDir = "$buildDir/generated/openapi"
apiPackage = "ru.tinkoff.kora.example.openapi.api"
modelPackage = "ru.tinkoff.kora.example.openapi.model"
invokerPackage = "ru.tinkoff.kora.example.openapi.invoker"
openapiNormalizer = mapOf(
"DISABLE_ALL" to "true"
)
configOptions = mapOf(
"mode" to "kotlin-server",
"enableServerValidation" to "true" //(1)!
)
}
- Включение валидации на стороне контроллера HTTP сервера
Перехватчики¶
Есть возможность на созданные контроллеры с @HttpController
аннотацией поставить перехватчики.
Значение - Json объект, ключом которого выступает тег апи из контракта, а значением объект с полями type
и tag
,
можно указывать как оба поля одновременно, так и опционально одно из них на выбор где:
type
- класс реализации конкретного перехватчикаtag
- теги перехватчика (можно указать как массив строк)
Для этого необходимо установить параметр configOptions.interceptors
:
openApiGenerate {
generatorName = "kora"
group = "openapi tools"
inputSpec = "$projectDir/src/main/resources/openapi/openapi.yaml"
outputDir = "$buildDir/generated/openapi"
apiPackage = "ru.tinkoff.kora.example.openapi.api"
modelPackage = "ru.tinkoff.kora.example.openapi.model"
invokerPackage = "ru.tinkoff.kora.example.openapi.invoker"
openapiNormalizer = [
DISABLE_ALL: "true"
]
configOptions = [
mode: "java-server",
interceptors: """
{
"*": [
{
"tag": "ru.tinkoff.example.MyTag"
}
],
"pet": [
{
"type": "ru.tinkoff.example.MyInterceptor"
}
],
"shop": [
{
"type": "ru.tinkoff.example.MyInterceptor",
"tag": "ru.tinkoff.example.MyTag"
}
]
}
"""
]
}
openApiGenerate {
generatorName = "kora"
group = "openapi tools"
inputSpec = "$projectDir/src/main/resources/openapi/openapi.yaml"
outputDir = "$buildDir/generated/openapi"
apiPackage = "ru.tinkoff.kora.example.openapi.api"
modelPackage = "ru.tinkoff.kora.example.openapi.model"
invokerPackage = "ru.tinkoff.kora.example.openapi.invoker"
openapiNormalizer = mapOf(
"DISABLE_ALL" to "true"
)
configOptions = mapOf(
"mode" to "kotlin-server",
"interceptors" to """{
"*": [
{
"tag": "ru.tinkoff.example.MyTag"
}
],
"pet": [
{
"type": "ru.tinkoff.example.MyInterceptor"
}
],
"shop": [
{
"type": "ru.tinkoff.example.MyInterceptor",
"tag": "ru.tinkoff.example.MyTag"
}
]
}
"""
)
}
Рекомендации¶
Совет
В случае если у вас что-то не создается посредствам плагина, либо поведение отличается от желаемого или других версий, требуется тщательно проверить настройки конфигурации плагина и изучить их, так как они могут влиять на результаты того как создаются классы.
Начиная с 7.0.0
версии плагина, включенное по умолчанию SIMPLIFY_ONEOF_ANYOF
правило у параметра openapiNormalizer
может вести к некоторым не очевидным результатам генератора.