GraphQL を Spring Boot で試してみる 1

最近、GraphQL が気になっています。学習を兼ねて簡単なサンプルを作ってみようかと。今回、Spring Boot で Query を試してみます。

サンプルコードはこちら。

kntmr/playground/graphql-spring-examples - GitHub

GraphQL

graphql.org

2015-2016年頃に登場してしばしば名前を見かけることはあったのですが、自分の観測範囲ではあまり盛り上がりを感じられず...。ただ、REST API の煩雑なところをいい感じに解決してくれそうで、今さら魅力を感じるようになってきました。

よく言われる GraphQL の特徴は以下のあたりかと思われます。

  • エンドポイントを1つにまとめることができる
  • 1リクエストで必要なデータを取得できる
  • スキーマファースト (ドキュメントファースト)

とはいえ、レスポンスとして返して欲しいデータをリクエストで指定したり、Swagger などを使うことで同等のことは実現できるかと思います。ただ、当然、サーバー側でそれなりに実装したり、ツールを導入する手間はかかるわけで、そのあたりは GraphQL を使うメリットになりそう。あと、今回は試してないですが、コードを自動生成するツールもあるようです。

あと、AWS がマネージドサービスとして提供するようになったので、今後、適用事例も増えていくんではなかろうかと思っています。

aws.amazon.com


以下、備忘録。

依存ライブラリ

GraphiQL を追加すると、/graphiql で GraphiQL が使えるようになる。

<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphql-java-tools</artifactId>
    <version>5.2.4</version>
</dependency>
<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphql-spring-boot-starter</artifactId>
    <version>5.0.2</version>
</dependency>
<dependency>
    <groupId>com.graphql-java</groupId>
    <artifactId>graphiql-spring-boot-starter</artifactId>
    <version>5.0.2</version>
</dependency>
schema / データクラス

resources/graphql/schema.graphqlsスキーマを定義。データクラスでは、参照先のクラス側に ID のフィールドを定義する。今回のサンプルでは、あるグループに所属するユーザーの ToDo リストを返すことを想定。

type Group {
    id: ID!
    name: String!
}
type User {
    id: ID!
    name: String!
    group: Group!
    todos: [ToDo]
}
type ToDo {
    id: ID!
    content: String!
    completed: Boolean!
}
DAO / Resolver

DAO は適当にダミーデータを返すように実装。Resolver は、Query の場合は GraphQLQueryResolver インタフェースを実装する。

@Component
public class UserQueryResolver implements GraphQLQueryResolver {
    private UserDao userDao;
    public UserQueryResolver(UserDao userDao) {
        this.userDao = userDao;
    }
    public User getUser(int id) throws Exception {
        return userDao.findById(id).orElseThrow(() -> new Exception("User not found."));
    }
}

データの関連を解決する場合は GraphQLResolver<T> インタフェースを実装する。今回、グループとユーザーの関連を解決する場合は次の通り。

@Component
public class GroupResolver implements GraphQLResolver<User> {
    private GroupDao groupDao;
    public GroupResolver(GroupDao groupDao) {
        this.groupDao = groupDao;
    }
    public Group group(User user) {
        return groupDao.findById(user.getGroupId()).orElse(new Group(0, "Undefined"));
    }
}

ユーザーと ToDo の関連を解決する場合は次の通り。

@Component
public class TodoResolver implements GraphQLResolver<User> {
    private TodoDao todoDao;
    public TodoResolver(TodoDao todoDao) {
        this.todoDao = todoDao;
    }
    public List<ToDo> todos(User user) {
        return todoDao.findByUser(user.getId());
    }
}
リクエス

アプリを起動して、http://localhost:8080/graphiql にアクセスする。以下の形式でリクエストする。指定したフィールドをレスポンスで返してくれる。

query {
  getUser(id: 1) {
    id
    name
    group {
      id
      name
    }
    todos {
      id
      content
      completed
    }
  }
}

所感

今回は簡単なサンプルでしたが、スキーマが複雑になるほど必要なデータクラスや Resolver が多くなりそうです。ただ、このあたりは自動生成のツールを使うことで解決できるんだろうか。スキーマファーストというだけあって、やはりスキーマの設計がキモなんだろうと思われます。いかに無駄なくシンプルに設計できるか。

