SAP Graph自由研究1時間チャレンジ

この記事は [chillSAP 夏の自由研究2021](https://note.com/chillsap/n/n08ef5ec73b4c)の記事として執筆しています。
##はじめに

夏休みももうおしまいですね。
この記事を読んでいる方々は大人の紳士淑女の皆さまかと思いますが、皆さまは子どもの頃、夏休みにどんな自由研究をした記憶がありますでしょうか。

内容はさておき当の私はといえば、登校日の朝に研究を捏造し、締め切り前に必死で模造紙に架空の結果を書き殴ったことを思い出します。

残念ながら次郎くんはあれから十数年経った今でも何も変わっておらず、**ガチのマジで何の準備もしないまま**、とうとう夏休みの最終日を迎えようとしているようです。
![スクリーンショット 2021-08-29 20.24.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277725/f0588ea3-0510-1328-e58d-dfe230be759d.png)

本来であれば少年時代に培った、頭の中という最高の研究室で仮説検証から考察まで全てを行う、歩く荒唐無稽と呼ばれた私の能力をまざまざと皆さまにお見せしたかったのですが、この気持ちをぐっと堪えて**1時間で実機検証も行いつつ記事を書いてみることにしました。**

以上、とにかく準備を怠ったことのアピールでした。
早速本題に参りましょう。

##研究のきっかけ
以前からGraphQLという技術に興味を持って情報収集していたのですが、去年のTechEdで**SAP Graph**
というワードを見てからずっと気になっていたのでこのテーマを選びました。

##GraphQLとは？
本題のSAP Graphの前にGraphQLについて超簡単に書きます。
GraphQLとは、WebAPI用のクエリ言語であり、WebAPIにおけるSQLのような存在です。(概念理解のために噛み砕いて表現しています)
一般的なRestfulAPIと比較されることが多く、次世代APIと呼ばれたりもするそうな。

RestfulAPIの以下のような弱点が克服された特徴を持っています。
- 取得情報を呼出し元でコントロールできない
- 仕様変更に弱い

一般的なRestfulAPIでは、API内で定義した(決められた)情報を返すことしかできません。
例えばGraphQLの説明でよく見かけるスターウォーズのAPIで言うと、People APIのID No.4を実行すると以下のような結果が返ってきます。
![スクリーンショット 2021-08-29 21.14.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277725/ab1a82dd-dfc2-528e-c419-3f1e8110a31a.png)

多くの情報が得られますが、呼出し元のアプリケーションで必要となるデータが名前（name）のみだった場合、それ以外のデータは不要なデータとなります。
つまりアプリケーション側ではこの無駄な情報を黙って受け取るしかないのです。

得られた情報以上の情報が必要な場合、例えばname: Darth Vaderが出演している作品がどれなのか知りたい場合は別のAPIを実行しなければならない、といった手間が発生します。
また、APIのエンドポイント名の仕様が変わってしまった場合などは呼出し元側でも変更を入れる必要があり、これも手間になります。

こんな問題を解決したのがGraphQLという仕組みです。

##あれ？ODataは？

GraphQLの説明前に、カンの鋭い方であればここで気づいたかもしれません。
SAPの世界には(SAPに限った話でもありませんが)ODataという強い味方がいます。
ODataを呼出す際の記述は、こんな感じで定義が出来ていました。

```Java:CreatePurchaseOrder.java
  @Override
    protected void doPost(final HttpServletRequest request, final HttpServletResponse response)
            throws ServletException, IOException {

        final PurchaseOrder po = PurchaseOrder.builder()
                                .purchaseOrderType("NB")
                                .purchasingOrganization("organization")
                                .purchasingGroup("group")
                                .companyCode("1000")
                                .supplier("supplier")
                                .language("JA") 
                                .purchaseOrderItem(poi)
                                .build();
```

先ほど紹介した一般的なRestfulAPIとは異なり、**呼出し元側でAPIへ渡す(受け取る)情報量をコントロール出来ていた**、というのがODataです。
普段何気なく利用していたのですが、これって大きな恩恵だったのですね。(しみじみ)

ですが、ODataさんを持ってしても、OData自体の仕様が変わってしまったりしては手の打ちようがありません。
また標準のODataは伝票単位で作られていることが多いため、例えば特定の出荷伝票に紐づく販売伝票を取得しようとすると複数のODataを実行する必要があります。

##GraphQLで解決

GraphQLでは必要なデータだけを指定してリクエストを投げます。
先ほど例で言うと、Darth Vaderが出演している作品だけを取得する場合はこのようなクエリでGraphQLのエンドポイントを実行します。

```js
query {
  person(personID:4) {
    name
    filmConnection {
      films {
         title
      }
    }
  }
}
```

そうすると一回のリクエストで必要な情報のみが取得できるのが大きなメリットです。
また、裏側の各APIの仕様やエンドポイントを理解する必要がないことも大きな特徴です。

ということでGraphQLについて書いてきましたが本題です。

##あらためてSAP Graphとは？

ここまで書いてきたことを読んでいただけると、SAP Graphについて表した図をおおよそ理解できるかと思います。
SAPのビジネスオブジェクトってスターウォーズの登場人物以上に数が多くてリレーションも複数に構成されていますよね。
今までODataを使って直感的に分かりやすく(裏側の複雑なリレーションを理解することなく)データを取り扱っていましたが、SAP Graphを仲介させることでもっと楽しようよ、というのが超ざっくりした私の解釈です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277725/095df905-bb7c-6203-5fb4-192086593b67.png)


