Spring GraphQLを試してみた

## 概要
Spring BootでGraphQLのQueryを
試してみたときの記録です。
Spring GraphQLを遅ればせながらのお試し。

GraphQLの説明は[本家](https://graphql.org/)を参照してください。

# 開発環境
OS : Windows 7 Home Edition 64bit
Java : Java 11
STS : 4.10.0

# 確認手順の概要
 - Spring Bootプロジェクトを作る
 - GraphQL周りを設定する
 - サーブレットをGraphQL経由で実行する

## Spring Bootプロジェクトを作る
Spring Bootのバージョン2.1.9でプロジェクト作成、
依存関係は以下の通りです。DB周りは個々の環境に
合わせてください。

 - Lombok
 - Spring Data JPA
 - Oracle Driver
 - Oracle Database XE 

## GraphQL関連
### 要注意事項
 - Spring Bootのバージョン
 - GraphQL単体で使うことについて

#### Spring Bootのバージョン
Spring GraphQLではpom.xmlでkotlinの
バージョン指定が必要になります。
ですが、Spring Bootの選択可能なバージョンが
この記事投稿時点で2.5.5, 2.4.11等で、
これらのバージョンでは
Spring Bootの依存関係で既にkotlinがバージョン指定されて
pom.xml側で指定するとMavenでエラーになります。
回避策として一度選べるバージョンで
Spring Bootアプリケーションを作成し、
古いバージョンにグレードダウンさせて、
kotlinのエラーが発生しないようにしてから試しています。

#### GraphQL単体で使うことについて
STSでGraphQLを使おうとしたのですが、
GETのメソッドではURLパラメータを
エンコードしないといけないので、
GraphiQLを使うことにしました。

ただし、プロジェクト作成時に
依存関係追加対象に無かったため、
pom.xmlを直接編集して追加しています。

STSのバージョンによっては
作成時の依存関係追加ができるかもしれません。

```xml:pom.xml(抜粋)
<dependency>
    <groupId>com.graphql-java-kickstart</groupId>
    <artifactId>graphql-spring-boot-starter</artifactId>
    <version>11.1.0</version>
</dependency>
<dependency>
    <groupId>com.graphql-java-kickstart</groupId>
    <artifactId>graphiql-spring-boot-starter</artifactId>
    <version>11.1.0</version>
</dependency>
```

# Queryを試す
次のようなクラスで登録されている情報を
リスト取得するために必要な手順を説明していきます。

```java:UserInfo.java
// 前略
@Data
public class UserInfo {
    private String id; // ID
    private String name; // 氏名
    private Integer age; // 年齢
}
```

尚、今回の説明では既存のRESTな
Spring Bootアプリケーションに
GraphQLを使う場合に必要な手順を説明します。

 - GraphQLQueryResolverの実装クラス作成
 - application.yamlへの追記
 - schema.graphqlsの作成
 - GraphiQLで動作確認

## application.yamlへの追記
アプリケーション内でGraphiQLを動かし、
動作確認するためにGraphQLのエンドポイント、
GraphiQLのエンドポイントを指定します。
以下、最低限度の指定です。

```yaml:application.yaml
graphiql:
  enabled: true
  mapping: /graphiql
  endpoint:
    graphql: /graphql
```

## GraphQLQueryResolverの実装クラス作成
GraphQL経由でDBデータ操作する場合に
このインターフェースの実装が必要となります。
UserInfoDaoはSpring Data JPAで
作った既存部品のDAOのため、説明を割愛します。

```java:UserInfoQueryResolver.java
// 前略
@Component
public class UserInfoQueryResolver implements GraphQLQueryResolver {

    @Autowired
    UserInfoDao userInfoDao;

    public List<UserInfo> getUserInfoList() {
        return userInfoDao.getUserInfoList();
    }
}
```

## schema.graphqlsの作成
schema.graphqlsというファイルを
src/main/resources/graphql配下に
置くことでアプリケーションから
呼び出すデータの構造、メソッド、データを指定可能です。
以下、最低限度の指定です。

```graphqls:schema.graphqls
type UserInfo {
    id: ID!
    name: String!
    age: Int
}

type Query {
    getUserInfoList: [UserInfo]
}
```

## GraphiQLで動作確認
GraphiQLの使い方は[こちら](https://github.com/graphql/graphiql#graphiql)を参照してください。
まず、アプリケーション内のGraphiQLをブラウザで表示させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533981/1eb4a227-74cd-564a-9d39-0af2ed6a4b07.png)

次に取得したいリストを呼び出します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533981/b7a6cd08-d133-6985-0229-b5c676583cdd.png)
できました。

# 最後に
GraphQLでクライアント側のAPI呼び出しが画一化され、
クライアント側の多様化にもスムーズに対応できていきそうです。

# 余談
GraphQLをSpringで使えるようになり、
他言語でもGraphQLを扱っている中、
むしろサーバーサイドはJavaでなくても、と
改めて認識する良い機会になりました。

あと、全く関係ないですが、
[こちら](https://spring.pleiades.io/projects/spring-graphql#overview)だと
Spring GraphQLは「リリースに向けて」と記載されています。
英語の必要性を再認識しました。