次は Mutation を試してみようかと。あと、全体的にまだ理解が浅いのでドキュメントを読んで勉強する。その他、自動生成などの開発ツール周りを調べたい。

参考

JJUGナイトセミナー「JDK 11リリース記念:今知っておくべきJDK 11の重要ポイント」に行ってきた #jjug

先日、JJUGナイトセミナー「JDK 11リリース記念:今知っておくべきJDK 11の重要ポイント」に行ってきました。簡単に所感をまとめます。

jjug.doorkeeper.jp

メモから抜粋。(詳しくは資料をご参照ください)

Java Is Still Free

Java Is Still Free の翻訳がついに来た。ありがたい。

www.sakatakoichi.com

JDK 11 リリースなので改めて「新しい JDK リリースモデル解説 (サマリー&アップデート)」

www.slideshare.net

  • Oracle OpenJDK
    • GPLv2 + Classpath Exception
    • ラクルによるセキュリティアップデート提供
  • Oracle JDK
    • 今まで(v9/v10)までのライセンスと少し違う
    • 商用ライセンス or OTNLA for Oracle Java SE
    • JDK11以降は社内もしくは個人での開発/テスト/試作/デモの用途では無償で利用可能
  • OTNLAが6ヶ月で切れるかどうかは未定 (LTSと同期間になる可能性はある)
  • JMCは個別にダウンロードできるようになる
  • Subscription
    • Javaが実行される可能性のあるすべてのハードウェアが対象
    • デスクトップとサーバーが対象 (クラウド含む)
    • Named User Plus (1台から購入可能、個人でも購入できる予定)
    • Processor

Java 11 : サポートとVM機能編

www.slideshare.net

サポート

  • 開発サポート
    • OpenJDK コミュニティ
  • 配信サポート
    • OpenJDK コミュニティは配信はしていない
  • 問い合わせサポート
  • AdoptOpenJDK
    • 配信サポート期間が一番長い(4年)
  • OpenJDK の開発サポートは現時点では3年間
    • 今後より長くなる可能性もある
  • Oracle JDK から OpenJDK のマイグレーション
    • 証明書周りがネックになるかも (配信元による)
    • だいたいはライセンスの問題
  • AdoptOpenJDK のリリースが遅れているかのは大丈夫か
    • テスト期間があるので1-2週間は遅れる
    • ゼロデイ攻撃が心配なら Oracle OpenJDK の利用を検討する
  • JRE
    • コンテナなどで、バイナリサイズを削減したいなら jlink を使う
    • モジュール化が進むとより効果がありそう
  • 特に理由がなければ OpenJDK の開発サイクルが短いバージョンは無視してOK
  • 多くの場合、必要なのは配信サポート
    • AdoptOpenJDK が4年なのでマイグレーションに1年の猶予がある
    • 問い合わせサポートは予算とSLAに依存する

VM機能

  • JEP 330
    • ソースファイルを java コマンドで実行
    • Java ソースをスクリプトのように扱う (バージョン指定可能)
  • JEP 328 (Flight Recorder)
    • プロファイラ
    • Oracle JDK のものとはオプション構成が違う
  • JEP 318 (Epsilon)
    • No-Op GC
    • 主に開発や研究用途を想定
  • JEP 333 (ZGC)
    • アプリケーションスレッドとGCスレッドの並列化
    • 従来のGCとはアルゴリズムが異なる (世代別GCではない、など)
    • 64bit, Linux 限定

Java 11 : APIの変更点編

  • JEP 181 (Nest-Based Access Control)
    • Nestmates
    • 第5のアクセス制御 (インナークラス間の private メンバ参照)
    • NestHost, NestMembers
  • JEP 309 (Constant Dynamic, condy)
    • Constant Dynamic が Constant Pool に入る
    • static final フィールドではなく、class-file 上の定数
  • JEP 320
    • Java EE & CORBA 関連モジュール削除
    • Maven artifact を使う
  • JEP 321 (HTTP Client)
    • モダンな API, HTTP2, Reactive
    • 非同期呼び出しの場合は Flow が返る
  • JEP 323
    • ローカル変数の型推論が Lambda で使えるように

