こんにちは、エキサイト株式会社の平石です。
今回は、OpenAPI Generatorを利用してJavaのAPIクライアントを自動生成する方法をご紹介します。
はじめに
アプリケーションを開発していると、自社(自身)で開発したAPIを利用することがあります。
例えば、自社で利用している複数のサービスに共通のAPIがあり、実際のサービスや機能を実装するための処理でそのAPIを呼び出す場合が考えられます。
このような時、「HTTPクライアントを用意」、「エンドポイントと必要なパラメータを確認」、「パラメータ名を間違えないようにセット」などの面倒なことをAPIを呼び出す度に行わなければなりません。
また、前述のような共通のAPIを呼び出す場合には、同じような処理が複数のサービスや機能のソースコードに出現してしまいます。
そのため、APIクライアントのコードを自動生成できると開発の効率が良くなることが期待できます。
OpenAPI Generatorとは
OpenAPIはAPIの仕様を記述するためのフォーマットのようなものです。
これに従って「必要なパラメータ」や「レスポンスの形式」「認証の方法」のようなAPIに関する情報を、YAMLやJSON形式で記述することでドキュメントを作成することができます。
OpenAPI Generatorは、OpenAPIの仕様に則って作成されたドキュメントから、APIクライアントコードやAPIを実装するための雛形となるコードを自動生成してくれます。
様々な言語に対応していますが、今回はJavaのAPIクライアントを自動生成していきます。
OpenAPIの仕様に則って作成されたドキュメントから自動生成するため、呼び出し先のAPIはどの言語で記述されていても問題ありません。
準備
環境
今回は以下のような環境を利用します。
使用するAPIドキュメント
今回は以下のようなYAML形式で記述されたAPIドキュメントからAPIクライアントを生成します。
openapi: 3.0.1 info: title: OpenAPI definition version: v0 servers: - url: http://localhost:8190 description: Generated server url paths: /user: get: tags: - user summary: ユーザー取得 operationId: getUser parameters: - name: userId in: query description: ユーザーID required: true schema: type: string description: ユーザーID example: 11111111 example: 11111111 responses: "200": description: 正常に処理が終了した場合 content: application/json: schema: $ref: '#/components/schemas/UserResponseDto' components: schemas: UserResponseDto: title: ユーザーのレスポンス required: - email - userId - userName type: object properties: userId: title: ユーザーID type: string example: "11111111" userName: title: ユーザー名 type: string example: 白金 高輪 email: title: メールアドレス type: string example: takanawa.shirokane@example.com
http://localhost:8190/userに対してuserIdというクエリパラメータを指定すると、userId、userName、emailの3つを含むレスポンスが返ってくることを表しています。
このようなファイルを自力で記述するのは大変ですが、既に実装したAPIから自動生成することもできます。
JavaのSpring Bootでの方法については、以下の記事の「OpenAPI仕様のドキュメントの自動生成」の部分を参考にしてください。
このファイルにtest-api-docs.yamlという名前をつけて、プロジェクトルート内のspecsディレクトリに置いておきます。
依存関係の追加と設定を行う
自動生成を行う方法はいくつかありますが、今回はGradleのプラグインを利用します。
build.gradleは以下の通りです。
buildscript {
repositories {
mavenCentral()
}
dependencies {
// OpenAPI Generatorのプラグイン
classpath "org.openapitools:openapi-generator-gradle-plugin:7.2.0"
}
}
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.1'
id 'io.spring.dependency-management' version '1.1.4'
}
apply plugin: 'org.openapi.generator'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '21'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
基本的には、OpenAPI Generatorのプラグインを入れているだけです。
ここに、生成の際の設定を追加することができます。
build.gradleに以下のブロックを追加してください。
openApiGenerate {
generatorName.set("java")
inputSpec.set("$rootDir/specs/test-api-docs.yaml")
outputDir.set("$projectDir/clientgen")
apiPackage.set("com.example.clientgen.api")
invokerPackage.set("com.example.clientgen.invoker")
modelPackage.set("com.example.clientgen.model")
configOptions.set([
groupId: "com.example",
artifactVersion: "0.0.1-SNAPSHOT",
])
}
それぞれの設定項目を解説していきます。
generatorNameはGeneratorのリストにある、Generator名のどれかを設定します。
今回は、JavaのAPIクライアントを生成したいので、javaを設定しています。
inputSpecとoutputDirはそれぞれ生成に利用するOpenAPIのフォーマットに沿ったファイルのパスと、生成するコードの出力ディレクトリを指定します。
apiPackage, invokerPackage, modelPackageには生成するコードを出力する具体的なパッケージを設定します。
これらはOpenAPI GeneratorのGradleプラグインの設定項目であり、その他の設定項目はOpenAPI GeneratorのGradleプラグインの公式ドキュメントにあります。
反対にconfigOptionsでは、OpenAPI GeneratorでJavaクライアントを生成する際の共通の設定を行なえます。
groupIdとartifactVersionは、生成されるbuild.gradleやpom.xmlファイル内に記述されるgroupIdとversionに対応しています。
他にも様々な設定項目が用意されていますので、詳細は公式ドキュメントをご確認ください。
実際に生成してみる
ここまで記述できたら、Gradleプロジェクトのビルドを行います。
./gradlew build
ビルドが完了すると、OpenAPI GeneratorのGradleプラグインにより、openApiGenerateというタスクが実行可能になっています。
これを実行すると、outputDirに設定したディレクトリ(ここではclientgen)に自動生成ファイルが生成されます(ディレクトリが存在しない場合は作成される)。
./gradlew openApiGenerate

