LoginSignup
2
1

More than 1 year has passed since last update.

Apolloライブラリを使用してGraphQL Clientを実装しながら学ぶの巻

Posted at

はじめに

本記事は@ruwatanaさんの記事Java × Spring Boot × Apollo で GraphQL クライアントを実装するを参考に作成しました。

@ruwatanaさんの記事との主な違いは

  • IntellJ IDEAを利用した実装を前提とする
  • Spring Bootを利用しない
  • Kotlinで実装する

です。

本記事は、MacでGraphQLのClient開発環境をIntelliJ IDEA, Apolloライブラリ, Kotlin, gradleを利用して作成する方法を説明することを目的としています。

尚、本記事で作成したIntelliJ IDEAのProjectをhttps://github.com/kobunhada/GraphQLClientExampleに公開しています。よろしければ参考&忌憚のないツッコミをお願い致します。

記事作成時の開発環境について

本記事を作成する際に使用した開発環境は以下の通りです。versionについては、2021/08/29時点で(多分)最新だと思います。

環境 Version 備考
OS macOS 11.5.2(Big Sur)
IDE IntelliJ IDEA 2020.3.4 gradle, KotlinSDK等は当IDEに依存
IDE Plugin JS GraphQL 3.0.0 IntelliJ IDEAでGraphQLファイルを扱うのに便利なPlugin
GraphQL Client Apollo Client 2.3.5 build.gradleに設定
GraphQL Server環境構築 Node.js v16.8.0 local環境にGraphQL Pokémon Serverを構築する為に必要
GraphQL Server環境構築 yarn 1.22.11 同上
Terminal 任意のTerminalアプリ -

GraphQL Serverの準備

当記事では、GraphQL Clientの作成を目的としているので、GraphQL Serverは、GraphQL学習者には有名?なGraphQL Pokémonを利用します。

GraphQL PokémonのServer構築にはNode.jsとyarnが必要です。構築方法については@thesugarさんの記事Mac に Node.js 環境をさくっと整えるための最短ルートがお薦めです。

Node.jsとyarnのインストールが完了したらGraphQL Pokémonを任意のDirectoryにCloneしましょう。

GraphQL PokémonをClone(localに持ってくる)する。

任意のGit Clientアプリ(GitHub Desktopなど)で任意のDirectryにCloneしましょう。

Tearminalアプリを使ってsshでcloneした例
git clone git@github.com:lucasbento/graphql-pokemon.git

Cloneが上手く行かない(わからない)場合は、GraphQL Pokémonのサイトを開いて、zipファイルをDownloadでも無問題です。その場合は、任意のディレクトリにDownloadしたzipファイルを展開して下さい。

graphql_pokemon.png

GraphQL Pokémonを起動する

ターミナルアプリで実行します。

1.GraphQL PokémonをCloneしたdirecoryのrootに移動します。

cloneしたdirectoryのrootに移動
cd [あなたがClone(or zipファイルを展開したDirectory)]/graphql-pokemon

2.GraphQL PokémonをBuildして起動します。

buildして起動する
yarn
yarn run build-app
yarn start

起動まで成功すると

成功した場合
GraphQL-Pokemon started on http://localhost:5000/

が出力されて、GraphQL Pokémon Serverにアクセス出来るようになります。

http://localhost:5000/にアクセスして以下のサイトが表示されたら成功です。

pokemon_server.png

GraphQL Pokémon Serverについて

画面の左側にGraph QLのQueryを書いて実行(丸に三角矢印ボタン)すると右側に実行結果が出力されます。

executequery.png

また、上記サイトの右上に< DOCsボタンがありますが、ここからGraphQL PokémonのSchemaを確認できます。

expanddocs.png

JS GraphQL Pluginの導入

IntelliJ IDEAでGraphQLのファイルを扱う場合に便利なPluginです。また、本記事では、当Pluginのインストールを前提に説明します。
インストール方法は、他のPlanginと同様です。

JS GraphQLをインストールする

1.メニューから Preferencesを選択する

jsgraphql.png

2.左側のPluginsを選択し、右上のMarketplaceを選択後、GraphQL等で検索してJS GraphQLをインストールして下さい。

jsgraphql2.png

インストール後、NewメニューからGraphQL関連のファイルを作成できます。
jsgraphql3.png

新規Projectの作成

以下の設定でIntelliJ IDEAの新規Projectを作成して下さい

  • 言語: Kotlin/JVM
  • Build Tool: Gradle

Project作成例

newproject1.png
newproject2.png

Projectが作成されたらbuild.gradleを開いて下さい。

openbuildgradle.png

Apolloライブラリの導入

Apploライブラリは GraphQLのClientライブラリです。

  • 以下pluginをbuild.gradlepluginsに追加して下さい。
    • 'com.apollographql.apollo' version '2.5.3'
pluginsに追加後のbuild.gradle
plugins {
    id 'java'
    id 'org.jetbrains.kotlin.jvm' version '1.5.30'
    id 'com.apollographql.apollo' version '2.5.3'
}
  • 以下、3つのライブラリをbuild.gradledependenciesに追加して下さい。
    • com.apollographql.apollo:apollo-runtime:2.5.3
    • com.apollographql.apollo:apollo-coroutines-support:2.5.3"
    • com.apollographql.apollo:apollo-rx3-support:2.5.3
dependenciesに追加後のbuild.gradle
dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib"
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
    //Apollo client library for read GraphQL web server
    implementation("com.apollographql.apollo:apollo-runtime:2.5.3")
    implementation("com.apollographql.apollo:apollo-coroutines-support:2.5.3")
    implementation("com.apollographql.apollo:apollo-rx3-support:2.5.3")
}

