Spring BootでGraphQLを実装する

## GraphQLとは
[RESTの課題とGraphQL](https://qiita.com/NagaokaKenichi/items/a4991eee26e2f988c6ec)を参照していただけたらと思います。

## 環境

* Windows10
* Java8
* Spring Boot 2.2.1.RELEASE
* Maven 3.2.5

## 依存ライブラリの追加

以下を追加します。

* GraphQL Java
* GraphQL Spring Boot Starter
* GraphQL Java Tools

```pom.xml
    <!-- https://mvnrepository.com/artifact/com.graphql-java/graphql-java -->
    <dependency>
      <groupId>com.graphql-java</groupId>
      <artifactId>graphql-java</artifactId>
      <version>11.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.graphql-java/graphql-spring-boot-starter -->
    <dependency>
      <groupId>com.graphql-java</groupId>
      <artifactId>graphql-spring-boot-starter</artifactId>
      <version>5.0.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.graphql-java/graphql-java-tools -->
    <dependency>
      <groupId>com.graphql-java</groupId>
      <artifactId>graphql-java-tools</artifactId>
      <version>5.2.4</version>
    </dependency>
```

※バージョンは2019年12月時点の最新を利用しています

## Schema（スキーマ）定義

スキーマや型については、[GraphQLのスキーマと型定義](https://qiita.com/NagaokaKenichi/items/d341dc092012e05d6606)を参照していただけたらと思います。

```schema.graphqls
type Book {
    id: ID
    name: String
    pageCount: Int
    author: Author
}

type Author {
    id: ID
    firstName: String
    lastName: String
}

type Query {
    bookById(id: ID): Book
}

```

## Typeクラスの作成

スキーマ定義で定義したtypeに該当するJavaクラス（何らかのデータソースから取得したデータを保持するクラス）を作成します。

```Book.java

public class Book {

    private String id;
    private String name;
    private int pageCount;
    private Author author;

    public void setId(String id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPageCount(int pageCount) {
        this.pageCount = pageCount;
    }

    public void setAuthor(Author author) {
        this.author = author;
    }
}
```

```Author.java
public class Author {

    private String id;
    private String firstName;
    private String lastName;

    public void setId(String id) {
        this.id = id;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}
```
## リゾルバ（Resolver）の作成
[GraphQLのスキーマと型定義](https://qiita.com/NagaokaKenichi/items/d341dc092012e05d6606)でも触れたとおり、スキーマ定義にてクライアントが操作できるクエリや様々な型を定義しています。ただし、スキーマはあくまで定義のみで実際のデータ操作は行いません。実際のデータ操作を行うのがリゾルバというものになります。

```BookResolver.java
@Component
public class BookResolver implements GraphQLQueryResolver {
	
	public Book bookById(String bookId) {
		// 実際は何らかのデータストアからデータを読み込み返却するケースがほとんどだが、ここではダミー値を返却
		Book book = new Book();
		book.setId(bookId);
		book.setName("bookName");
		book.setPageCount(900);
		Author author = new Author();
		author.setId("0001");
		author.setFirstName("fName");
		author.setLastName("lName");
		book.setAuthor(author);
		return book;
	}
}


```



## 実行
GraphQLを実行するには、[GraphQLの便利なツール](https://qiita.com/NagaokaKenichi/items/f83148f4903b17d1d2f0)でも紹介した通り、GraphiQLとGraphQL Playground等のツールを利用します。今回は、GraphQL Playgroundのデスクトップ版を利用します。
※ダウンロード、インストールは[GraphQLの便利なツール](https://qiita.com/NagaokaKenichi/items/f83148f4903b17d1d2f0)を参照ください。
Spring Bootを起動したら、インストールしたGraphQL Playgroundを立ち上げます。「URL ENDPOINT」を選択し、http://localhost:8080/graphql を入力しOPENをクリックします。立ち上がったら、左ペインに以下のクエリを書いて再生ボタンを押してみます。

```
query {
  bookById(id:1) {
    id
    name
  }
}
```

以下のようなレスポンスが返ってくれば成功です。

```
{
  "data": {
    "bookById": {
      "id": "1",
      "name": "bookName"
    }
  }
}
```

取得項目を増やしてみましょう。今度は以下のクエリを書いて再生ボタンを押してみます。

```
query {
  bookById(id:1) {
    id
    name
    author {
      id
      firstName
      lastName
    }
  }
}
```

以下のようなレスポンスが返ってくれば成功です。ソースを変更せずに取得したい項目が動的に変えることが可能となります。

```
{
  "data": {
    "bookById": {
      "id": "1",
      "name": "bookName",
      "author": {
        "id": "0001",
        "firstName": "fName",
        "lastName": "lName"
      }
    }
  }
}
```

以上です。

## 参考

* https://www.graphql-java.com/documentation/master/
* https://www.graphql-java.com/tutorials/getting-started-with-spring-boot/
* https://techblog.yahoo.co.jp/advent-calendar-2018/create-springbook-graphql-api/
* https://github.com/graphql-java-kickstart/graphql-spring-boot#enable-graphql-servlet