##SAP Graphやってみた
今回1時間しか時間がありませんので、SAPさんに感謝しながら超簡単に[API Business Hub](https://api.sap.com/package/SAPGRAPH/odatav4)上でSAP Graphを実行してみます。
(こちらの[ブログ](https://blogs.sap.com/2021/06/15/part-2-hello-graph-write-your-first-sap-graph-application/)と内容はほぼ同一です。)

現在API Business Hub上で公開されているのは下記の5種。
少ない！と思った方もいるかもしれませんが、先ほど説明した通り裏側の複雑なリレーションを一切理解せず情報をやり取りする、という意味ではこれだけシンプルな形でよくまとまっている証拠でもあるのかなと思います。
![スクリーンショット 2021-08-29 22.26.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277725/03c573a7-5ebd-3ca1-c786-a24c42635e37.png)

参考ブログに則ってSalesからCustomerQuoteを動かしてみます。
Try OutからSandbox環境を試すことが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277725/52314d2d-e128-7452-936e-b755f468ab52.png)

Requestパラメータをいくつか変更することができます。
まずはレコードを上から適当な数だけ取得してみます。
これをそのまま動かすとこんな形でSandbox環境のSalesQuoteのレコードが取得できます。
これがブログの結果部分で得られているところですね。
![スクリーンショット 2021-08-29 22.32.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277725/53fd2d92-640a-c13e-ea71-cadf002959a2.png)

残念ながらAPI Business Hubではそんなに細かなRequestパラメータを設定が出来ないのですが、例えば欲しい情報がidとsalesOrgだけだったりする場合、こんな形でパラメータを指定すれば必要な情報にだけアクセスすることが出来ます。
![スクリーンショット 2021-08-29 22.33.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277725/15c62951-47c0-7e3b-5f85-3c3d58ad75e2.png)
![スクリーンショット 2021-08-29 22.34.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277725/112e2459-61a2-a257-4f9b-e7d87577b28a.png)
さらに例えば、salesOrgをクエリ上で指定すれば特定のsalesOrgを持ったSalesQuoteを1回のAPI実行で取得出来ることになります。

本当はさらに強力な、このSalesQuoteに紐づくProduct情報を1回の実行で取得するなどを試してみたかったのですが、それはまたの機会にやってみます。(時間切れ)

##考察・展望
OSSの世界では続々とGraphQLが流行っているっぽいのですが、SAPの世界でも流行っていくんじゃないかと感じました。
改めてODataのありがたさも感じました。
しかし複雑なSAPのビジネスオブジェクトをカプセル化しているとはいえ、標準のODataは[死ぬほど数があり](https://help.sap.com/doc/55bb1642ea614bf582d514ed34401136/1.0/en-US/index.html)まだまだ探すのが大変だったりするので、SAP Graphでもっと楽ができるといいなと楽観的に思いました。

###参考
無かったら死んでました。本当にありがとうございました。
https://dev.classmethod.jp/articles/reinvent19-graphql-modern-api/
https://qiita.com/NagaokaKenichi/items/a4991eee26e2f988c6ec
https://blogs.sap.com/2021/06/08/part-1-introduction-to-sap-graph/
https://blogs.sap.com/2021/06/15/part-2-hello-graph-write-your-first-sap-graph-application/
https://explore.graph.sap/docs/beta/overview


###終わりに

もっと時間をかけて、ちゃんとコード書いて検証しろよという声が聞こえてきそうで恐縮です。
来世ではもっと計画的に宿題ができる子になれればいいな、とお祈り申し上げます。
とりあえず本当にざっくりした触りだけ皆さまに伝わればと思います。
雑な記事でしたが、私から無言の圧力を置いてシメたいと思います。

https://zenn.dev/kaityo256/articles/save_the_earth