API

  • trim は全角空白は取れないが、strip は全角空白が取れる
  • Collection#toArrayIntFunction を取るように
    • List.of("aaa").toArray(String[]::new) (要素数を指定せずにメソッド参照で書ける)
  • Predicate.not
    • 今までメソッド参照が使えなかったところが使えるように (String::inEmpty とか)
  • 元号対応 (Japanese Era)
    • "JapaneseEra.HEISEI 31/5/1" 以降を指定するとエラーになる
  • += のバグ
  • TimSort

JDK12

  • JEP 326 (Raw String Literals)
    • バッククォートで囲む
    • 変数の埋込は今のところない
  • JEP 325: Switch Expressions

さり気なく JShell のバージョンが JDK 12 っていうのがなんとも。

Developers.IO 2018 に行ってきた #cmdevio2018

先日、Developers.IO 2018 に行ってきました。

dev.classmethod.jp

セッションレポートと発表資料は以下にまとめられています。

Developers.IO 2018 セッションレポートと発表資料まとめ #cmdevio2018

今回参加したセッションは以下の通り。最後までいるつもりだったけど、16時過ぎで体力切れ...。無念。

1000件以上の活用を見てわかった絶対に失敗しないAWSベストプラクティス

おなじみの AWS Well-Architected Framework の話です。

基礎から応用までじっくり学ぶ「AWSでのネットワークの作り方」

ネットワーク関連はあまり知見がないため、基礎の部分はとても勉強になりました。最後の方は若干理解が追い付かず...。

クラスメソッドにおけるWeb APIエンジニアリングの基本的な考え方と標準定義

今回聴きたかったセッションの1つ。API アクションやユースケース、パス、リソースなど、Web API を検討するときにどういうことを考えるのか、とても参考になりました。CQRS のエッセンスを取り入れるのはいいけど、例えば、RDB から ES に大量にデータを連携するときにタイムラグは発生しないのだろうか。

あと、クラスメソッドさんもドキュメントに GitBook を使っているということを知れてよかったです。自分のプロジェクトでも使ってるけど、あまり開発がアクティブじゃないっぽくてちょっと不安になってたのでw

dev.classmethod.jp

次世代モバイル向けクラウドサービスAWS AppSyncを使って店舗スタッフと顧客の体験を最大化する方法

最近、GraphQL に興味があって、今回聴きたかったセッションの1つ。スキーマをもとにコードを自動生成するツールが豊富というのはちょっと意外でした。GraphQL 自体の前提知識は必要なものの、スキーマファーストの開発は確かに効率がよさそう。

AWSのセキュリティ設定がどうなっているか抜け漏れなくちゃんと確認する方法

責任範囲の理解、現状把握、対策。必要に応じてツールや専門家を活用する。あと、初めて生の徳丸さんを観ました。徳丸本第2版ポチるか。

ビジネスを阻害しない!AWSアカウントのID・権限管理について

IAM の構成要素やベストプラクティスの話。AWS を使う上で特に重要な内容の1つだと思います。要復習。

その他

ありがたいことにほとんどの資料はすでに公開されています。今回参加できなかったセッションの資料もあとで読もうと思います。

GitHub から Potential security vulnerability found という通知が来てた

GitHub の通知欄に「Potential security vulnerability found in the bootstrap dependency」という通知が来てた。クリックしてみるとこんな表示が。

f:id:knt_mr:20180920170710p:plain

package.json脆弱性のある依存パッケージが含まれているからアップデートしなさい、ということらしい。

「Review vulnerable dependency」をクリックすると、Bootstrap に CVE-2018-14041 という脆弱性があることが分かります。

f:id:knt_mr:20180920170719p:plain

初めて知りましたが、GitHub はこういうのを検出してくれるんですね、親切。

で、このプロジェクトなんですが、もともと学習のためにお試しで作ったもので、かつ、Bootstrap 3 から 4 にアップデートするのがちょっと面倒だったので、今回はそっ閉じすることに...。時間があったらアップデートしよう。

GitHub - kntmr/bootstrap-vue-mockup

