A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://zenn.dev/msksgm/articles/20221021-kotlin-spring-openapi-generator below:

Kotlin(Spring Boot)の API を OpenAPI Generator で自動生成

概要 !

2022 年 12 月 14 日現在、SpringBoot v3 がリリースされています。
しかし、OpenAPI Generator v6.2.0 では Kotlin-Spring に対して SpringBoot v3 は非対応です。
現在、PR が作成されています。v6.3.0 でマージが予定されているので、待ちましょう。
本記事は、OpenAPI Generator v6.2.0 と SpringBoot v2 における内容です。

本記事では OpenAPI Generator を用いて openapi.yaml から Kotlin(Spring Boot)のソースコードを自動生成する方法を紹介します。
以下の構成にしたがって進めていきます。

本記事で作成したサンプルコードは以下に載せています。

https://github.com/Msksgm/openapi-generator-sample

OpenAPI Generator について

OpenAPI Generator とは、OpenAPI Specification(以下、OpenAPI)をもとに、ソースコードを自動生成するツールです。
OpenAPI Generator を利用することで、スキーマ駆動開発を実現しやすくなります。

https://github.com/OpenAPITools/openapi-generator

OpenAPI ベースでソースコードを生成できるため、以下のメリットがあります。

OpenAPI と OpenAPI Generator についてほかにも特徴がありますが、以下の記事を参考にしたので、詳細なことは以下を参考にしてください。

https://qiita.com/amuyikam/items/e8a45daae59c68be0fc8

また、記事に引用されていた以下の資料は、OpenAPI Generator の Contributer の方が作成されたものです。
OpenAPI の歴史と OpenAPI Generator が制作された経緯を紹介しており、非常に興味深かったのでぜひ一読してください。

https://speakerdeck.com/akihito_nakano/gunmaweb34

Kotlin(Spring Boot)に導入

Kotlin に導入する際には、build.gradle.kts 記述が必要なため本項目で解説します。
Kotlin で導入すると、Controller に使用する interface と data class が生成されます。interface はエンドポイントのルーティング、メソッド、ステータスコードなどが定義されます。同様に、data class はリクエストとレスポンスの型が定義されています。

openapi.generator プラグインを導入するほかに、前提として以下のように設定します。

概要 内容 生成される interface のエンドポイントのまとめ方は、OpenAPI の tags 準拠 デフォルトだと API のパスをパースするため 生成されたソースコードは、Git で管理しない build/ 配下に生成して、builld.gradle.kts の設定で import できるようにする compile するたびにソースコードを自動生成する 意図しない変更があったときに、ビルドを停止するため !

Git で管理しない理由は自動生成したファイルを編集すると、次に自動生成したタイミングで簡単に上書きや、コンフリクトが発生するためです。
また、自由でに修正できる状態だと、ソースコードがスキーマファイルである OpenAPI から乖離します。結果、スキーマファーストな開発ができなくなってしまいます。

build.gradle.kts

具体的に build.gradle.kts に何を記述するのか解説します。
長くなったので、項目(plugins、dependencies、task、そのた)ごとに分割しました。

plugins

まず、OpenAPI Generator が提供している、openapi.generator を記述します。

build.gradle.kts


plugins {
	
	
	id("org.openapi.generator") version "6.2.0"
}

dependencies

生成したソースコード内で利用されているライブラリを記述します。
src/から参照したり、ビルド時にも参照するため、記述しないとビルドが落ちます。

build.gradle.kts

dependencies {
	
	
	compileOnly("io.swagger.core.v3:swagger-annotations:2.2.4")
	compileOnly("io.swagger.core.v3:swagger-models:2.2.4")
	compileOnly("jakarta.annotation:jakarta.annotation-api:2.1.1")

	
	implementation("org.springframework.boot:spring-boot-starter-validation")
}

task

./gradlew に task を追加します。
追加するタスクは以下の表の通りです。

タスク 内容 generateApiDoc openapi.yaml から API スキーマのドキュメントを生成する generateApiServer openapi.yaml からソースコードを生成する(tags 準拠で生成できるようにする)

また、task の追加設定で、コンパイル時にgenerateApiServerの実行するように設定します。
task<GenerateTask>("generateApiServer")に記述してある、apiPackage.setmodlePackage.setのパスは各自のパスを指定してください。main/kotlin からパスを指定します。

build.gradle.kts

import org.openapitools.generator.gradle.plugin.tasks.GenerateTask 




task<GenerateTask>("generateApiDoc") {
	generatorName.set("html2")
	inputSpec.set("$projectDir/openapi.yaml")
	outputDir.set("$buildDir/openapi/doc/")
}


task<GenerateTask>("generateApiServer") {
	generatorName.set("kotlin-spring")
	inputSpec.set("$projectDir/openapi.yaml")
	outputDir.set("$buildDir/openapi/server-code/") 
	apiPackage.set("com.example.yourapp.openapi.generated.controller") 
	modelPackage.set("com.example.yourapp.openapi.generated.model") 
	configOptions.set(
		mapOf(
			"interfaceOnly" to "true",
		)
	)
	
	additionalProperties.set(
		mapOf(
			"useTags" to "true"
		)
	)
}


