今回は、Spring Bootで実装したREST APIのコードから、APIを叩くクライアントコードを自動生成する方法を書いていきたいと思います。
今回やりたいこと
- すでに実装してあるREST APIのコードを基に、mavenのビルドライフサイクルの中でクライアントコードを自動生成したい
- Swagger Specificationではなく、OpenAPI Specification(V3)に対応したSpecファイルからコードを自動生成したい
環境
やることの流れ
REST APIを実装する
今回は、あらかじめ実装しておいたサンプルコードを使います。
@RestController @RequiredArgsConstructor public class SampleHelloController { private final SampleHelloService sampleHelloService; @GetMapping public String hello() { return sampleHelloService.hello(); } }
@Service public class SampleHelloService { public String hello() { return "hello"; } }
自動生成に必要なライブラリ/プラグインをpom.xmlに追加する
springdoc/springdoc-openapi-webmvc-core
SpringのアノテーションやJSR-303のアノテーションなどを解析してドキュメントを自動生成してくれるライブラリです。 今回はspringdoc-openapi-webmvc-coreを使っていますが、SwaggerUIを使いたい場合やSpring Webfluxを使っているアプリケーションで使いたい場合など用途ごとにライブラリが用意されています。 https://github.com/springdoc/springdoc-openapi
<dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-webmvc-core</artifactId> <version>1.4.3</version> </dependency>
springdoc/springdoc-openapi-maven-plugin
ビルド時にアプリケーションのコードから、OpenAPIのspecファイルを自動生成するMavenプラグインです。
springdoc/springdoc-openapi-webmvc-core
だけだと、アプリケーション起動時にspecファイルを内部生成してエンドポイントとしてSpecファイルを公開するだけなので、このライブラリを使ってビルド時にspecファイルをローカルに生成させます。
デフォルトではjson形式でSpecファイルを生成するので、pluginのconfigurationでyaml形式で生成する設定を追加しています。
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <id>pre-integration-test</id> <goals> <goal>start</goal> </goals> </execution> <execution> <id>post-integration-test</id> <goals> <goal>stop</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-maven-plugin</artifactId> <version>1.0</version> <executions> <execution> <id>integration-test</id> <goals> <goal>generate</goal> </goals> </execution> </executions> <configuration> <apiDocsUrl>http://localhost:8080/v3/api-docs.yaml</apiDocsUrl> <outputFileName>openapi.yaml</outputFileName> </configuration> </plugin>
OpenAPITools/openapi-generator-maven-plugin
ビルド時にspecファイルから、クライアントコードを自動生成するMavenプラグインです。
上であげた2つのライブラリ/プラグインを入れることでビルド時にローカルにSpecファイルを生成することができたので、そのSpecファイルを使ってクライアントコードを自動生成します。
<plugin> <groupId>org.openapitools</groupId> <artifactId>openapi-generator-maven-plugin</artifactId> <version>4.3.1</version> <executions> <execution> <phase>post-integration-test</phase> <goals> <goal>generate</goal> </goals> <configuration> <inputSpec> ${project.basedir}/target/openapi.yaml </inputSpec> <output> ${project.basedir}/generated/api-client/${openapi.generator.maven.plugin.generatorName} </output> <apiPackage>com.daisuzz.sampleapiclient.api</apiPackage> <modelPackage>com.daisuzz.sampleapiclient.model</modelPackage> <packageName>com.daisuzz.sampleapiclient</packageName> <groupId>com.daisuzz</groupId> <artifactId>sample-api-client</artifactId> <artifactVersion>0.0.1-SNAPSHOT</artifactVersion> </configuration> </execution> </executions> </plugin>
pluginのconfigurationでは、自動生成する言語を指定できたり、自動生成したクライアントコードの出力先やpackage nameやgroupId, artifactId, versionなどの指定ができます。
openapi.generator.maven.plugin.generatorName
プロパティもpluginのconfigurationとして指定できるのですが、生成するクライアントコードのプログラミング言語をコマンド実行時に動的に変更したかったため、あえてシステムプロパティで受け取るようにしました。
pom.xmlに静的に記述したければ、以下のようにopenapi-generator-maven-pluginのconfigurationで指定すればOKです。
... <generatorName>java</generatorName> <output> ${project.basedir}/generated/api-client/java </output> ...
mvnコマンドでクライアントコードを自動生成する
mvnコマンドでpost-integration-test
を実行します。
mvn clean verify -Dopenapi.generator.maven.plugin.generatorName=java
フェーズの実行が成功すると、指定したディレクトリ配下にコードが自動生成されています。 ↓の例では、JavaとKotlinでそれぞれクライアントコードを生成してみました。