現場からは以上です。

GFUG の「各ベンダーのJDKリリースモデル特集!」に行ってきた #glassfish_jp

先日、GFUG の「各ベンダーのJDKリリースモデル特集!」に行ってきました。簡単に所感をまとめます。

glassfish.doorkeeper.jp

メモから抜粋。

Azul Systems - Your Long Term Java Partner

  • Microsoft は Azul 製品の最初のユーザー
  • Zing
    • Java ランタイム
    • JavaGC やウォームアップの問題を排除
    • パフォーマンスのよさがウリ (HotSpot よりパフォーマンスがいい)
    • ヒープ 8TB までをサポート
    • LLVM ベースの JIT コンパイラ
  • Zulu / Zulu Enterprise
    • Zulu は OpenJDK ビルド
    • Java スタンダードに準拠 (Java SE 認定の100%オープンソース)
    • Enterprise は Zulu + サポート
    • LTS あり
    • 10年以上(!)のサポートあり
  • Zulu Embedded
    • 組み込みや IoT 向け
    • 技術的な違いは Enterprise と違いはない
    • 組み込みの場合は Embedded になる?
  • x86/32ビットOSをサポート
  • 非LTS版 の Mid Term Support あり
  • Java FX はすべてサポート
  • ブラウザのプラグインや Applet はない
  • Azul のサポートは基本的に英語 (日本にエンジニアがいない)

オープンソースで提供される第二のJVM:OpenJ9 VMIBM Javaについて

www.slideshare.net

  • IBM SDK for Java Technology
    • Java SE 仕様に準拠
    • IBM 独自実装の JVM (J9 VM) を含む開発/実行環境
    • サーバーサイドのみ (JavaFX などは含まれない)
  • OpenJ9
  • OpenJDK + OpenJ9
    • OpenJDK (クラスライブラリ) + OpenJ9 (JVM)
    • AdoptOpenJDK や Docker Hub (Dockerイメージ) から入手可能
  • サポート
  • IBM SDK for Java Technology
    • OpenJDK + OpenJ9 ベース + IBM 独自機能
    • 製品同梱で提供
    • 単独入手は Docker イメージのみ
    • IBM SDK for Java 11 は 2025年までサポート
  • 今後、IBMミドルウェアは原則としてDockerイメージで提供していく
  • WebSphere Liberty
    • 軽量/高速なランタイム
    • Open Liberty の商用版
  • OracleIBMバグフィックスは別物か?
    • 原則、Oracle と同期するようにしている
    • 今のところ Oracle からパッチの提供を受けている

今後の Java に関して

  • なぜ半年1回のリリースになったのか
  • IT業界においての3年はとても長い
  • 3年ごとに新しい機能を入れても価値がないかもしれない
  • Java の進化のためにサイクルを早くする
  • モジュール化によって新しい機能を追加しやすくなった
  • Java の開発/提供もアジャイル的に
  • JDK10 から Docker コンテナの対応を強化
    • ヒープのメモリ割り当てや CPU 状況の取得を改善
  • JDK11 では今まで動いてたアプリケーションが動かないかも?
    • Java SE から多くのパッケージが削除される (JAX-WS, JAXB, ...)
    • 依存ライブラリを追加する
    • ユーザー側で対応できるのか製品側の対応を待つ必要があるのかを確認すること
  • カスタム JDK/JRE が作れる

その他

今回の勉強会に合わせて公開された Red Hat さんのエントリ。

nekop.hatenablog.com

あと、Java Champion の公式アナウンス。あとで読む。

ちなみに会社の別チームでは Oracle JDK のサポートを購入するという話になっているところがチラホラ...。他には製品ベンダーの対応を待つ感じですかね。

コミュニケーションの敷居を下げてプロジェクトの雰囲気をよくする

最近よく思うのは、コミュニケーションの敷居が低くなるとプロジェクトの雰囲気がよくなる、ということ。

ここで言う『敷居が低い』には2つあって、コミュニケーションが簡単にとれることと、その内容に親近感 (安心感?) があること。

ここ数年、Slack などのコラボレーションツールが広く使われるようになり、メールを使う機会は以前よりずっと少なくなりました。

