Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Fukuhara
Advisor
Advisor
SAP Cloud SDK for JavaScriptを使ってアプリを作成してSAP Cloud Foundry Application Runtimeへデプロイする方法のメモです。

Node.jsとSAP Cloud SDK for JavaScriptについては、別記事「SAP Cloud SDK for JavaScriptを使ってSAP CP CFへアプリをデプロイ」を参照ください。

Node.jsプログラムはGitHubに置いています。

開発環境


以下の環境で実行しています。

  • OS: Ubuntu18.04.01 LTS

  • Node.js: 12.14.1

  • npm: 6.13.4

  • CF cli: 6.49.0+d0dfa93bb.2020-01-07

  • SAP Cloud SDK for JavaScript:1.16


 

手順


1. Node.js開発


1.1. プロジェクト作成


以下のコマンドでProjectフォルダが作成される。

途中project nameを入れ、anonymous usage analyticsはNo
# Node.jsのプロジェクトを管理したいディレクトリから
$ sap-cloud-sdk init node-sdk-chat
This folder does not contain a `package.json`.
Should a new `nest.js` project be initialized in this folder? (y|n): y
Building application scaffold... done
Enter project name (for use in manifest.yml) [node-sdk-chat]: node-sdk-chat
Do you want to provide anonymous usage analytics to help us improve the SDK? (y|n): n
✔ Creating files
✔ Modifying test config
✔ Adding dependencies to package.json
✔ Installing dependencies
✔ Modifying `.gitignore`

+--------------------------------------------------------------+
Init finished successfully.

? Next steps:
- Run the application locally (`npm run start:dev`)
- Deploy your application (`npm run deploy`)

? Consider setting up Jenkins to continuously build your app.
Use `sap-cloud-sdk add-cx-server` to create the setup script.
+--------------------------------------------------------------+

1.2. プロジェクト作成確認


プロジェクトディレクトリに移動し、nodeを起動します。
# プロジェクトディレクトリに移動しstart:devを実行
$ cd node-sdk-chat && npm run start:dev

1:23:58 AM - Starting compilation in watch mode...

11:24:02 AM - Found 0 errors. Watching for file changes.
[Nest] 64793 - 02/13/2020, 11:24:02 AM [NestFactory] Starting Nest application...
[Nest] 64793 - 02/13/2020, 11:24:02 AM [InstanceLoader] AppModule dependencies initialized +15ms
[Nest] 64793 - 02/13/2020, 11:24:02 AM [RoutesResolver] AppController {/}: +4ms
[Nest] 64793 - 02/13/2020, 11:24:02 AM [RouterExplorer] Mapped {/, GET} route +2ms
[Nest] 64793 - 02/13/2020, 11:24:02 AM [NestApplication] Nest application successfully started +2ms

CURLでリクエスト送り、正常にレスポンスを受け取れることを確認
$ curl localhost:3000
Hello World!

1.3. コントローラ作成


nest cliでchatのコントローラ生成。
$ nest g controller chat
CREATE /src/chat/chat.controller.spec.ts (479 bytes)
CREATE /src/chat/chat.controller.ts (97 bytes)
UPDATE /src/app.module.ts (322 bytes)

chat.cotroller.tsを変更します(拙いコードで失礼します)。出力フォーマットは公式ヘルプを参考にしています。
import { Controller, Get, Req, Post, Param } from '@nestjs/common';
import { Request } from 'express';

@Controller('chat')
export class ChatController {
@Get()
Reply(@Req() request: Request) {
//console.log(request)
console.log('Receive Get Request!!!!')
console.log('-----body-----')
console.log(request.body)

const test = {
"replies": [
{
"type": "quickReplies",
"content": {
"title": "Select Message Type",
"buttons": [
{
"title": "Button",
"value": "Show Buttonnest"
},
{
"title": "Picture",
"value": "Show Picture"
}
]
}
}]
}
;

return test
//return this.chatService.Reply();
};
@Post(':type')
ReplyPost(@Req() request: Request, @Param('type') type: string) {
console.log(type)
console.log('Receive Post Request!!!!')
console.log('-----body-----')
console.log(request.body)
var reply = { "replies": [] }
switch (type) {
case 'pict':
reply.replies.push(
{
"type": "picture",
"content": "https://www.sap.com/dam/application/shared/logos/sap-logo-svg.svg.adapt.svg/1493030643828.svg",
}
);
break;
case 'button':
reply.replies.push(
{
"type": "buttons",
"content": {
"title": "BUTTON_TITLE",
"buttons": [
{
"title": "BUTTON_TITLE",
"type": "BUTTON_TYPE",
"value": "BUTTON_VALUE"
}
]
}
});
break;
}
return reply
}
}

 

curlで確認します。
$ curl localhost:3000/chat
{"replies":[{"type":"quickReplies","content":{"title":"Select Message Type","buttons":[{"title":"Button","value":"Show Buttonnest"},{"title":"Picture","value":"Show Picture"}]}}]}

$ curl -X POST -H "Content-Type: application/json" -d '{"key": "value"}' localhost:3000/chat/pict
{"replies":[{"type":"picture","content":"https://www.sap.com/dam/application/shared/logos/sap-logo-svg.svg.adapt.svg/1493030643828.svg"}]}

1.4. CFへデプロイ


CFにデプロイする前にいくつか調整ごとをします。

1.4.1 package.json変更


まずはpackage.jsonを変更。"scripts"以下ににあるci-packageの中身を変更。CFへアップロードする元の"deployment"フォルダにnode_modulesがコピーされてしまうので削除します(node_modulesが重いくせに何もしていない気がする)。
"ci-package": "sap-cloud-sdk package && rm -r -f deployment/node_modules",

1.4.2. manifest.yml変更

manifest.ymlを少し変更します。random_routeを削除し、routeを固定します(<route>部分を変更)。試行錯誤していく中で、routeをcfのquotaに対して使い切ってしまったので、固定にしました。
applications:
- name: node-sdk-chat
path: deployment/
buildpacks:
- nodejs_buildpack
memory: 256M
command: npm run start:prod
routes:
- route: <route>.eu10.hana.ondemand.com

1.4.3.CFにデプロイ


あとはコマンド"npm run deploy"で、ビルドとパッケージ、cf pushを一気にやってしまいます。具体的にdeployが何をしているかは、package.jsonに定義されています。
$ npm run deploy

2. SAP Conversational AI


Botの作成部分は省略します。英語で登録しています。特別な設定はありません。

2.1. インテント登録


"start-api-test"というインテントを登録。こんな感じのexpression。


2.2. エンティティ


エンティティとして登録した"type"の一覧。


2.3. スキル"test"


スキル"test"を登録。

2.3.1. Trigger


Triggerは先程登録したインテント。


2.3.2. Requirement


Requirementにtypeを入れます。



typeがなかった場合にWebhookを使います(今回は権限なし)。


2.3.3. Action


今度はActionです。

type.valueが"picture"の場合のWebhookです。先程と違ってhttpメソッドはPOSTにして、URLの最後のパスをpictにしています。



ほぼ同じでpictureがbuttonに変わっただけです。

 



最後に条件なしでメモリ情報を出し、メモリをすべてクリアします。これでCAI側も完成です。


実装イメージ


チャットのテストをします。

"run api"とすると、メッセージタイプを選択させるquick repliesが動きます。



"Button"ボタンを押すことでButtonのサンプルを出します。Buttonの選択を待たずして、次のメモリ情報も表示されます。

 



メモリをクリアしていきなり"show picture"とすると、メッセージタイプ選択をせずに画像表示まで一気に行きます。