KotlinとSpring BootでのOpenAPIを使用できるようにする(環境構築)

Docker

はじめに

OpenAPIを使用してKotlinとSpring Bootでコードを自動生成し、開発の効率化を図る方法を紹介します。これにより、手動でのコード記述の手間を減らし、一貫性のある高品質なコードを効率的に生成することができます。

準備

DockerとVSCodeを使って開発環境を構築したいと思います。

- Dockerのインストール方法
Dockerのインストール方法について、下記のリンクを確認してください

Windows 11でWSL2をインストールする方法
はじめに 今回は、Windows 11でLinuxの環境を手軽に使える「WSL2 (Windows Subsystem for Linux 2)」のインストール方法についてご紹介します。 以下の公式サイトもご確認ください。 前提条件 Win...
WSL2のUbuntuにDockerをインストールする方法
はじめに 前回、WSL2のインストール方法についての記事を作成しました。今回は、WSL2上にインストールしたLinuxディストリビューションの1つであるUbuntuにDockerをインストールする方法について解説します。 以下の公式サイトも...
  • VSCodeのインストール方法について、下記のリンクを確認してください
Visual Studio Code のインストール方法(Windows版) - Qiita
初めにWindows版のVisual Studio Code のインストール方法についてまとめます。手順1:インストーラのダウンロード以下のサイトからインストーラをダウンロードします。htt…
  • 拡張機能をインストール
    以下の手順でRemote Development拡張機能をインストールしてください。
  1. VSCodeでCTRL + SHIFT + Xを押して拡張機能パネルを開きます。
  2. 検索バーに以下を入力して検索します。
    ms-vscode-remote.vscode-remote-extensionpack
  3. 表示された拡張機能をインストールします。
    file
  • ディレクトリの作成
    以下のようなディレクトリ構成を想定します。なお、Gitの設定が不要な場合は省略しても構いません。
.
├── .devcontainer
│   ├── Dockerfile
│   ├── devcontainer.json
│   └── git
│       ├── .gitconfig
│       ├── .gitignore
│       └── .ssh
│           └── id_rsa.pub
├── .vscode
│   ├── settings.json
│   └── tasks.json
└── {任意のプロジェクトディレクトリ}
  • Dockerfileを作成
    以下の内容でDockerfileを作成します。
# ベースイメージ:Ubuntu 24:04
FROM ubuntu:24.04

# パッケージのインストール時に対話的なプロンプトが表示されないように設定する
ENV DEBIAN_FRONTEND=noninteractive

