【備忘録】Kotlin + SpringBoot + GradleのプロジェクトにOpenAPIを導入する

備忘録として書きます。

## 環境

- OS: Windows11
- kotlin: 1.8
- SpringBoot: 3.1.2
- OpenAPI Generator: 6.6.0


## 導入手順

SpringBootのプロジェクトは作成済みであるものとします。
また、各手順の後はビルドして問題ないことを確認します。

### 1. build.gradle.ktsにopenapi-generatorを追加する

```build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "3.1.2"
    id("io.spring.dependency-management") version "1.1.2"
    id("org.graalvm.buildtools.native") version "0.9.23"
    // OpenAPI Generatorを追加する
    id("org.openapi.generator") version  "6.6.0"
    kotlin("jvm") version "1.8.22"
    kotlin("plugin.spring") version "1.8.22"
}
```

### 2. openApiGenerateタスクを定義する

build.gradle.ktsに以下のタスクを定義します。

```gradle:build.gradle.kts
openApiGenerate {

    // モデルがkotlinクラスとして生成されるようにする
    generatorName.set("kotlin-spring")
    // yamlファイルの場所を指定する
    inputSpec.set("$projectDir/src/docs/api/openapi.yaml")
    // 生成ファイルの出力先を指定する
    outputDir.set("$projectDir/src/main/kotlin/com/example/demo/presentation/model")

}
```
### 3. yamlファイルでAPIの仕様を定義する。

CSVファイルを返すAPIを定義したいので、以下のように記述します。

```yaml
openapi: 3.0.3
info:
  title: Customer Export API
  version: 1.0.0
paths:
  /api/customers/export:
    post:
      summary: Export customers based on given IDs
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomerExportRequestModel'
      responses:
        '200':
          description: Successful operation
          headers:
            Content-Type:
              $ref: '#/components/headers/ContentTypeHeader'
            Content-Disposition:
              $ref: '#/components/headers/ContentDispositionHeader'
          content:
            text/csv:
              schema:
                $ref: '#/components/schemas/CustomerExportResponseModel'
        '400':
          description: Bad request
        '500':
          description: Internal server error
components:
  schemas:
    CustomerExportRequestModel:
      type: object
      properties:
        ids:
          type: array
          items:
            type: string
          description: An array of customer IDs to be exported.
    CustomerExportResponseModel:
      type: string
      description: CSV file containing the exported customer data.
      example: |
        id,name,age
        1,Bob,30
        2,Alice,19
  headers:
    ContentTypeHeader:
      schema:
        type: string
        default: text/csv
        description: Content type of the returned file.
    ContentDispositionHeader:
      schema:
        type: string
        default: attachment
        description: How the content should be treated by the browser.
```

### 4. ビルドする

プロジェクトルートディレクトリで以下のコマンドを実行します。

```bash
$  ./gradlew openApiGenerate
```

``` BUILD SUCCESSFUL ``` とターミナルに表示されれば成功です。

Modelクラスが生成されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598747/bb75c27d-b5bf-1cb5-a329-52e8a3fcdcba.png)




ただ、不要なファイルが生成されていたりパッケージ階層が必要以上に深くなってしまっています。
この点は今後修正していきたいと思います。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598747/7a2706a0-d529-5388-435b-560c633ef080.png)


## 参考資料

- [OpenAPI Generator](https://openapi-generator.tech/)
- [OpenAPITools / openapi-generator](https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-gradle-plugin)