【CAP】CAPで作ったODataをUI5アプリで使う(1) CAPサービスの作成

##CAP(Cloud Application Programming Model)とは
CAPとは、CDSをベースにODataサービスを開発する手法です。CAPで開発したODataサービスはUI5をはじめ、さまざまなフロントエンド技術で使用することができます。
CAPを詳しく学ぶには、Open SAPの以下のコースがおすすめです。
[Building Applications with SAP Cloud Application Programming Model](https://open.sap.com/courses/cp7/)

###CAPのよいところ
データモデルを定義するだけで、CRUD処理はコードを書かなくてもついてきます。ちょうど[BOPF](https://qiita.com/tami/items/b1458094d16dfdc87359)のような感じです。また、UIアノテーションをつけることもでき、作成したODataサービスからFiori elementsアプリを作成することができます。

##今回やること
上記Open SAPのコースでは、バックエンド側の開発が中心だったため、作成したODataサービスをどのようにUI5アプリから利用するのかについては触れられていませんでした。そこで、このシリーズではCAPで作成したODataサービスをUI5アプリで使用する方法について調べながら実装してみたいと思います。
今回はステップ1として、CAPでODataサービスを作成してSCPにデプロイします。
1. CAPで簡単なODataサービスを作成する
2. OData V2に対応させる
3. SCPにデプロイする

##前提
- Cloud Foundryに[トライアルアカウントを作成](https://developers.sap.com/tutorials/hcp-create-trial-account.html)していること
- 開発環境はVS Code

##1. CAPで簡単なODataサービスを作成する
###1.1. 事前準備
以下のチュートリアルのステップ1, 2を参考に、ローカル開発で必要なツールをインストールします。
https://developers.sap.com/tutorials/cp-apm-nodejs-create-service.html

###1.2. プロジェクトを作成
プロジェクトを作成したいディレクトリに移動し、以下のコマンドを実行します。最後のproductsは今回のプロジェクトの名前です。

```
cds init products 
```

必要なモジュールをローカルにインストールします。

```
npm install
```

以下のような構成のプロジェクトが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/affaecc7-4cc8-8650-e666-d82eb8d5be57.png)

###1.3. スキーマの定義
dbフォルダにschema.cdsファイルを追加します。ここでデータモデルを定義します。

```schema.cds
namespace demo.products;
using { managed } from '@sap/cds/common';

entity Products: managed {
    key product : String(40);
    productType: String(4);
    baseUnit: String(3);
    description: String(40);
}
```

###1.4. サービスの定義
srvフォルダにproduct-service.cdsファイルを追加します。これがODataサービスの定義です。
ここではシンプルに、Productsエンティティのすべての項目を公開しています。

```product-service.cds
using demo.products as prod from '../db/schema';

service ProductService {
    entity Products as projection on prod.Products;
}
```
`cds watch`コマンドを実行し、ブラウザに`localhost:4040`と入力すると以下のような画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/9a0f7250-b971-f6d5-1f65-60713c0316c3.png)
$metadataを選択すると、メタデータが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/a357cf81-2d3d-93a3-9ee9-0dbe5227ba5f.png)

###1.5. テストデータの追加
db/csvフォルダの下にdemo.products-Products.csvファイルを追加します。
ファイル名は`<namespace>-<Entity名>.cdv`とします。こうすると、自動的にエンティティとファイルがひもづきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/d7ce495f-66dc-c3a9-62bb-f4e19eb4c2ee.png)

ファイルの中身です。1行目がヘッダ、2行目以降がデータです。

```
product;productType;baseUnit;description
1;HAWA;PC;Sample1
2;MAT;KG;Sample2
```

ブラウザからProductsのリンクをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/e7dd3b8e-e07f-f4cf-7360-efc8736093ed.png)

データが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/87c3ef70-9d14-5076-eaf9-c5f0e1e086fe.png)

###1.6. ローカルテスト用にsqliteをインストール
ここまでで、実はもうCRUD処理までできるようになっています。ただし、データはメモリ上に保存されるためcdsを再起動すると消えてしまいます。データが消えないように、データをsqliteというローカルDBに保存できるようにします。

####sqliteをダウンロード
sqliteを以下からダウンロードします。
https://sqlite.org/download.html
Windowsの場合、以下を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/336a42fb-204c-a643-3a11-2c4f34047ecf.png)
ダウンロードしたファイルを解凍し、任意の場所に格納します。格納したフォルダを環境変数(Path)に追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/d5b57ebc-7889-099f-8ab5-bab7725b4b3f.png)

####sqliteにデプロイ

以下のコマンドで、sqlite3を追加します。

```
npm I sqlite3 -D
```

sqliteにデプロイします。デプロイといってもCFへのデプロイではなく、sqlite DB用のバイナリファイルを作成することを意味します。`db/demo-products.db`はデプロイした結果のファイルの名前で、.dbとついていればどんな名前でもOKです。

```
cds deploy --to sqlite:db/demo-products.db
```
この結果、package.jsonに以下のセクションが追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/ac9960cb-f5ee-94ad-a2c5-e02526d4aa3e.png)

作成されたファイル`db/demo-products.db`は、そのままでは人が見てもわからないのですが、以下のコマンドで中身を表示させることができます。

```
sqlite3 db/demo-products.db
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/62c620e4-a633-3d73-40c4-7d5e2a29ca7a.png)


####1.7. Postmanでテスト
Postmanを使用してデータを追加してみます。
URL: http://localhost:4004/product/Products

ヘッダのContent-Typeにappliction/jsonを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/6cfae768-71be-9ac1-8103-d5462ce2b2b2.png)
Bodyには以下を設定します。

```json
{
    "product": "3",
    "productType": "HAWA",
    "baseUnit": "PC",
    "description": "Sample3"
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/92ffd091-bb24-77e1-9c28-3e9a68309305.png)