一般的にチャット上のテキストは口語的なものが多いと思われます。また、絵文字や顔文字を使うことで表現豊かなコミュニケーションが手軽にできます。メール時代にあったような挨拶文 (「お疲れ様です、○○です。」のような前置き) を書く必要はありません。チャットはメールよりリアルタイム性に優れているため、コミュニケーションのサイクルが格段に早く感じます。

たまには雑談を交わすのも OK です。ノイズが気になるなら専用のチャンネルやルームを用意すればいいわけです。

お堅い現場ではそうはいかないかもですし、モノによりますが、このようなツールを使う環境を用意するのはそれほど難しくはありません。とはいえ、ゆるい雰囲気で使えるかどうかはメンバーの性格やノリによるところが大きいと思います。そんなときは誰かが率先してゆるい雰囲気を作る必要があります。

自分は決してそういうキャラではないのですが (たぶん)、ゆるい雰囲気を作るために、日々、顔文字や絵文字、おもしろ画像を率先してポストする役目をこなすわけです。

de:code 2017 テスト駆動開発の動画の鑑賞会をやってみた

今さらではあるのですが、先日、昨年の de:code 2017 で t_wada さんが公演されていたテスト駆動開発の動画をみんなで鑑賞するという会をやってみました。

とはいえ、実際、de:code 2017 には参加しておらず、この動画も今年の春くらいに初めて見たのですが、内容がとてもよかったので「他のひとたちにも観てもらおう」と思ったのがきっかけです。

内容としては基本的なものかと思います。が、観たことがないという方はぜひ一度ご覧いただければと思います。途中、ライブコーディングのデモで TDD を紹介していますが、時間がない方は前半の概要と最後のまとめだけでも。(ライブコーディングのデモも非常に学びがあります)

大事なポイントとしては以下ですかね。

  • 動作するきれいなコードには2つの道がある
  • TDD のサイクル (Red-Green-Refactor)
  • テストが予想通り落ちることを確かめる
  • 仮実装、三角測量

(ちなみに書籍はこちら > テスト駆動開発)

特に、この 仮実装三角測量 はよく使う手法ですが、TDD に限った話ではないだろうと思います。

例えば、新しいフレームワークやライブラリを試すときに小さいサンプルアプリを作ったりすることがありますが、ゼロからすべてを一気に作るのは難しいので、モックのデータを返したりして、範囲を絞りながら調査を進めると思います。これは TDD の『仮実装』と同じアプローチです。

あと、デバッグするときに、あるパラメータを渡すとこう動作する、別のパラメータを渡すとこう動作する、ということはこのパラメータを渡せばこう動作するだろう、と再現パターンを調べることがあると思います。これは TDD の『三角測量』と同じアプローチです。

おそらく、テスト駆動開発の中で実践している細かいプラクティスは普段からすでにやっていることなのかもしれません。

まとめ

自分も手探りながら テスト駆動開発モドキ を実践してみた中で大事だと考えているのは、テストから考え始めること (テストファースト) です。

テストから考え始めることで、仕様に対してどのように動作するべきか、ということを整理できてシンプルな観点として落とし込めるようになります。テストがシンプルになると、それに対する実装もシンプルになり易いです。これは実践してみて初めて気が付いたことです。

いきなり実装から書き始めるといろいろな条件を1箇所のロジックに詰め込みがちで、あっという間に複雑になります。当然、その実装に対するテストも複雑になります。そして誰もメンテできなくなるわけです。

ちなみに、鑑賞会のあとに参加者で意見交換したところ、やはり気になるのは既存のアプリにテストコードがないときはどうするか、ということ。正直、あとからテストコードを追加するのは非常に難しいと考えています。というか、かけるコストに対して得られるメリットが少ないんではないかと。

こういうときはテストコードは諦めてドキュメントベースでテスト観点を管理する、というのが最近の自分の見解です。

決してテストコードを書くことはマストではないと思います。メンバーのスキルを考慮する必要もあります。大事なのは実装のあるべき姿を最初に整理して何かしらの形で残すことだと思います。もちろんそれが設計の成果物にあたるのかもしれませんが、そのあたりは現場によってさまざまなのかな。