こんにちは、エキサイト株式会社の平石です。
今回は、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以外の言語でも生成できるので、ぜひ活用してみてください。
別のブログで、自動生成されたものを実際に活用する方法を執筆する予定です。
では、また次回。