Skip to Content
Technical Articles
Author's profile photo Maxime Simon

CAPでSAP HANA CloudのテーブルをODataサービスとして公開する

SAP HANAデータベースにあるデータを外部に公開するユースケースではODataを使用することを推奨しています。

2019年からSAP では数々のプロジェクトで得た経験に基づいて、統一されたクラウドアプリケーションの開発手法Cloud Application Programming model (CAP)を構築し、提供しています。
CAPは、サービス及びアプリケーションを構築するための言語、ライブラリ、ツールのフレームワークです。
ベストプラクティスを凝縮し「ゴールデンパス」を提供しています。
開発過程で繰り返し発生する作業に対して、すぐに使える豊富なソリューションに沿って開発者をガイドします。

CAPのプロジェクトでは、技術的な分野を掘り下げずに、ドメインに重点を置いて開発を進めることができます。

このブログでは、SAP Cloud Application Programming Modelを使用してSAPHANA Cloudにテーブルを作成し、そのテーブルをODataサービスとして公開します。
この方法では、ODatav4.0を使用してデータを公開します。 ODatav2.0を使用してデータを公開する従来のxsodataメソッドとは対照的です。

参考リンク:
Building hana-opensap-cloud-2020
SAP Experience academy (SAP Internal)
CAP Getting started guide

前提

開発環境の準備

HANA Cloudインスタンスがセットアップされ、開始する準備ができたら、サブアカウントでサブスクリプションを開き、SAP Business ApplicationStudioをクリックします。

新しいDev Spaceを作成します。

SAP Cloud Business Application テンプレートを選択し、開発スペース名を指定します。

ステータスが「開始中」から「実行中」に変わったら、開発スペース名の付いたタイルをクリックします。
バックグラウンドで、Dev Spaceには、CAPアプリケーションの開発に必要なコンポーネントが用意されています。たとえば、ノードJSやCDSなど。
Business Application Studioで開発すると、ローカルPCに何もインストールする必要がありません。

テンプレートからプロジェクトを作成

これで、Business Application Studioが起動、構成され、使用できるようになりました。 Welcomeタブで、[テンプレートからプロジェクトを作成]をクリックします。

@sap/capテンプレートを選択します。

プロジェクトにSAP HANA関連の機能を含めるには、[hana]チェックボックスをオンにします。

舞台裏で、プロジェクトが生成されます。完了すると、画面に戻り、プロジェクトのワークスペースを開くためのポップアップメッセージボックスが右下に表示されます。 [新しいワークスペースで開く]ボタンをクリックします。

エディターが新しいワークスペースで開き、CAPアプリの開発を開始できるようになります。
画面の下部にある青いバーに、スペースがCloud Foundyで設定されていないことに注意してください。このバーをクリックして、Business Application StudioをODataサービスをデプロイ先のCloud Foundryスペースに接続します。

Cloud Foundryエンドポイントを記入し、クレデンシャルを入力して、デプロイ先のスペースを選択します。接続に必要な情報はSAP Business Technology PlatformのCockpitに記載されています。

データモデルの作成

これで、Business Application StudioがCloud Foundryスペースに接続されました。
データベースに作られるデータモデルを定義してみましょう!
データモデルはdbフォルダーの仲の.cdsファイルで定義されます。

左側のファイル構造から、dbフォルダーを右クリックし、新しい.cdsファイルを作成します。
下記のスクリーンショットでは”schema.cds”というファイル名で作成しています。ファイル名は任意です。
このファイルは、HANAデータベースにデプロイされるすべてのオブジェクト(テーブル、ビュー)を定義します。

schema.cdsファイルの中に最初のCAP構造を作成します。

namespace scp.cloud;

using {
  cuid,
  sap.common
} from '@sap/cds/common';

entity SafetyIncidents : cuid {
  title                  : String(50)                    @title : 'Title';
  description            : String(1000)                  @title : 'Description';
}

この例では、namespaceをscp.cloudとして定義しています。
3行目~6行目で@ sap / cds / commonライブラリをと呼びcuidアスペクトを使用します。
8行目ではcuidを用いて、エンティティSafetyIncidentsでID列を自動的に定義します。
アスペクトについての詳細はCAPドキュメントをご参照ください。
CAPで定義されたエンティティは、データベースのテーブルとしてデプロイされます。

トップメニューに移動し、[ターミナル]-> [新しいターミナル]を選択して、ターミナルウィンドウを開きます。

プロジェクトフォルダー内で、コマンドnpm installを実行します。

次に、CAP開発では欠かせない便利なコマンドcds watchを使います。
プロジェクトに.cds、.json、または.jsファイルを追加や変更するたびに、サーバーは自動的に再起動して新しいコンテンツを提供し始めます。

ではcds watch を実行します。

そのコマンドが実行されている限り、プロジェクト構造を変更するたびに、プロジェクトの変更が自動的に保存および再デプロイされます。