追加後、gradleのsyncを忘れずに実行して下さい。

GraphQLの各種ファイルの追加

GraphQLのServerからDataを取得するためには

  • Schama定義ファイル
  • GraphQL Queryファイル

が必要です。

GraphQLのSchama定義ファイルを追加する

以降のターミナルでの作業はIntelliJ IDEAのターミナルから実行した方が多分楽だと思います。以下は、IntelliJのターミナルの表示方法の説明です。

1.IntelliJのターミナルを表示する

画面の下にある"Terminal"をクリックしてTerminalを表示する.
terminal.png

2.Schama定義ファイルの出力先directoryをProjectに作成する

project/src/main/に、任意の名前でdirectoryを作成する.

directryを作成する
mkdir -p src/main/graphql/graphqlpokemon 

3. schema.jsonを生成する(=Schama定義ファイルの出力)

前もって準備したGraphQL Pokémon ServerのEnd Pointを指定してschema.jsonを生成します。

schema.jsonを生成する
./gradlew downloadApolloSchema \
  --endpoint="http://localhost:5000/graphql/endpoint" \
  --schema="src/main/graphql/graphqlpokemon/schema.json"
build成功時
BUILD SUCCESSFUL in 584ms
1 actionable task: 1 executed

buildに失敗した場合は、build.gradleの設定を見直して下さい。

GraphQLのQueryを追加する

続いて、Queryを追加します。

1.Queryファイルを作成する

./src/main/graphql/graphqlpokemondirectoryを右クリック-> New -> GraphQL File の順で選択し、任意のQuery名で作成して下さい。
graphqlquery1.png

Query名を入力(拡張子は不要)
graphqlquery2.png

2.Queryを実装する

http://localhost:5000/にアクセスしてQueryが正しく動作するかを確認してから実装した方が多分楽です。

ExampleQuery.graphqlの実装例
query Example {
    pokemons(first: 10) {
        number,
        name,
        maxHP,
        maxHP,
        image
    }
}

3.ReBuildする

ReBuildすることで、Apolloライブラリが 2.で追加したQueryのモデルクラス(graphqlpokemon.ExampleQuery)を生成してくれます。

rebuild.png

Clientアプリの実装

以下を実装して下さい。

  • graphqlpokemon.Example・・・GraphQLからデータを取得する為のクラス
  • graphqlpokemon.Main・・・mainメソッド。Example.get()メソッドをcallして、dataを標準出力する
src/main/java/graphqlpokemon/Example.kt

package graphqlpokemon

import com.apollographql.apollo.ApolloClient
import com.apollographql.apollo.coroutines.await
import java.lang.Exception

class Example {
    suspend fun get(): MutableIterator<ExampleQuery.Pokemon>? {
        val apolloClient = ApolloClient.builder()
            .serverUrl("http://localhost:5000/graphql/endpoint")
            .build()
        val query = ExampleQuery.builder().build()
        val result: MutableIterator<ExampleQuery.Pokemon>? = try {
            apolloClient.query(query).await().data?.pokemons?.iterator()
        } catch (e: Exception) {
            null
        }

        return result

    }
}

src/main/java/graphqlpokemon/Main.kt

package graphqlpokemon

import kotlinx.coroutines.*
import kotlin.jvm.JvmStatic
import kotlin.system.exitProcess

object Main {
    private var isExit = false
    @JvmStatic
    fun main(args: Array<String>) {
        GlobalScope.launch {
            val pokemons = Example().get()
            if (pokemons == null) {
                println("no pokemon")
                isExit = true
            } else {
                pokemons.forEach { pokemon ->
                    delay(100)
                    println(
                        "number:%s, name:%s, hp:%s, cp:%s, image url:%s".format(
                            pokemon.number,
                            pokemon.name,
                            pokemon.maxHP,
                            pokemon.maxCP,
                            pokemon.image
                        )
                    );
                }
                isExit = true
            }
        }
        while (true) {
            Thread.sleep(100)
            if (isExit) exitProcess(0)
        }
    }
}

成功すれば、以下の様に出力されます。

実行結果
number:001, name:Bulbasaur, hp:1071, cp:951, image url:https://img.pokemondb.net/artwork/bulbasaur.jpg
number:002, name:Ivysaur, hp:1632, cp:1483, image url:https://img.pokemondb.net/artwork/ivysaur.jpg
number:003, name:Venusaur, hp:2580, cp:2392, image url:https://img.pokemondb.net/artwork/venusaur.jpg
number:004, name:Charmander, hp:955, cp:841, image url:https://img.pokemondb.net/artwork/charmander.jpg
number:005, name:Charmeleon, hp:1557, cp:1411, image url:https://img.pokemondb.net/artwork/charmeleon.jpg
number:006, name:Charizard, hp:2602, cp:2413, image url:https://img.pokemondb.net/artwork/charizard.jpg
number:007, name:Squirtle, hp:1008, cp:891, image url:https://img.pokemondb.net/artwork/squirtle.jpg
number:008, name:Wartortle, hp:1582, cp:1435, image url:https://img.pokemondb.net/artwork/wartortle.jpg
number:009, name:Blastoise, hp:2542, cp:2355, image url:https://img.pokemondb.net/artwork/blastoise.jpg
number:010, name:Caterpie, hp:443, cp:367, image url:https://img.pokemondb.net/artwork/caterpie.jpg

Process finished with exit code 0

おわりに

筆者は、GraphQL未経験&Kotlinも久し振り(と言うか、Coding自体がほぼ半年振り)なので拙い内容かもしれませんが、誰かのお役に立てれば幸いです。

参考

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1