OpenAPI Generator Gradle PluginsをAndroidプロジェクトに導入する
先日、OpenAPI Generator Gradle Pluginsの導入を行いました。
コードの生成自体は非常に役に立ったのですが、詰まるところがあったため記事に起こします。
OpenAPI Generatorとは
OpenAPI Specificationに従って書かれたyamlから、通信部分のコードを生成してくれるプログラムです。本家のGithubから対応している言語など確認することができます。
依存関係を追加
OpenAPI Generator Gradle Pluginsはその名の通り、Gradleのプラグインとして用意されています。
build.gradle.kts
に以下の通りプラグインへの依存関係を記述します。
plugins {
// 投稿時の最新バージョン
id("org.openapi.generator") version "7.5.0"
}
project
、app
のどちらでも動作しますが、複数モジュールで利用するときはバージョンが衝突しないように気をつける必要があります。
これでタスクが利用可能になりました。
$ ./gradlew task
OpenAPI Tools tasks
-------------------
openApiGenerate - Generate code via Open API Tools Generator for Open API 2.0 or 3.x specification documents.
openApiGenerators - Lists generators available via Open API Generators.
openApiMeta - Generates a new generator to be consumed via Open API Generator.
openApiValidate - Validates an Open API 2.0 or 3.x specification document.
build.gradle.ktsにタスクの設定
Gradleのタスクとしては定義されましたが、実際に使えるように設定をしてやる必要があります。
openApiGenerate
プラグインを導入することでopenApiGenerate
という関数が使えるようになります。
この関数を使って設定を行っていきます。
以下に例を示します。
openApiGenerate {
# 生成したいプログラミング言語
generatorName = "kotlin"
# 生成されるコードのパッケージ構成
packageName = "com.package"
# 参照するyamlファイル
inputSpec = "$rootDir/specs/api.yaml"
# 生成されるコードの出力先
outputDir = "$rootDir/data"
# テンプレートファイルの格納先(後述)
templateDir = "$rootDir/templates"
# 通信に使うライブラリ
library = "jvm-retrofit2"
# Selializarに用いるライブラリなどの設定
configOptions = mapOf("serializationLibrary" to "kotlinx_serialization")
# suspend関数を有効化
additionalProperties = mapOf("useCoroutines" to "true")
}
公式のREADME.mdにて詳しく記述されているので、こちらを参考にしつつプロジェクトに合わせて設定していきます。
以上の設定をしてやることでタスクとして使えるようになっているはずです。
./gradlew openApiGenerate
################################################################################
# Thanks for using OpenAPI Generator. #
# Please consider donation to help us maintain this project 🙏 #
# https://opencollective.com/openapi_generator/donate #
# #
# This generator's contributed by Jim Schubert (https://github.com/jimschubert)#
# Please support his work directly via https://patreon.com/jimschubert 🙏 #
################################################################################
Successfully generated code to {path}
無事にタスクが終わるとoutputDir
にて定義した場所にモジュールが追加されると思います。
あとはこのモジュールをsettings.gradle.kts
に追記することで利用可能です。
include(":feature:post")
これで完成としてもいいのですが、微妙に使いづらいところがちょこちょこあります。
そこで、私がプロジェクトに導入させる際に行なったことを書いていきます。
ビルド時に生成されるようにする
初期状態だと、毎回openApiGenerate
タスクを実行する必要があります。
それでもいいのですが、せっかくなのでビルド毎に実行されるように定義します。
以下のコードをbuild.gradle.kts
に追記します。
tasks.getByName("preBuild") {
dependsOn("openApiGenerate")
}
このようにすることで、ビルド前に走るようになってくれます。
gradleファイルの管理
OpenAPI Generatorではコマンドを実行することでモジュールを生成してくれます。
それ自体はいいのですが、そこで生成されてくるbuild.gradle
の内容が微妙に古かったりします。
以下に一部抜粋します。
group 'org.openapitools'
version '1.0.0'
wrapper {
gradleVersion = '7.5'
distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
}
buildscript {
ext.kotlin_version = '1.8.10'
ext.retrofitVersion = '2.10.0'
// 6.13.0 is the latest stable release that supports JDK8
ext.spotless_version = "6.13.0"
repositories {
maven { url "https://repo1.maven.org/maven2" }
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "com.diffplug.spotless:spotless-plugin-gradle:$spotless_version"
}
}
執筆当時では、Gradleは8.7、Kotlinは1.9.23が登場しており、古いバージョンを使っていることがわかります。とはいえ、このコードも自動生成されるので書き直すわけにもいきません。
そこで私のプロジェクトでは、build
ファイルに入れることでソースコードのみ利用する形をとることにしました。
まず、生成コードの配置場所をbuild
ファイル内に変更します。
# 生成されるコードの出力先
+ outputDir = "${layout.buildDirectory.get()}/generated/openapi"
- outputDir = "$rootDir/data"
これでタスクを実行するとbuild/generated/openapi
に生成されたコードが配置されるようになります。
ただ、これだけではコードから呼び出すことができないため以下のようなコードを追記します。
kotlin.sourceSets.main {
kotlin.srcDir("${layout.buildDirectory.get()}/generated/openapi/src/main")
}
上の設定をすることでmain
から生成されたコードを呼び出すことができるようになります。
ここまでのステップを踏むことで、ソースコードのみを利用することが可能になりました。
使うライブラリはタスクを定義したbuild.gradle.kts
で定義してやる必要があります。
dependencies {
# 執筆当時の最新バージョン
api("com.squareup.retrofit2:retrofit:2.11.0")
}
テンプレートを上書き
コードが自動生成されるのは嬉しいのですが、偶に意図していないコードが生成されることがあります。
そのときはテンプレートを上書きしてやることで修正する必要があります。
私の場合、以下のようなケースに衝突しました。
- Retrofitで使うJson ParserとしてKotlinx Serializationを採用していた
- 従来ではKotlinx Serialization Converter Factoryとしてサードパーティ製のライブラリが利用されていた
- 最近本家に統合されたが、OpenAPI Generatorではまだ以前のライブラリを使用している
本ケースの場合、import文を書き換えてやる必要があります。
build.gradle.kts
にて記述した場所にテンプレートを格納するフォルダを作成します。
# テンプレートファイルの格納先(後述)
templateDir = "$rootDir/templates"
次にテンプレートファイルをコピペします。
本家サイトにてテンプレートが公開されていますのでこちらから必要なテンプレートだけコピーして貼り付けていきます。
今回のケースだとlibraries/jvm-retrofit2/infrastructure/ApiClient.mustache
です。
注意事項として、ファイルだけではなくディレクトリ構造もコピーする必要があります。今回の場合、templates/libraries/jvm-retrofit2/infrastructure/ApiClient.kt.mustache
にコードを格納する感じです。
あとはこのコードを書き換えてやれば完成です。58行目に該当コードがあるので書き換えます。
+ import retrofit2.converter.kotlinx.serialization.asConverterFactory
- import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
これでタスクを実行すると書き換わっているはずです。
Discussion