数秒後、cds watchコマンドがODataサービスを生成します。
また、schema.cdsに定義されたテーブルを開発環境内のSQLiteデータベースに作成します。
[公開して開く]ボタンをクリックして、最初の空のサービスがブラウザウィンドウに表示されるかどうかを確認します。

空っぽのサービスが表示されます。

ODataサービスとしてエンティティを公開

先ほどのステップでSafetyIncidentsエンティティがdbフォルダーで定義されました。
srvフォルダーでサービス定義を追加することでODataサービスとして公開できます。

早速やってみましょう! srvフォルダ内にincidentService.cdsという新しいファイルを作成します。

incidentService.cdsの中身がこちら:

using scp.cloud from '../db/schema';

service IncidentService {
    entity SafetyIncidents as projection on cloud.SafetyIncidents;
}

1行目では、前に作成したschema.cdsファイルを参照することを定義しています。
2行目では、”cloud.SafetyIncidents”をIncidentServiceというODataサービスとして公開しています。

まとめると:
DB entity : cloud.SafetyIncidents
OData service entity : SafetyIncidents
OData Service : IncidentService

プレビュー画面をもう一度開くと、SafetyIncidentsエンティティが表示されます。

プレビュータブを閉じた場合は、[View]:[Find command]をクリックしてから、[Port:Preview]コマンドを検索することで、いつでも再度開くことができます。
これにより、現在公開されているポートのプレビューが開きます。

それでは、データをテーブルに挿入しましょう。
dbフォルダー内にdataという新しいフォルダーを作成することから始めます。

そのフォルダ内に、次のエントリを含むscp.cloud.SafetyIncidents.csvというファイルを作成します。

 

ID;title;description
067460c5-196c-4783-9563-ede797399da8;Broken machine;The printing machine is leaking
efec3e9f-ceea-4d17-80a7-50073f71c322;Software bug;The computer is on fire

ファイル名は、データを挿入するnamespace(scp.cloud)およびエンティティ名(SafetyIncidents)と一致する必要があります。

スクリーンショットに示されているように、dbフォルダーの下にデータフォルダーのスペルが正しいこと、およびファイル名のスペルが正しいことを確認してください。csvファイルで列名が正しいことをも確認してください。

cdsウォッチがまだ実行されている場合は、一度停止し、ターミナルでcds runを実行して、データがSQLiteテーブルにインポートされていることを確認します。

> filling scp.cloud.SafetyIncidents from db/data/scp.cloud.SafetyIncidents.csv メッセージでデータがインポートされていることがわかります。

これで実行中です。
サービスを開いてSafetyIncidentsエントリをクリックすると、データが表示されます。

これで、開発環境内のSQLiteデータベースにデプロイされたテーブルが作成され、テストデータも格納されました。
このテーブルは、部からアクセスできるODataサービスを介して公開されます。

データモデル、およびODataサービスをSAP Business Technology Platform上のHANA Cloudにデプロイ

ローカル環境のSQLiteでバックエンドサービスを実行しているので、次はこのプロジェクトをSAP HANA Cloudで実行します。

今まで作成したもの

  • インシデント管理アプリケーションのスキーマ(データモデル)をschema.cdsで定義しました。
  • データを公開するためのODataサービスをincidentService.cdsで定義しました。
  • SQLiteにデータをロードし、ODataサービスを通して確認しました。

HANACloud用にプロジェクトを準備

SAP HANA Cloudでは、CDSモデルはhdbcdsではなくhdbtableおよびhdbview形式でデプロイされます。
package.jsonを編集して、deploy-formatをhdbtableに設定します
package.jsonの「cds」セクションに次の行を追加します。

"hana" : { "deploy-format": "hdbtable" }

下記のスクリーンショットのように編集します。

プロジェクトをビルド

Node.JSの世界には、NODE_ENVという環境変数があります。
これまで、development「開発」環境を使用してきました。その変数をproduction「本番」に切り替える時が来ました。
CDSの動作に影響します。プロジェクトをSAP Business Technology Platformにデプロイするには、ターミナルウィンドウから次のコマンドを実行する必要があります。

  1. すでに実行されている場合は、CTRL + Cを使用して実行中のCDSプロセスを停止します。
  2. export NODE_ENV=productionコマンドを実行
  3. cds build/all --cleanコマンドを実行

このコマンドは、関連するすべてのHANAアーティファクトをビルドし、それらを新しく作成されたgenフォルダに配置します。
genフォルダを展開すると、DBとSRVの2つのフォルダが表示されます。ご想像のとおり、DBフォルダーにドリルインすると、HANA DBアーティファクトが表示され、SRVにドリルインすると、そこにも新しいファイルがあります。

HDI Containerを作成しオブジェクトをデプロイ

ビルドプロセスが完了したら、(1)Cloud FoundryでHANAデプロイメントインフラストラクチャ(HDI)コンテナーを作成し、(2)HANAアーティファクトをデプロイし、(3)SRVアーティファクトをデプロイするために、3つのコマンドを連続して実行します。
ビルドプロセスの結果、HDIコンテナを作成するために必要なコマンドがターミナルに示されていることに注意してください。