tasks.compileKotlin {
	dependsOn("generateApiServer")
}

その他

build されたソースコードを import できるようにする設定も、build.gradle.kts に記述します。

build.gradle.kts


kotlin.sourceSets.main {
	kotlin.srcDir("$buildDir/openapi/server-code/src/main")
}

以上で導入完了です。

ソースコードの自動生成

導入したので、どのようにして自動生成するのか確認します。

!

自動生成する部分だけを手元で確認したい場合は、以下の手順で確認可能です。

OpenAPI の作成

ソースコードの生成もとになる、OpenAPI を作成します。本記事では v3.0.2 で作成しました。
メタ情報(openapi、info、servers)、エンドポイント(paths)、コンポーネント(components)から構成されます。
具体的な記述方法について触れませんので、公式ドキュメントを参照してください。

https://spec.openapis.org/oas/v3.0.2

本記事で作成した OpenAPI。

openapi.yaml








openapi: "3.0.2"









info:
  title: OpenAPI Generator Kotlin Sample
  description: OpenAPI Generator を用いた自動生成のサンプルコードです
  license:
    name: MIT License
    url: https://opensource.org/licenses/MIT
  version: "1.0"









servers:
  - url: /api









paths:

  
  
  
  
  
  
  
  /customers:

    
    
    
    get:

      
      
      
      
      
      
      
      
      tags:
        - Customer

      
      
      
      
      
      
      
      
      summary: カスタマーの一覧取得

      
      
      
      
      
      
      
      
      description: DB に登録されているカスタマーを全て取得する

      
      
      
      
      
      
      
      
      operationId: List

      
      
      
      
      
      
      
      
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MultipleCustomersResponse'









components:

  
  
  
  
  
  
  
  
  
  
  
  
  schemas:

    
    
    
    
    
    
    
    Customer:

      
      
      
      
      
      
      
      
      required:
        - first_name
        - last_name

      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      type: object

      properties:
        first_name:
          type: string
        last_name:
          type: string
    MultipleCustomersResponse:
      required:
        - customers
      type: object
      properties:
        customers:
          type: array
          items:
            $ref: '#/components/schemas/Customer'

コマンドの実行

以下のコマンド(または、intellij の gradle タブ->other->generateApiServer)でソースコードを自動生成できます。
生成されたソースコードは、build/openapi/server-code/src 配下に存在します。

./gradlew generateApiServer


生成されたソースコード

中身を確認すると、以下になっています。
OpenAPI がソースコードに反映されたことがわかりました。

CustomerApi.kt





@Validated
@RequestMapping("\${api.base-path:/api}")
interface CustomerApi {

    @Operation(
        summary = "カスタマーの一覧取得",
        operationId = "list",
        description = "DB に登録されているカスタマーを全て取得する",
        responses = [
            ApiResponse(responseCode = "200", description = "OK", content = [Content(schema = Schema(implementation = MultipleCustomersResponse::class))])
        ]
    )
    @RequestMapping(
            method = [RequestMethod.GET],
            value = ["/customers"],
            produces = ["application/json"]
    )
    fun list(): ResponseEntity<MultipleCustomersResponse> {
        return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)
    }
}

また、以下のコマンドによって、API ドキュメントの生成も可能です。

生成された API ドキュメント ./build/openapi/doc/index.html 。


生成された API ドキュメント

REST API の作成

生成した interface を実装することで、REST API を作成します。

interface の実装

生成した interface の実装方法は以下になります。
build.gradle.kts の設定によりbuild/配下のファイルを import 可能なことがわかります。
非常に簡潔な実装になり、開発者が実装する部分はほとんどないことがわかります。

CustomerController.kt

package com.example.openapigeneratorsample.controller

import com.example.realworldkotlinspringbootjdbc.openapi.generated.controller.CustomerApi 
import com.example.realworldkotlinspringbootjdbc.openapi.generated.model.Customer 
import com.example.realworldkotlinspringbootjdbc.openapi.generated.model.MultipleCustomersResponse 
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.RestController

@RestController
class CustomerController : CustomerApi {
    override fun list(): ResponseEntity<MultipleCustomersResponse> {
        
        
        return ResponseEntity(
            MultipleCustomersResponse(
                customers = listOf(Customer("Alice", "example01"), Customer("Bob", "example02")),
            ),
            HttpStatus.OK
        )
    }
}

動作確認

一応動作確認します。

以下のコマンドでレスポンスが戻ってくることが確認できたら完了です。

curl -X GET \
 -H "Accept: application/json" \
 "http://localhost:8080/api/customers"

まとめ

本記事では OpenAPI Generator を利用して、Kotlin(Spring Boot)で API のソースコードを自動生成する方法を紹介しました。
OpenAPI Generator によってスキーマ駆動開発による並行開発や開発者が注力する領域をドメインに限定できます。
さまざまな言語で利用できるため、新規開発で新しい言語を導入する敷居も下がるので、ぜひ利用してみてください。

参考

https://blog.onk.ninja/2017/09/21/schema_first_development

https://qiita.com/amuyikam/items/e8a45daae59c68be0fc8

https://speakerdeck.com/akihito_nakano/gunmaweb34

https://ackintosh.github.io/blog/2018/05/12/openapi-generator/


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4