# 必要なパッケージのインストール
RUN set -eux && \ 
    apt-get update && \
    apt-get install -y \
    # bashコマンド補完
    bash-completion \
    # treeコマンド
    tree \
    # 基本的な開発ツール
    build-essential \  
    # URLからデータを転送するためのツール
    curl \
    # バージョン管理システム
    git \
    # テキストエディタ  
    vim \
    # 圧縮ツール
    zip \  
    # 解凍ツール
    unzip \
    # 圧縮アーカイブツール
    tar \  
    # ファイル間の差分を表示するためのツール
    diffutils \
    # ファイルやディレクトリを検索するためのツール
    findutils \
    # ファイルを圧縮・解凍するためのツール
    gzip \
    # コマンドラインで使用するGitリポジトリビューア
    tig \
    # コマンドの実行ファイルの場所を表示するためのツール
    which && \ 
    # APTキャッシュのクリーンアップ
    apt-get clean && \
    # APTリポジトリのメタデータを削除してディスクスペースを節約
    rm -rf /var/lib/apt/lists/*

# AdoptiumのGitプロジェクトのベースURL
ARG BASE_URL_JDK=https://github.com/adoptium
# JDK 17のバイナリがあるプロジェクト
ARG JDK_DOWNLOAD=temurin17-binaries/releases/download
# JDK 17のリリースバージョン
ARG JDK_RELEASE=jdk-17.0.11%2B9
# JDKのバージョン番号
ARG JDK_VERSION=17.0.11_9
# JDKのファイル名
ARG JDK_FILE_NAME=OpenJDK17U-jdk_x64_linux_hotspot_${JDK_VERSION}.tar.gz

# OpenJDKのダウンロードとインストール
RUN set -eux && \
    # OpenJDKを指定されたURLからダウンロードし、一時ディレクトリに保存
    curl -L -o /tmp/openjdk.tar.gz ${BASE_URL_JDK}/${JDK_DOWNLOAD}/${JDK_RELEASE}/${JDK_FILE_NAME} && \
    # インストール先のディレクトリを作成
    mkdir -p /usr/lib/jvm/java-17-openjdk-amd64 && \
    # ダウンロードしたtar.gzファイルを解凍し、指定ディレクトリに展開
    tar -xzf /tmp/openjdk.tar.gz -C /usr/lib/jvm/java-17-openjdk-amd64 --strip-components 1 && \
    # 解凍後、一時ファイルを削除
    rm /tmp/openjdk.tar.gz

# 環境変数の設定
ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
ENV PATH="${JAVA_HOME}/bin:${PATH}"

# Kotlinコンパイラのダウンロードとインストール
ARG BASE_URL_KOTLIN=https://github.com/JetBrains/kotlin/releases/download/
# Kotlinコンパイラのバージョン
ARG KOTLIN_VERSION=2.0.0
# Kotlinコンパイラのファイル名
ARG KOTLIN_FILE_NAME=kotlin-compiler-${KOTLIN_VERSION}.zip

# Kotlinのダウンロード
RUN set -eux && \
    # Kotlinコンパイラを指定されたURLからダウンロードし、一時ディレクトリに保存
    curl -L -o /tmp/kotlin-compiler.zip ${BASE_URL_KOTLIN}/v${KOTLIN_VERSION}/kotlin-compiler-${KOTLIN_VERSION}.zip && \
    # ダウンロードしたZIPファイルを解凍し、指定ディレクトリに展開
    unzip /tmp/kotlin-compiler.zip -d /opt/kotlin && \
    # 解凍後、一時ファイルを削除
    rm /tmp/kotlin-compiler.zip

# 環境変数の設定
ENV KOTLIN_HOME=/opt/kotlin/kotlin-compiler-${KOTLIN_VERSION}
ENV PATH="${KOTLIN_HOME}/bin:${PATH}"

# Gradleのダウンロード
ARG GRADLE_VERSION=8.8
ARG BASE_URL_GRADLE=https://services.gradle.org/distributions
ARG GRADLE_FILE_NAME=gradle-${GRADLE_VERSION}-bin.zip

RUN set -eux && \
    # Gradleを指定されたURLからダウンロードし、一時ディレクトリに保存
    curl -L -o /tmp/gradle.zip ${BASE_URL_GRADLE}/gradle-${GRADLE_VERSION}-bin.zip && \
    # ダウンロードしたZIPファイルを解凍し、指定ディレクトリに展開
    unzip /tmp/gradle.zip -d /opt/gradle && \
    # 解凍後、一時ファイルを削除
    rm /tmp/gradle.zip

# 環境変数の設定
ENV GRADLE_HOME=/opt/gradle/gradle-${GRADLE_VERSION}
ENV PATH="${GRADLE_HOME}/bin:${PATH}"

WORKDIR /workspace

ENV LANG=C.UTF-8

ENV DEVCONTAINER=true
  • devcontainer.jsonを作成
    以下の内容でdevcontainer.jsonを作成します。なお、Gitの設定が不要な場合は削除してください。
{
    "name": "kotlin",
    "build": {
        "dockerfile": "Dockerfile"
    },
    "customizations": {
        "vscode": {
            "extensions": [
                "vscjava.vscode-java-pack",
                "vmware.vscode-boot-dev-pack",
                "fwcd.kotlin",
                "mathiasfrohlich.Kotlin",
                "mhutchie.git-graph",
                "donjayamanne.githistory",
                "eamodio.gitlens"
            ],
            "settings": {
                "java.jdt.ls.java.home": "/usr/lib/jvm/java-17-openjdk-amd64",
                "kotlin.compiler.jvmTarget": "17"
            }
        }
    },
    "workspaceFolder": "/workspace",
    "mounts": [
        "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached",
        "source=${localWorkspaceFolder}/.devcontainer/git/.ssh,target=/root/.ssh,type=bind,consistency=cached",
        "source=${localWorkspaceFolder}/.devcontainer/git/.gitconfig,target=/root/.gitconfig,type=bind,consistency=cached"
    ],
    "postCreateCommand": "mkdir -p /root/.ssh"  // .sshディレクトリの作成を保証する
}
  • キャッシュなしリビルドでコンテナを起動
    開発コンテナ:キャッシュなしリビルドし、コンテナで再度開く
    file

エラーなくうまく起動できれば成功です。

  • Gradleで開発プロジェクトを作成
    以下のコマンドを実行して、Gradleプロジェクトを初期化します。

    gradle init

    次に表示される対話形式の質問に回答します:

1. Enter selection (default: Application) [1..4]
→ 1
2. Enter selection (default: Java) [1..6]
→ 2
3. Enter target Java version (min: 7, default: 21):
→ 17
4. Project name (default: {今いるディレクトリ}):
→ app
5. Enter selection (default: Single application project) [1..2]
→ 1
6. Enter selection (default: Kotlin) [1..2] 
→ 1
7. Enter selection (default: kotlin.test) [1..2] 
→ 2
8. Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] 
→ no
gradle init
Starting a Gradle Daemon, 1 incompatible and 1 stopped Daemons could not be reused, use --status for details

Select type of build to generate:
  1: Application
  2: Library
  3: Gradle plugin
  4: Basic (build structure only)
Enter selection (default: Application) [1..4] 1

Select implementation language:
  1: Java
  2: Kotlin
  3: Groovy
  4: Scala
  5: C++
  6: Swift
Enter selection (default: Java) [1..6] 2

Enter target Java version (min: 7, default: 21): 17

Project name (default: {今いるディレクトリ}): app

Select application structure:
  1: Single application project
  2: Application and library project
Enter selection (default: Single application project) [1..2] 1

Select build script DSL:
  1: Kotlin
  2: Groovy
Enter selection (default: Kotlin) [1..2] 1

Select test framework:
  1: kotlin.test
  2: JUnit Jupiter
Enter selection (default: kotlin.test) [1..2] 2

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] no

> Task :init
To learn more about Gradle by exploring our Samples at https://docs.gradle.org/8.8/samples/sample_building_kotlin_applications.html

BUILD SUCCESSFUL in 10m 22s
1 actionable task: 1 executed
  • build.gradle.ktsを修正
    build.gradle.ktsを以下のように書き換えてください。
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "3.3.0"
    id("io.spring.dependency-management") version "1.1.6"
    id( "org.openapi.generator") version "7.6.0"
    kotlin("jvm") version "2.0.0"
    kotlin("plugin.spring") version "2.0.0"
    application
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springdoc:springdoc-openapi-starter-webflux-ui:2.5.0")
    implementation("ch.qos.logback:logback-classic:1.5.6")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(17))
    }
}

application {
    mainClass.set("org.app.AppKt")
}

tasks.named<Test>("test") {
    useJUnitPlatform()
}

tasks.withType<KotlinCompile>().configureEach {
    compilerOptions {
        freeCompilerArgs.add("-Xjsr305=strict")
        jvmTarget.set(JvmTarget.JVM_17)
    }
}

tasks.withType<JavaCompile> {
    options.encoding = "UTF-8"
    options.release.set(17)
}

openApiGenerate {
    // 使用するジェネレーターを指定します。この場合、「kotlin-spring」を使用して、KotlinとSpringに適したコードを生成します。
    generatorName.set("kotlin-spring")

    // OpenAPI仕様ファイルのパスを指定します。$projectDirはプロジェクトのルートディレクトリを指し、openapi/XXX.yamlファイルを指定しています。
    inputSpec.set("$projectDir/openapi/openapi.yaml")

    // 生成されたコードの出力ディレクトリを指定します。$buildDirはビルドディレクトリを指し、generatedフォルダに出力されます。
    outputDir.set(layout.buildDirectory.dir("generated").map { it.asFile.path })

    // 生成されたAPIコードのパッケージ名を指定します。ここではcom.app.apiパッケージに生成されます。
    apiPackage.set("com.app.api")

    // 生成されたインボーカーコード(APIリクエストを行うコード)のパッケージ名を指定します。ここではcom.app.invokerパッケージに生成されます。
    invokerPackage.set("com.app.invoker")

    // 生成されたモデルクラスのパッケージ名を指定します。ここではcom.app.modelパッケージに生成されます。
    modelPackage.set("com.app.model")

    configOptions.putAll(
        mapOf(
            // 日付ライブラリに「java11」を使用するように設定しています。
            "dateLibrary" to "java11",
        )
    )

}
  • App.ktを修正
    App.ktを以下のように書き換えてください。
package org.example

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class App

fun main(args: Array<String>) {
    runApplication<App>(*args)
}
  • AppTestを修正
    AppTestを以下のように書き換えてください。
package org.example

import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest

@SpringBootTest
class AppTest {

    @Test
    fun contextLoads() {
        // テストが正しくロードされることを確認するためのテスト
    }
}
  • 動作確認
    Gradleのbuildコマンドが成功するかを確認します。以下のコマンドを実行してください。
./gradlew build

以下のように表示されれば成功です

./gradlew build

BUILD SUCCESSFUL in 2s
12 actionable tasks: 12 up-to-date

file

OpenAPIの動作確認

  • openapi.yamlを作成

$projectDir/openapi/openapi.yamlにファイルを作成し、以下の内容を記述します。なお、$projectDirはプロジェクトのルートディレクトリです。

openapi: 3.1.0
info:
  title: Sample API
  version: 1.0.0
paths:
  /hello:
    get:
      summary: Returns a greeting message
      responses:
        '200':
          description: A greeting message
components:
  schemas:
    Greeting:
      type: object
      properties:
        message:
          type: string
  • コードを自動生成する
    次に、以下のコマンドを実行してOpenAPIコードを自動生成します。
./gradlew openApiGenerate

以下のように表示されれば成功です

./gradlew openApiGenerate

> Task :app:openApiGenerate
Generation using 3.1.0 specs is in development and is not officially supported yet. If you would like to expedite development, please consider woking on the open issues in the 3.1.0 project: https://github.com/orgs/OpenAPITools/projects/4/views/1 and reach out to our team on Slack at https://join.slack.com/t/openapi-generator/shared_invite/zt-12jxxd7p2-XUeQM~4pzsU9x~eGLQqX2g
invokerPackage with kotlin-spring generator is ignored. Use packageName.
Generation using 3.1.0 specs is in development and is not officially supported yet. If you would like to expedite development, please consider woking on the open issues in the 3.1.0 project: https://github.com/orgs/OpenAPITools/projects/4/views/1 and reach out to our team on Slack at https://join.slack.com/t/openapi-generator/shared_invite/zt-12jxxd7p2-XUeQM~4pzsU9x~eGLQqX2g
################################################################################
# Thanks for using OpenAPI Generator.                                          #
# Please consider donation to help us maintain this project 🙏                 #
# https://opencollective.com/openapi_generator/donate                          #
################################################################################
Successfully generated code to /workspace/dto-customize/app/build/generated

BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

file

以下のようにファイルが自動生成されたらOpenApiの環境構築は完了です。
file

コメント

タイトルとURLをコピーしました