clientgenディレクトリには、主に自動生成されたクライアント自体の依存関係が記述されたbuild.gradleやpom.xmlと、実際のコードが含まれるsrcディレクトリがあります。
srcディレクトリ内を辿ると、api, invoker, modelの3つがあり、それぞれ以下のようなコードが存在しています。
api:test-api-docs.yamlから生成されたAPIinvoker: HTTPクライアントや例外クラス、認証まわりなどの実際にAPIを呼び出すために必要なコードmodel: APIのリクエストやレスポンスのためのモデル
なお、生成されるJavaコードやその依存するライブラリ等は、最新版よりやや古いものもあるため注意が必要です。
実際に使ってみる
生成したクライアントを最も手軽に利用する方法は、README.mdにあるようにMavenのローカルリポジトリにインストールする方法でしょう。
ローカルリポジトリはMaven Centralのローカル版のようなものであり、デフォルトでは$HOME/.m2/repositoryにあります。
Mavenをインストールする必要があるので、まだインストールされていない方はこちらからインストールしてください。
outputDirに設定したディレクトリに移動し、以下のコマンドを実行してMavenのローカルリポジトリに生成したAPIクライアントをローカルリポジトリにインストールします。
mvn clean install
build.gradleに以下を追記します。
〜〜 略 〜〜
repositories {
mavenCentral()
// ローカルリポジトリの設定
mavenLocal()
}
〜〜 略 〜〜
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// 依存関係を追加
implementation "example.com:openapi-java-client:0.0.1-SNAPSHOT"
}
〜〜 略 〜〜
プロジェクトを再ビルドし、以下のようなコントローラーを作成します。
import com.example.clientgen.api.UserApi; import com.example.clientgen.invoker.ApiException; import com.example.clientgen.model.UserResponseDto; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class DemoController { @GetMapping("user") public String getUser() { try { final UserResponseDto response = new UserApi().getUser("11111111"); return String.format("Name: %s, Email: %s", response.getUserName(), response.getEmail()); } catch (ApiException e) { throw new RuntimeException(e); } } }
SpringApplicationを起動し、/userにアクセスすることで、内部でAPIクライアントがtest-api-docs.yamlで記述したAPIを呼んでくれます。
結果は、例えば以下のようになるでしょう。

終わりに
OpenAPI Generatorを利用することで、API呼び出しコードを自動で生成してくれます。
Java以外の言語でも生成できるので、ぜひ活用してみてください。
別のブログで、自動生成されたものを実際に活用する方法を執筆する予定です。
では、また次回。