POSTすると、以下のように結果が返ってきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/ffd9fca1-d07c-4c16-b8f5-0e7b75e536e0.png)

ブラウザでProductsの中身を見てみると、レコードが1つ増えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/a97049dc-66e3-0d4c-a2e6-e00d13523e20.png)

##2. OData V2に対応させる
CAPで作ったODataサービスはデフォルトではOData V4になります。UI5はまだ完全にはV4に対応していないので、V2に変換しておいたほうが無難です。V2に変換するには、cds-odata-v2-adapter-proxyを使用します。以下に詳しい説明があります。
https://gregorwolf.github.io/SAP-NPM-API-collection/apis/cds-odata-v2-adapter-proxy/

###2.1. cds-odata-v2-adapter-proxyをインストール
以下のコマンドでインストールします。

```
npm install @sap/cds-odata-v2-adapter-proxy -s
```

products/srvの下にserver.jsというファイルを作成し、以下のコードを入力します。もともと@sap/cdsモジュールはserver.jsというファイルを持っていますが、ローカルにserver.jsを作成した場合はそちらが使用される仕組みになっているそうです。（参考：https://blogs.sap.com/2020/06/30/how-to-add-odata-v2-adapter-proxy-to-your-cap-project/）

```products/srv/server.js
"use strict";

const cds = require("@sap/cds");
const proxy = require("@sap/cds-odata-v2-adapter-proxy");

cds.on("bootstrap", app => app.use(proxy()));

module.exports = cds.server;
```

###2.2. V2のサービスにアクセス
V2のサービスにアクセスする場合は、localhost:4004の後ろに/v2/をつけます。何もつけない場合はV4のサービスが呼ばれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/e9074ab4-27f2-db2a-6073-275154519d98.png)
ProductsエンティティをV2で見てみると、__metadataがあったりするなど、V4のときとは異なる内容になっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/46407a17-4f89-471f-e206-b4837f801e70.png)

##3. SCPにデプロイする
作成したプロジェクトをSCPにデプロイします。

###3.1. データベースをhanaにする
SCP上ではhana DBを使うため、以下のコマンドを実行します。

```
cds add hana
```
その結果、package.jsonが以下のように書き換わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/f9bf925b-0d11-b9bd-6e4f-9451e2daac56.png)
※このままだとローカルでのテストに支障があるので、デプロイした後で以下のように書き換えておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/9ee17157-ef6e-5d82-d5bf-c7393ee18108.png)

###3.2. mta.yamlを追加する
mta.yamlはサービスに必要なモジュールや依存関係を記述するファイルで、これをベースにデプロイ用のアーカイブファイル(mtar)が作られます。
以下のコマンドでmta.yamlファイルを追加します。

```
cds add mta
```
プロジェクト直下にmta.yamlファイルが作られます。トライアル環境にデプロイするので、serviceをhanatrialに書き換えます。

```yaml
# ------------------------------------------------------------
 - name: products-db
# ------------------------------------------------------------
   type: com.sap.xs.hdi-container
   parameters:
     service: hanatrial  # or 'hanatrial' on trial landscapes ※hanaから書き換え
     service-plan: hdi-shared
   properties:
     hdi-service-name: ${service-name}
```

###3.3. ビルドする
アーカイブファイルを作るためには、[Cloud MTA Build Tool](https://sap.github.io/cloud-mta-build-tool/)が必要です。インストール方法はリンク先のDownload, Makeのページに載っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/22dc6900-da08-a944-0cb9-7d00511664b5.png)



以下のコマンドでビルドします。

```
mbt build
```
mtarファイルが作られます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/bbb1bdda-c805-8fb6-454a-75e624246dc3.png)

###3.4. デプロイする
####3.4.1. Cloud Foundryにログインする
Cloud Foundry Command Line Interface (CLI)が必要なので、インストールされていない場合は以下を参考にインストールします。
https://developers.sap.com/tutorials/cp-cf-download-cli.html

以下のコマンドで、Cloud Foundryにログインします。

``` 
cf login
```
デプロイ先の組織とスペースが表示されればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/ce3f2e21-384a-3ca6-b6e1-3ee87f78c1ac.png)

####3.4.2. デプロイする
以下のコマンドで、mtarファイルをデプロイします。

```
cf deploy mta_archives/products_1.0.0.mtar
```
しばらく時間がかかりますが、以下のようなメッセージが表示されれば完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/d809afca-3432-74e0-0b47-f3771a38ffe3.png)

表示されたURLをブラウザに入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/6571f835-27ab-2fe2-1cc5-f11bf9ced949.png)

V2でも表示できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/cbc13983-1286-b0de-4b43-33eb23560b59.png)

Cloud Platformコックピットで見てみると、products-dbとproducts-srvというサービスができています。dbのサービスは停止していますが、これはDBのセットアップのタスクで、デプロイが完了すると停止します。（参考：https://blogs.sap.com/2019/05/01/cloudfoundryfun-4-fetch-football-scores-periodically/）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/8845f310-a45e-1d81-c9a6-00ece3bdb10b.png)
products-srvのサービスのURLが、ODataサービスのURLになっています。（上記で実行したURLと同じ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/868b268a-c52c-4e32-0180-55ccd5e8c3af.png)