query bookDetails {
bookById(id: "book-1") {
id
name
pageCount
author {
firstName
lastName
}
}
}
GraphQL サービスの構築
Spring for GraphQL は、GraphQL Java (英語) 上に構築された Spring アプリケーションのサポートを提供します。
このガイドでは、Spring for GraphQL を使用して Java で GraphQL サービスを作成するプロセスについて説明します。
構築するもの
http://localhost:8080/graphql
で GraphQL リクエストを受け入れるサービスを構築します。
必要なもの
約 15 分
Eclipse STS や IntelliJ IDEA のような任意の IDE または VSCode のようなテキストエディター
Java 17 以降
コードを直接 IDE にインポートすることもできます。
本ガイドの完成までの流れ
ほとんどの Spring 入門ガイドと同様に、最初から始めて各ステップを完了するか、すでに慣れている場合は基本的なセットアップステップをバイパスできます。いずれにしても、最終的に動作するコードになります。
最初から始めるには、Spring Initializr から開始に進みます。
基本をスキップするには、次の手順を実行します。
このガイドを Eclipse で「Spring 入門コンテンツのインポート」するか、ソースリポジトリをダウンロードして解凍、または、Git (英語) を使用してクローンを作成します。
git clone https://github.com/spring-guides/gs-graphql-server.git
gs-graphql-server/initial
に cdGraphQL のごく簡単な導入にジャンプしてください。
完了したときは、gs-graphql-server/complete
のコードに対して結果を確認できます。
Spring Initializr から開始
必要に応じて、この事前入力済みの Spring Initializr リンクを使用して正しい設定を読み込むことができます。それ以外の場合は、Initializr を手動で設定してください。
プロジェクトを手動で初期化するには:
IDE のメニューまたはブラウザーから Spring Initializr を開きます。アプリケーションに必要なすべての依存関係を取り込み、ほとんどのセットアップを行います。
Gradle または Maven のいずれかと、使用する言語を選択します。このガイドは、Java を選択したことを前提としています。
依存関係をクリックし、Spring for GraphQL と Spring Web を選択します。
生成をクリックします。
結果の ZIP ファイルをダウンロードします。これは、選択した内容で構成された GraphQL アプリケーションのアーカイブです。
Eclipse や IntelliJ のような IDE は新規プロジェクト作成ウィザードから Spring Initializr の機能が使用できるため、手動での ZIP ファイルのダウンロードやインポートは不要です。 |
GitHub (英語) からプロジェクトをフォークして、IDE または他のエディターで開くこともできます。 |
GraphQL のごく簡単な導入
GraphQL は、サーバーからデータを取得するためのクエリ言語です。これは、REST、SOAP、gRPC に代わるものです。このチュートリアルでは、オンラインストアバックエンドから特定の書籍の詳細を照会します。
これは、書籍の詳細を取得するために GraphQL サーバーに送信できるリクエストの例です。
この GraphQL リクエストは次のように述べています。
ID "book-1" の本のクエリを実行する
本の場合は、ID、名前、pageCount、作成者を返します
作成者の場合は firstName と lastName を返す
レスポンスは JSON です。例:
{
"bookById": {
"id":"book-1",
"name":"Effective Java",
"pageCount":416,
"author": {
"firstName":"Joshua",
"lastName":"Bloch"
}
}
}
GraphQL の重要な機能は、スキーマ言語を定義し、静的に型付けされることです。サーバーは、リクエストが照会できるオブジェクトの型と、それらのオブジェクトに含まれるフィールドを正確に認識しています。さらに、クライアントはサーバーをイントロスペクトして、スキーマの詳細をリクエストできます。
このチュートリアルのスキーマという用語は、「GraphQL スキーマ」を指し、「JSON スキーマ」や「データベーススキーマ」などの他のスキーマとは関係ありません。 |
上記のクエリのスキーマは次のとおりです。
type Query {
bookById(id: ID): Book
}
type Book {
id: ID
name: String
pageCount: Int
author: Author
}
type Author {
id: ID
firstName: String
lastName: String
}
このチュートリアルでは、Java でこのスキーマを使用して GraphQL サーバーを実装する方法に焦点を当てます。
GraphQL で可能なことの表面をなぞったにすぎません。詳細については、GraphQL の公式ページ (英語) を参照してください。
サンプル API: 書籍の詳細を取得する
Spring for GraphQL を使用してサーバーを作成する主な手順は次のとおりです。
GraphQL スキーマを定義する
クエリの実際のデータを取得するロジックを実装する
サンプルアプリは、特定の本の詳細を取得するための単純な API です。包括的な API を意図したものではありません。
スキーマ
前に準備した Spring for GraphQL アプリケーションで、次の内容を含む新しいファイル schema.graphqls
を src/main/resources/graphql
フォルダーに追加します。
type Query {
bookById(id: ID): Book
}
type Book {
id: ID
name: String
pageCount: Int
author: Author
}
type Author {
id: ID
firstName: String
lastName: String
}
すべての GraphQL スキーマにはトップレベルの Query
型があり、そのフィールドはアプリケーションによって公開されるクエリ操作です。ここで、スキーマは、特定の本の詳細を返す bookById
と呼ばれる 1 つのクエリを定義します。
また、フィールド id
、name
、pageCount
、author
を持つ型 Book
と、フィールド firstName
および lastName
を持つ型 Author
も定義します。
上記でスキーマを記述するために使用されたドメイン固有言語は、スキーマ定義言語または SDL と呼ばれます。詳細については、GraphQL ドキュメント (英語) を参照してください。 |
データのソース
GraphQL の主な強みは、どこからでもデータを取得できることです。データは、データベース、外部サービス、静的なメモリ内リストから取得できます。
チュートリアルを簡素化するために、本と作成者のデータは、それぞれのクラス内の静的リストから取得されます。
Book および Author データソースを作成する
メインアプリケーションパッケージの GraphQlServerApplication
のすぐ隣に Book
および Author
クラスを作成しましょう。以下をコンテンツとして使用します。
package com.example.graphqlserver;
import java.util.Arrays;
import java.util.List;
public record Book (String id, String name, int pageCount, String authorId) {
private static List<Book> books = Arrays.asList(
new Book("book-1", "Effective Java", 416, "author-1"),
new Book("book-2", "Hitchhiker's Guide to the Galaxy", 208, "author-2"),
new Book("book-3", "Down Under", 436, "author-3")
);
public static Book getById(String id) {
return books.stream()
.filter(book -> book.id().equals(id))
.findFirst()
.orElse(null);
}
}
package com.example.graphqlserver;
import java.util.Arrays;
import java.util.List;
public record Author (String id, String firstName, String lastName) {
private static List<Author> authors = Arrays.asList(
new Author("author-1", "Joshua", "Bloch"),
new Author("author-2", "Douglas", "Adams"),
new Author("author-3", "Bill", "Bryson")
);
public static Author getById(String id) {
return authors.stream()
.filter(author -> author.id().equals(id))
.findFirst()
.orElse(null);
}
}
データを取得するためのコードの追加
Spring for GraphQL は、アノテーションベースのプログラミングモデルを提供します。コントローラーのアノテーション付きメソッドを使用して、特定の GraphQL フィールドのデータをフェッチする方法を宣言できます。
Book
および Author
の横にある、メインアプリケーションパッケージの BookController.java
に以下を追加します。
package com.example.graphqlserver;
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.graphql.data.method.annotation.SchemaMapping;
import org.springframework.stereotype.Controller;
@Controller
public class BookController {
@QueryMapping
public Book bookById(@Argument String id) {
return Book.getById(id);
}
@SchemaMapping
public Author author(Book book) {
return Author.getById(book.authorId());
}
}
@QueryMapping
でアノテーションが付けられた bookById
という名前のメソッドを定義することにより、このコントローラーは Query 型で定義されているように Book
を取得する方法を宣言します。クエリフィールドはメソッド名から決定されますが、アノテーション自体で宣言することもできます。
Spring for GraphQL は、そのような各コントローラーメソッドを GraphQL Java graphql.schema.DataFetcher として登録する RuntimeWiring.Builder を使用します。DataFetcher は、クエリまたは任意のスキーマフィールドのデータをフェッチするロジックを提供します。GraphQL の Spring Boot スターターには、この登録を自動化する自動構成があります。 |
GraphQL Java エンジンでは、DataFetchingEnvironment
はフィールド固有の引数値のマップへのアクセスを提供します。@Argument
アノテーションを使用して、引数をターゲットオブジェクトにバインドし、コントローラーメソッドに挿入します。デフォルトでは、メソッドパラメーター名は引数の検索に使用されますが、アノテーション自体で指定することもできます。
この bookById
メソッドは、特定の Book
を取得する方法を定義しますが、関連する Author
の取得については考慮しません。リクエストが作成者情報をリクエストする場合、GraphQL Java はこのフィールドを取得する必要があります。
@SchemaMapping
アノテーションは、ハンドラーメソッドを GraphQL スキーマのフィールドにマップし、それがそのフィールドの DataFetcher
であることを宣言します。フィールド名はデフォルトでメソッド名になり、型名はデフォルトでメソッドに注入されたソース / 親オブジェクトの単純なクラス名になります。この例では、フィールドはデフォルトで author
に設定され、型はデフォルトで Book
に設定されています。
詳細については、Spring for GraphQL アノテーション付きコントローラー機能のドキュメントを参照してください。
必要なコードはこれだけです。
最初のクエリを実行してみましょう。
最初のクエリを実行する
GraphiQL プレイグラウンドを有効にする
GraphiQL は、クエリの作成と実行などに役立つビジュアルインターフェースです。この構成を application.properties
ファイルに追加して、GraphiQL を有効にします。
spring.graphql.graphiql.enabled=true
アプリケーションを起動する
Spring アプリケーションを開始します。http://localhost:8080/graphiql に移動します。
クエリを実行する
クエリを入力し、ウィンドウの上部にある再生ボタンをクリックします。
query bookDetails {
bookById(id: "book-1") {
id
name
pageCount
author {
id
firstName
lastName
}
}
}
このようなレスポンスが表示されるはずです。
おめでとうございます。GraphQL サービスを構築し、最初のクエリを実行しました。Spring for GraphQL の助けを借りて、わずか数行のコードでこれを実現できました。
テスト
Spring for GraphQL は、spring-graphql-test
アーティファクトで GraphQL テストのヘルパーを提供します。このアーティファクトは、Spring Initializr によって生成されたプロジェクトの一部としてすでに含まれています。
GraphQL サービスを徹底的にテストするには、さまざまな範囲のテストが必要です。このチュートリアルでは、単一のコントローラーに焦点を当てた @GraphQlTest
スライステストを作成します。完全なエンドツーエンドの統合テストと焦点を絞ったサーバー側のテストを支援する他のヘルパーがあります。詳細については、Spring Boot ドキュメントの Spring for GraphQL テストドキュメントおよび自動構成された Spring for GraphQL テストを参照してください。
数分前に GraphiQL プレイグラウンドでリクエストされたものと同じ bookDetails
クエリを検証するコントローラースライステストを作成してみましょう。
以下をテストファイル BookControllerTests.java
に追加します。このファイルを src/test/java/com/example/graphqlserver/
フォルダー内の場所に保存します。
package com.example.graphqlserver;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.graphql.GraphQlTest;
import org.springframework.graphql.test.tester.GraphQlTester;
@GraphQlTest(BookController.class)
public class BookControllerTests {
@Autowired
private GraphQlTester graphQlTester;
@Test
void shouldGetFirstBook() {
this.graphQlTester
.documentName("bookDetails")
.variable("id", "book-1")
.execute()
.path("bookById")
.matchesJson("""
{
"id": "book-1",
"name": "Effective Java",
"pageCount": 416,
"author": {
"firstName": "Joshua",
"lastName": "Bloch"
}
}
""");
}
}
このテストは、GraphiQL Playground で使用したものと同様の GraphQL クエリを参照しています。再利用できるように $id
でパラメーター化されています。src/test/resources/graphql-test
にある bookDetails.graphql
ファイルにこのクエリを追加します。
query bookDetails($id: ID) {
bookById(id: $id) {
id
name
pageCount
author {
id
firstName
lastName
}
}
}
テストを実行し、結果が GraphiQL Playground で手動でリクエストされた GraphQL クエリと同じであることを確認します。
@GraphQlTest
アノテーションは、1 つのコントローラーに焦点を当てたコントローラースライステストを作成する場合に役立ちます。@GraphQlTest
は、トランスポートやサーバーが関与することなく、Spring for GraphQL インフラストラクチャを自動構成します。自動構成により、定型コードをスキップすることでテストをより迅速に作成できます。これは焦点を絞ったスライステストであるため、@Controller
および RuntimeWiringConfigurer
を含む限られた数の Bean のみがスキャンされます。スキャンされた Bean のリストについては、ドキュメントを参照してください。
GraphQlTester
は、トランスポートに関係なく、GraphQL リクエストをテストするための共通のワークフローを宣言する契約です。私たちのテストでは、必要な変数を含む documentName
でドキュメントを提供し、次にリクエストを execute
で提供します。次に、JSON パスを含むレスポンスの一部を選択し、この場所の JSON が期待される結果と一致することをアサートします。
おめでとう! このチュートリアルでは、GraphQL サービスを構築し、最初のクエリを実行し、最初の GraphQL テストを作成しました。
参考文献
サンプルソースコード
このガイドは、GraphQL Java (英語) チームと共同で作成されました。Donna Zhou [GitHub] (英語) 、Brad Baker [GitHub] (英語) 、Andreas Marek [GitHub] (英語) に多大な感謝を! このチュートリアルのソースコードは GitHub (英語) にあります。
ドキュメント
Spring for GraphQL ドキュメントを参照してください。
GraphQL Java は、Spring for GraphQL を強化する GraphQL エンジンです。GraphQL Java ドキュメント (英語) を参照してください。
その他の Spring for GraphQL の例
1.0. ×ブランチ [GitHub] (英語) でより多くのサンプルを参照してください。これはまもなく別のリポジトリに移動 [GitHub] (英語) されます。
スタックオーバーフローに関する質問
spring-graphql でのスタックオーバーフロー (英語) タグに関する質問をすることができます。
新しいガイドを作成したり、既存のガイドに貢献したいですか? 投稿ガイドラインを参照してください [GitHub] (英語) 。
すべてのガイドは、コード用の ASLv2 ライセンス、およびドキュメント用の Attribution、NoDerivatives creative commons ライセンス (英語) でリリースされています。 |