daisuzz.log

【OpenAPI】Spring Bootで実装したREST APIのクライアントコードを自動生成する方法

今回は、Spring Bootで実装したREST APIのコードから、APIを叩くクライアントコードを自動生成する方法を書いていきたいと思います。

今回やりたいこと

  • すでに実装してあるREST APIのコードを基に、mavenのビルドライフサイクルの中でクライアントコードを自動生成したい
  • Swagger Specificationではなく、OpenAPI Specification(V3)に対応したSpecファイルからコードを自動生成したい

環境

やることの流れ

  • REST APIを実装する
  • 自動生成に必要なライブラリ/プラグインをpom.xmlに追加する
  • mvnコマンドでコードを自動生成する

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に追加する

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でそれぞれクライアントコードを生成してみました。