次のコマンドを実行し、cap_project-dbというHDIコンテナを作ります:cf create-service hana hdi-shared cap_project-db
コンテナの作成には数分かかる場合があります。

注:以下のスクリーンショットでは、コマンドcf create-service hanatrial hdi-shared cap_project-dbを実行しています。古い「HANA as a Service」にデプロイしています。 パラメータhanaを使用することでHANA Cloudにデプロイします。

次のコマンドを実行します:cf push -f gen/db -k 256M

これにより、生成されたhdbtableオブジェクトとhdbviewオブジェクトがHDIコンテナにデプロイされます。
HDIコンテナの作成には数分かかります。

次のコマンドを実行します: cf push -f gen/srv --random-route -k 320M

これにより、ODataサービスを公開するNode.JSアプリケーションがBTPにデプロイされます。開発者だけでなく、ユーザーもアクセスできるようになります。.

3つのコマンドがすべて実行されたら、ターミナルウィンドウの下部に指定されたルートが表示されます。

--random-routeオプションを使用しましたので、ランダムなURLを作成するようにプロセスに指示しました。

生成されたルートURLをブラウザに貼り付けて、インターネット上で利用可能であることを確認してみましょう。

Webブラウザーを開き、新しく作成したルートURLを貼り付けます。
エンティティを開くと、次のような見慣れた画面が表示されます。
SAP Business Technology PlatformにデプロイされたODataサービスは、インターネット上で利用可能になり、永続層としてSAP HANA Cloudを使用しています。

お疲れ様でした。SAP HANA Cloudにデータモデル、そしてBTPにODataサービスをデプロイしました。

より複雑なデータモデルの例

実際はより複雑なODataサービスを構築される方が多いと思います。参考コードを少しご紹介します。
次のステップとしては例えばこのサービスを使用して、Fiori UIを作成し、ユーザーが安全インシデントを報告できるアプリケーションを作成します。

以下のエンティティ定義とCAPドキュメントを調べて、CAPがどのように開発プロセスを楽にするかを学びましょう。

schema.cdsの中身を下記のコードに置き換えます:

namespace scp.cloud;

 using {
   cuid,
   managed,
   sap.common
 } from '@sap/cds/common';

 entity SafetyIncidents : cuid, managed {
   title                  : String(50)                   @title : 'Title';
   category               : Association to Category       @title : 'Category';
   priority               : Association to Priority       @title : 'Priority';
   incidentStatus         : Association to IncidentStatus @title : 'IncidentStatus';
   description            : String(1000)                  @title : 'Description';
   incidentResolutionDate : Date                          @title : 'ResolutionDate';
   assignedIndividual     : Association to Individual;
   incidentPhotos         : Association to many IncidentPhotos
                              on incidentPhotos.safetyIncident = $self;
   incidentHistory        : Association to many IncidentHistory 
                             on incidentHistory.safetyIncident = $self;
 }

 entity Individual : cuid, managed {
       firstName       : String @title : 'First Name';
       lastName        : String @title : 'Last Name';
       emailAddress    : String @title : 'Email Address';
       safetyIncidents : Association to many SafetyIncidents
                           on safetyIncidents.assignedIndividual = $self;
 }

 entity IncidentHistory : cuid, managed {
   oldStatus : Association to IncidentStatus @title : 'OldCategory';
   newStatus : Association to IncidentStatus @title : 'NewCategory';
   safetyIncident : Association to SafetyIncidents;
 }

 entity IncidentPhotos : cuid, managed {
   @Core.IsMediaType : true imageType  : String;
   @Core.MediaType   : ImageType image : LargeBinary;
   safetyIncident                      : Association to SafetyIncidents;
 }

 entity IncidentsCodeList : common.CodeList {
   key code : String(20);
 }

 entity Category : IncidentsCodeList {}
 entity Priority : IncidentsCodeList {}
 entity IncidentStatus : IncidentsCodeList {}

incidentService.cds の中身を下記のコードに置き換えます:

using scp.cloud from '../db/schema';

service IncidentService {

entity SafetyIncidents as projection on cloud.SafetyIncidents {*,assignedIndividual: redirected to Individual };
entity Individual as projection on cloud.Individual {*,safetyIncidents : redirected to SafetyIncidents};
entity SafetyIncidentsNoImages as projection on cloud.SafetyIncidents{ID ,createdAt, priority, incidentStatus,description};
entity IncidentPhotos as projection on cloud.IncidentPhotos {*,safetyIncident : redirected to SafetyIncidents};
entity IncidentHistory as projection on cloud.IncidentHistory {*,safetyIncident : redirected to SafetyIncidents};
entity IncidentsByCategory as select from cloud.SafetyIncidents {count(ID) as categories:Integer,key category} Group By category;

@readonly entity Category as projection on cloud.Category;
@readonly entity Priority as projection on cloud.Priority;
}

これで履歴や写真も保存するインシデントサービスが作られます。

より深くCAPについて知りたい方はこちらをご参照ください。

[English Version of this blog]

Maxime SIMON

Assigned tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.