##はじめに
この記事は、SAP Cloud SDK for JavaScriptを使ってみるシリーズの2回目です。この記事では、SAP Cloud SDK を使ってサービスを開発する手順について説明します。
ベースとするのは以下のチュートリアルです。
- Create an App Using SAP Cloud SDK for JavaScript
- Build an Address Manager with the SAP Cloud SDK's OData Virtual Data Model
チュートリアルでは、S/4HANAのOData APIであるBusiness Partnerを使い、SAP Cloud SDKのOData Clientの使い方を確認します。OData Clientの使い方自体はチュートリアルで詳しく説明されていますので、そちらを参考にしてください。
この記事では、NestJSのCLIを使って必要なファイルを作る方法について説明します。
##事前準備
テストで使えるS/4HANAの環境がない場合、接続先としては以下のオプションがあります。
①API Business Hub
②モックのBusiness Partner Serviceをローカルに作成
今回は、テストを行う都合上、結果が一定になる②の方法を選択します。
モックのBusiness Partner Serviceの作り方については、以下に書いてあります。
https://sap.github.io/cloud-s4-sdk-book/pages/mock-odata.html
簡単に説明すると、
-
GitHubのブランチ
mock-server
をチェックアウト
git clone https://github.com/SAP/cloud-s4-sdk-book
cd cloud-s4-sdk-book
git checkout mock-server
- モックサーバーを起動
npm i
npm start
http://localhost:3000/sap/opu/odata/sap/API_BUSINESS_PARTNER/A_BusinessPartner
にアクセスすると以下のようにデータが表示されます。
##ステップ
- プロジェクトを生成
- Module、Controller、Serviceを生成
- Business Partner取得のロジックを実装
- Cloud Foundryにデプロイ
###1. プロジェクトを生成
前提:npm install -g @sap-cloud-sdk/cli
でSAP Cloud SDK CLIがインストールされていること
####1.1. プロジェクトを生成
sap-cloud-sdk init my-sdk-project
一つ目の質問(nest.jsのプロジェクトをターゲットのディレクトリで初期化するか)にはy
を選択します。
二つ目の質問(usage analyticsを提供するか)にはy
またはn
を選択します。
The target directory (my-sdk-project) does not contain a `package.json.`
Should a new `nest.js` project be initialized in the target directory? (y|n): y
Building application scaffold... done
Enter project name (for use in manifest.yml) [my-sdk-project]:
Do you want to provide anonymous usage analytics to help us improve the SDK? (y|n): y
最終的に以下の画面が表示されます。
+--------------------------------------------------------------+
✅ 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. src/main.jsを変更
デフォルトでは、生成されたアプリケーションはポート3000で動くようになっていますが、モックサーバーをポート3000で実行している都合で、ポートを8080に変更します。
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(process.env.PORT || 3000); //->8080に変更
}
bootstrap();
####1.3. 実行してみる
ターミナルにnpm run start:dev
と入力し、ブラウザでhttp://localhost:8080/
を開きます。Hello Worldの画面が表示されればOKです。
###2. Module、Controller、Serviceを生成
続いて、Module、Controller、Serviceを生成します。Module、Controller、Serviceの関係については前回の記事をご参照ください。
####2.1. Moduleを生成
以下のコマンドでModuleを生成します。
nest generate module business-partner
srcフォルダの配下にbusiness-partnerというフォルダとモジュールができました。
app.module.tsのimportsにBusinessPartnerModuleが追加されます。
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { BusinessPartnerModule } from './business-partner/business-partner.module';
@Module({
imports: [BusinessPartnerModule], //自動で追加される
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
####2.2. Controllerを生成
以下のコマンドでControllerを生成します。
nest generate controller business-partner
business-partnerフォルダ配下にcontrollerとつくファイルが2つ追加されました。このうち、spec.ts
はユニットテストで使うためのファイルです。
business-partner.module.tsにControllerが自動で追加されました。
import { Module } from '@nestjs/common';
import { BusinessPartnerController } from './business-partner.controller';
@Module({
controllers: [BusinessPartnerController]
})
export class BusinessPartnerModule {}
####2.3. Serviceを生成
以下のコマンドでServiceを生成します。
nest generate service business-partner
business-partner.module.tsにServiceが自動で追加されました。
import { Module } from '@nestjs/common';
import { BusinessPartnerController } from './business-partner.controller';
import { BusinessPartnerService } from './business-partner.service';
@Module({
controllers: [BusinessPartnerController],
providers: [BusinessPartnerService]
})
export class BusinessPartnerModule {}
###3. Business Partner取得のロジックを実装
SAP Cloud SDKのOData Clientを使い、Business Partnerを取得します。
####3.1. @sap/cloud-sdk-vdm-business-partner-serviceをインストール
以下のコマンドでBusiness PartnerのODataサービスにアクセスするためのライブラリをインストールします。
npm i @sap/cloud-sdk-vdm-business-partner-service
####3.2. Serviceの実装
Serviceに以下のロジックを実装します。
import { Injectable } from '@nestjs/common';
import { BusinessPartner } from '@sap/cloud-sdk-vdm-business-partner-service'
@Injectable()
export class BusinessPartnerService {
getAllBusinessPartners(): Promise<BusinessPartner[]> {
return BusinessPartner.requestBuilder()
.getAll()
.execute({
destinationName: 'MockServer'
})
}
}
ここでは以下のことを行っています。
-
@sap/cloud-sdk-vdm-business-partner-service
からBusinessPartner
をインポート(2行目) -
getAllBusinessPartners
メソッドでBusiness Partnerを取得- GetAll Request Builderで全てのエンティティを取得するリクエストを作成
- executeでHTTPリクエストを実行
executeについて
executeメソッドにはDestinationオブジェクト、またはDestinationNameAndJwtオブジェクトを渡します。上の例では、BTPのDestinationを使用するためDestinationNameAndJwtを使用しています。URLを直接指定する場合はDestinationオブジェクトを使い以下のようにURLを設定します。
.execute({
url: 'http://localhost:3000'
})
ローカル実行のための設定
ローカル実行時にDestinationが取得できるように、以下の設定を行います。
①.envファイルを作成
プロジェクトのルートに.envファイルを作成し、Destinationの設定をします。
destinations=[{"name": "MockServer", "url": "http://localhost:3000"}]
②@nestjs/configをインストール
npm i @nestjs/config
③ConfigModuleをapp.mocule.tsに追加
.envファイルが環境変数として使用されるように、@nestjs/configのConfigModuleをapp.mocule.tsに追加します。
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config'; //追加
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { BusinessPartnerModule } from './business-partner/business-partner.module';
@Module({
imports: [ConfigModule.forRoot(), BusinessPartnerModule], //追加
####3.3. Controllerの実装
Controllerに以下のロジックを実装します。
import { Controller, Get } from '@nestjs/common';
import { BusinessPartnerService } from './business-partner.service';
import { BusinessPartner } from '@sap/cloud-sdk-vdm-business-partner-service'
@Controller('business-partner')
export class BusinessPartnerController {
constructor(private readonly businessPartnerService: BusinessPartnerService) {}
@Get()
getAllBusinessPartners(): Promise<BusinessPartner[]> {
return this.businessPartnerService.getAllBusinessPartners();
}
}
ここでは以下のことを行っています。
-
@nestjs/common
からController
およびGet
をインポート -
@sap/cloud-sdk-vdm-business-partner-service
からBusinessPartner
をインポート - BusinessPartnerControllerクラスのコンストラクタでBusinessPartnerServiceを使用することを宣言(※)
-
getAllBusinessPartners
メソッドでBusinessPartnerServiceのgetAllBusinessPartnersメソッドを呼ぶ
※これにより、実行時にNestJSが自動的にBusinessPartnerServiceをインスタンス化して挿入してくれる。このことをDependency Injectionという。この仕組みのおかげで、Unit Testで依存先のモジュールをテスト用のモジュールに簡単に置き換えることができる。
Controller、Getについて
これらはいずれもstring型のパスを引数に取ることができます。
Controllerで指定したパスがリクエストのベースパスに一致する場合、そのControllerで処理が行われます。同様に、Getで指定したパスがベースパスの次のパスに一致する場合、そのGetの下のメソッドで処理が行われます。
以下の例では、/business-partners/getAll
というリクエストがgetAllBusinessPartnersメソッドで処理されます。
@Controller('business-partner')
export class BusinessPartnerController {
constructor(private readonly businessPartnerService: BusinessPartnerService) {}
@Get('getAll')
getAllBusinessPartners(): Promise<BusinessPartner[]> {
return this.businessPartnerService.getAllBusinessPartners();
}
}
####3.4. 実行してみる
ブラウザにhttp://localhost:8080/business-partner
と入力します。
以下の画面が表示されればOKです。
####3.4. 追加のクエリオプションの指定
OData Clientでは、select, filter, top skipなどのクエリオプションを指定することも可能です。
以下のチュートリアル、およびドキュメントを参照して、クエリオプションを試してみてください。
###4. Cloud Foundryにデプロイ
####4.1. Destinationを使用するための設定
事前準備で作成したモックのBusiness Partner ServiceをCloud Foundryにデプロイし、Destinationとして登録します。デプロイ、およびDestinationの登録手順については以下のチュートリアルのStep2~4をご参照ください。
Deploy Application to Cloud Foundry with SAP Cloud SDK for JavaScript
####4.2. Cloud Foundryにデプロイ
Cloud Foundryにデプロイするためには、package.jsonに定義されたdeployスクリプトを実行します。
npm run deploy
deployスクリプトは以下のように3つのコマンドから成っています。
"deploy": "npm run build && sap-cloud-sdk package && cf push",
各コマンドは次のことを行います。
npm run build
distフォルダにビルドした結果のファイルを格納する。
sap-cloud-sdk package
deploymentフォルダにdistフォルダ、およびpackage.json、package-lock.jsonをコピーする。
cf push
manifest.ymlの内容に従い、アプリケーションをCloud Foundryにデプロイする。
manifest.ymlでは、deployment配下のものをデプロイする設定になっている。
applications:
- name: my-sdk-project
path: deployment/
buildpacks:
- nodejs_buildpack
memory: 256M
command: npm run start:prod
random-route: true
services:
- my-destination
- my-xsuaa