🐱 うさねこ教室 Java・OpenAPI・OpenTelemetry の教室

Spring Boot で実装する

🐱 この章の目次

演習プロジェクトの構成

Part 1 で学んだ Spring Boot を使い、前章の注文 API を実装します。 Spring Boot は HTTP サーバー、JSON 変換、依存性注入、外部設定を一つのアプリケーションとして構成します。

最初に Spring Initializr から JDK 21、Gradle Kotlin DSL、Spring Web を選んでプロジェクトを生成します。 コマンドで取得する場合は次のとおりです。

curl -fLG https://start.spring.io/starter.zip \
  --data-urlencode type=gradle-project-kotlin \
  --data-urlencode language=java \
  --data-urlencode bootVersion=4.1.0 \
  --data-urlencode javaVersion=21 \
  --data-urlencode groupId=com.example \
  --data-urlencode artifactId=orders \
  --data-urlencode name=orders \
  --data-urlencode baseDir=orders \
  --data-urlencode dependencies=web \
  -o orders.zip
unzip orders.zip
cd orders

生成された gradlewgradlew.batgradle/wrapper/ はプロジェクトと一緒にバージョン管理します。

build.gradle.kts には Spring MVC と springdoc-openapi を追加します。

plugins {
    java
    id("org.springframework.boot") version "4.1.0"
    id("io.spring.dependency-management") version "1.1.7"
}

group = "com.example"
version = "1.0.0"

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-webmvc")
    implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:3.1.0")
    testImplementation("org.springframework.boot:spring-boot-starter-webmvc-test")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

tasks.test {
    useJUnitPlatform()
}

Spring Boot プラグインが依存バージョンを管理するため、Spring Framework や Jackson のバージョンを個別に並べません。 springdoc-openapi は別プロジェクトなので、互換するバージョンを明示します。

アプリケーションの起点

OrderApplication.java を作ります。

package com.example.orders;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

@SpringBootApplication は、構成クラス、コンポーネント探索、自動構成の起点です。 JVM や Java 言語の機能ではなく、Spring Boot が解釈するアノテーションです。

REST エンドポイント

レスポンスの型を Order.java に置きます。

package com.example.orders;

public record Order(String orderId, String status) {}

注文を探す処理は OrderService.java に置きます。 この段階では、動作確認用の一件だけを返します。

package com.example.orders;

import java.util.Optional;
import org.springframework.stereotype.Service;

@Service
public class OrderService {
    public Optional<Order> find(String orderId) {
        if (!orderId.equals("abc-123")) {
            return Optional.empty();
        }
        return Optional.of(new Order(orderId, "shipped"));
    }
}

OrderController.java に、OpenAPI 契約と同じ GET のパス、パラメータ、ステータスを実装します。

package com.example.orders;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/orders")
public class OrderController {
    private final OrderService orderService;

    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }

    @GetMapping("/{orderId}")
    public ResponseEntity<Order> getOrder(
            @PathVariable String orderId) {
        return orderService.find(orderId)
                .map(ResponseEntity::ok)
                .orElseGet(() -> ResponseEntity.notFound().build());
    }
}

@RestController は戻り値を HTTP レスポンスへ変換し、@GetMapping は HTTP メソッドとパスを対応づけます。 Java の record はレスポンスのフィールドを型として明示し、Jackson が JSON へ変換します。

起動して契約を確認する

./gradlew bootRun
curl http://localhost:8080/orders/abc-123

http://localhost:8080/swagger-ui.html で Swagger UI、http://localhost:8080/v3/api-docs で実装から生成された OpenAPI 文書を確認できます。 手書きの openapi.yaml と実装由来の文書を比較すると、構造上の差異を確認できます。 この章では GET と 404 を実装し、次章で POST、201、400 を実装して契約へ追いつきます。

FastAPI との対応

FastAPI では関数と型ヒントからルートやスキーマを組み立てます。 Spring Boot ではコントローラー、Bean Validation、DI コンテナ、自動構成を組み合わせます。 この教室では後者を主演習にし、Part 4 で同じ JVM プロセスへ OpenTelemetry Java Agent を取り付けます。

参照