OpenAPI codegen
Module for creating declarative HTTP handlers HTTP server or create declarative HTTP clients from OpenAPI contracts using OpenAPI Generator plugin.
Dependency¶
Dependency build.gradle
:
Plugin dependency build.gradle
:
Dependency build.gradle.kts
:
Plugin dependency build.gradle.kts
:
Requires HTTP server or HTTP client module.
Configuration¶
Configuration is required for OpenAPI Generator plugin parameters:
- Configuring Gradle plugin parameters in documentation.
- Configuring
configOptions
plugin parameter in documentation. - Configuring
openapiNormalizer
plugin parameter in documentation.
Client¶
A minimal example of configuring a plugin to create a declarative HTTP client:
Kora's available plugin options:
clientConfigPrefix
- configuration prefix of created HTTP clientstags
- possibility to put additional tags on created HTTP-clientsinterceptors
- ability to specify interceptors for HTTP clientsprimaryAuth
- specify which authorization mechanism to use as the primary one if several securitySchemes are specified in OpenAPIsecurityConfigPrefix
- prefix of authorization mechanism configuration Basic/ApiKey (configuration path will be specified prefix + name securitySchemes in OpenAPI, or just name in OpenAPI if prefix is not specified).authAsMethodArgument
- ability to specify authorization as an argument of an HTTP client method rather than through an interceptoradditionalContractAnnotations
- ability to specify additional annotations over HTTP client methodsenableJsonNullable
- Treatnullable=true
andrequired=false
schema fields as a JsonNullable wrappermode
in which mode the generator should operate, available values:java-client
- create synchronous clientjava-async-client
- create CompletionStage clientjava-reactive-client
- create reactive client, you need to connect Project Reactor yourself.
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)!
]
}
- Path to OpenAPI file from which classes will be created
- Directory where the files will be created
- Package from classes of delegates, controllers, converters, etc.
- Package from classes of models, DTOs, etc.
- Package from calling classes
- Mode of plugin operation (creating Java client / Kotlin / Java server, etc.)
- Prefix path to client configuration file
Kora's available plugin options:
clientConfigPrefix
- configuration prefix of created HTTP clientstags
- possibility to put additional tags on created HTTP-clientsinterceptors
- ability to specify interceptors for HTTP clientsprimaryAuth
- specify which authorization mechanism to use as the primary one if several securitySchemes are specified in OpenAPIsecurityConfigPrefix
- prefix of authorization mechanism configuration Basic/ApiKey (configuration path will be specified prefix + name securitySchemes in OpenAPI, or just name in OpenAPI if prefix is not specified).authAsMethodArgument
- ability to specify authorization as an argument of an HTTP client method rather than through an interceptoradditionalContractAnnotations
- ability to specify additional annotations over HTTP client methodsenableJsonNullable
- Treatnullable=true
andrequired=false
schema fields as a JsonNullable wrappermode
in which mode the generator should operate, available values:kotlin-client
- create synchronous clientkotlin-suspend-client
- create suspend client
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)!
)
}
- Path to OpenAPI file from which classes will be created
- Directory where the files will be created
- Package from classes of delegates, controllers, converters, etc.
- Package from classes of models, DTOs, etc.
- Package from calling classes
- Mode of plugin operation (creating Java client / Kotlin / Java server, etc.)
- Prefix path to client configuration file
Once created, the HTTP client will be available for deployment as a dependency on the created interface.
Interceptors¶
It is possible to put interceptors on created clients with @HttpClient
annotation.
The value is a Json object whose key is the api tag from the contract, and the value is an object with type
and tag
fields,
it is possible to specify both fields at the same time, or optionally one of them:
type
- the implementation class of a particular interceptortag
- tags of the interceptor (can be specified as an array of strings).
In order to do this, set the configOptions.interceptors
parameter:
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"
}
]
}
"""
)
}
Tags¶
It is possible to put parameters httpClientTag
and telemetryTag
on created clients with @HttpClient
annotation.
The value is a Json object, the key of which is the api tag from the contract, and the value is the object with the fields httpClientTag
and telemetryTag
.
For this purpose it is necessary to set the configOptions.tags
parameter:
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: """
{
"*": { // applies to all tags except those explicitly specified (in this case, instrument)
"httpClientTag": "some.tag.Common.class",
"telemetryTag": "some.tag.Common.class"
},
"instrument": { // apply to instrument
"httpClientTag": "some.tag.Instrument.class",
"telemetryTag": "some.tag.Instrument.class"
}
}
"""
]
}
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 """{
"*": { // applies to all tags except those explicitly specified (in this case, instrument)
"httpClientTag": "some.tag.Common.class",
"telemetryTag": "some.tag.Common.class"
},
"instrument": { // apply to instrument
"httpClientTag": "some.tag.Instrument.class",
"telemetryTag": "some.tag.Instrument.class"
}
}
"""
)
}
Server¶
A minimal example of configuring a plugin to create HTTP server handlers:
Available Kora plugin parameters:
enableServerValidation
- whether to create validators according to the OpenAPI secification description for the server and whether to enable validation on HTTP handlers:true, false
.requestInDelegateParams
- whether to expectedHttpServerRequest
as a method argument:true, false
interceptors
- ability to specify interceptors for HTTP controllersadditionalContractAnnotations
- ability to specify additional annotations for controller methodsenableJsonNullable
- Treatnullable=true
andrequired=false
schema fields as a JsonNullable wrappermode
in which mode the generator should operate, available values:java-server
- create a synchronous serverjava-async-server
- create a CompletionStage serverjava-reactive-server
- create a reactive server, you need to connect Project Reactor yourself.
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)!
]
}
- Path to OpenAPI file from which classes will be created
- Directory where the files will be created
- Package from classes of delegates, controllers, converters, etc.
- Package from classes of models, DTOs, etc.
- Package from calling classes
- Mode of plugin operation (creating Java client / Kotlin / Java server, etc.)
Available Kora plugin parameters:
enableServerValidation
- whether to create validators according to the OpenAPI secification description for the server and whether to enable validation on HTTP handlers:true, false
.requestInDelegateParams
- whether to expectedHttpServerRequest
as a method argument:true, false
interceptors
- ability to specify interceptors for HTTP controllersadditionalContractAnnotations
- ability to specify additional annotations for controller methodsenableJsonNullable
- Treatnullable=true
andrequired=false
schema fields as a JsonNullable wrappermode
in which mode the generator should operate, available values:kotlin-server
- create synchronous serverkotlin-suspend-server
- create suspend server
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)!
)
}
- Path to OpenAPI file from which classes will be created
- Directory where the files will be created
- Package from classes of delegates, controllers, converters, etc.
- Package from classes of models, DTOs, etc.
- Package from calling classes
- Mode of plugin operation (creating Java client / Kotlin / Java server, etc.)
Once created, the handlers will be automatically registered.
Validation¶
In order to generate models and controllers with annotations from the validation module, the enableServerValidation
option must be set:
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)!
]
}
- Enabling validation on the HTTP server controller side
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)!
)
}
- Enabling validation on the HTTP server controller side
Interceptors¶
It is possible to put interceptors on created controllers with @HttpController
annotation.
The value is a Json object whose key is the api tag from the contract, and the value is an object with type
and tag
fields,
it is possible to specify both fields at the same time, or optionally one of them:
type
- the implementation class of a particular interceptortag
- tags of the interceptor (can be specified as an array of strings).
In order to do this, set the configOptions.interceptors
parameter:
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"
}
]
}
"""
)
}
Recommendations¶
????+ warning "Advice"
In case you have something that is not created by the plugin, or the behavior is different from what you want or other versions,
you should carefully check the [plugin configuration](#configuration) settings and examine them,
as they may affect the results of how classes are created.
Starting with `7.0.0` version of the plugin, the `SIMPLIFY_ONEOF_ANYOF` rule enabled by default at the `openapiNormalizer` parameter
may lead to some not obvious generator results.