[SAP CloudPlatform] MTAプロジェクトのAppRouterについて調べてみた


はじめに

SAP CloudPlatformのCF環境上でFioriアプリケーション開発をしていると
UIモジュールをデプロイした際、以下のようにインスタンスのでき方が違う場合があります。

画像赤枠で囲んであるApplicationは
どちらも単一のUIモジュールを持つMTAプロジェクトをデプロイして作成したものです。

上記の違いはMTAを作る際、Use HTML5 Application Repositoryオプションにチェックを入れるかどうかで変化します。
下記のチェックが入っているとデプロイ後に-approuterがついたApplicationが実行されます。

approuter付きのApplicationとそうではないApplicationのなにが違うのか?について
調べてみました。

AppRouterとは?

結論から言うと、
CF環境に対してUI(HTML5)をデプロイする際の方式は(おそらく)以下の2つあります。

  • AppRouter(HTML5 Application Repository)を使う場合
  • UIモジュールを単一のCFアプリケーションとして実行する場合

AppRouterについては以下が参考になりました。
【参考】
 HTML5 Application RepositoryやAppRouterについては以下のドキュメントを参照
 SAP Help Portal

 概要的なところは以下のブログにある絵がわかりやすいかもしれません
 ※見出し「SCP Applications Building Blocks」のあたりから下のところ
 Fiori Application Programming Model for Cloud Foundry and ABAP Cloud

上記に関してしっかり理解できてはいませんが。。
ざっくりいうとAppRouterを使った構成は以下の3つの機能(サービス)から成り立っているようです。

HTML5 Application Repository

  • デプロイされるUIモジュールをHTML5 Application Repositoryというサービスを使って保管・提供できる
  • Repositoryに保管されているコンテンツはapp-runtime serviceによって読み取られる

HTML5 Application Deployer

  • HTML5 Application Repositoryに対してアップロードしてくれるアプリケーション
  • SAPが提供するnpmモジュールとのこと
  • コクピットのアプリケーション一覧に追加されるが、デプロイ中のみ起動していて終わると停止する(デプロイだけの役割)

Application Router – Approuter

  • 認証やアプリケーションルーティング機能を提供するnode.jsアプリケーション
  • HTML5 Application Repositoryに格納されているHTML5アプリはApprouter経由で実行する
  • xs-app.jsonファイルで定義されているルーティング定義を処理する
  • UAA(認証・承認サービス)が使われる

つまり、
 UIモジュールはDeployerを使ってHTML5 Application Repositoryに格納され、
 実行時にはAppRouter経由でアクセスする
ということらしい?

AppRouterの利点

上記の参考URLに記載されている通り、利点はいろいろあるようです。
わかりやすいところだと以下があります。

  • 単一のApprouterで複数のHTML5アプリケーションが提供できる
  • SAP Fiori Launchpad(2.0)も(UIモジュール同様)AppRouterに統合される

従来のCFアプリケーションではUIモジュールごとにサーバー側で実行されていたのが統合できる
(CFのリソースも節約できる?)ようです。

なにが違うのか?

上記で大まかな構成は説明しましたが、
具体的になにが違うのか?を見ていきます。

プロジェクトの中身

デプロイをした2つのMTAプロジェクトはWebIDE上で以下の通りとなっています。
はじめにの画像参照)
 AppRouter(HTML5 Application Repository)を使用する  → HtmlRepoプロジェクト
 AppRouter(HTML5 Application Repository)を使用しない → NoHtmlRepoプロジェクト

画像の通りフォルダ構成は同じですが、
それぞれのmta.xmlは以下のように差異が出ています。

mta.xml(HtmlRepo)

mta.xml(HtmlRepo)
ID: HtmlRepo
_schema-version: '2.1'
parameters:
  deploy_mode: html5-repo
version: 0.0.1
modules:
  - name: htmlrepo-approuter
    type: approuter.nodejs
    path: htmlrepo-approuter
    parameters:
      disk-quota: 256M
      memory: 256M
    requires:
      - name: HtmlRepo_html5_repo_runtime
      - name: uaa_HtmlRepo
  - name: HtmlRepo_ui_deployer
    type: com.sap.html5.application-content
    path: HtmlRepo_ui_deployer
    requires:
      - name: HtmlRepo_html5_repo_host
    build-parameters:
      requires:
        - name: RepoTestModule
          artifacts:
            - './*'
          target-path: resources/RepoTestModule
  - name: RepoTestModule
    type: html5
    path: RepoTestModule
    build-parameters:
      builder: custom
      commands:
        - npm install
        - npm run build
      supported-platforms: []
      build-result: dist
resources:
  - name: HtmlRepo_html5_repo_runtime
    parameters:
      service-plan: app-runtime
      service: html5-apps-repo
    type: org.cloudfoundry.managed-service
  - name: HtmlRepo_html5_repo_host
    parameters:
      service-plan: app-host
      service: html5-apps-repo
    type: org.cloudfoundry.managed-service
  - name: uaa_HtmlRepo
    parameters:
      path: ./xs-security.json
      service-plan: application
      service: xsuaa
    type: org.cloudfoundry.managed-service
  - name: dest_HtmlRepo
    parameters:
      service-plan: lite
      service: destination
    type: org.cloudfoundry.managed-service

mta.xml(NoHtmlRepo)

mta.xml(NoHtmlRepo)
ID: NoHtmlRepo
_schema-version: '2.1'
version: 0.0.1

modules:
 - name: NoRepoTestModule
   type: html5
   path: NoRepoTestModule
   parameters:
      disk-quota: 512M
      memory: 256M
   build-parameters:
      builder: grunt
   requires:
    - name: uaa_NoHtmlRepo
    - name: dest_NoHtmlRepo

resources:
 - name: uaa_NoHtmlRepo
   parameters:
      path: ./xs-security.json
      service-plan: application
      service: xsuaa
   type: org.cloudfoundry.managed-service

 - name: dest_NoHtmlRepo
   parameters:
      service-plan: lite
      service: destination
   type: org.cloudfoundry.managed-service

大きな違いはHtmlRepoプロジェクトのmodules配下にはUIモジュールのほかにapprouterui_deployerが存在するが、
NoHtmlRepoにはUIモジュールのみとなっている点です。

HtmlRepoプロジェクト
approuterのrequiresにhtml5_repo_runtimeとUaaが含まれており、
ui_deployerにはBuildParameter部分にRepositoryにアップロードするモジュールが指定されています。

上記のモジュールがhtml5_repo_runtime、html5_repo_hostを前提としているので、
resourcesに記載が増えています。

※よくわからないのはdest_HtmlRepoがresourcesに存在するけれど、requiresに含まれていない点
 デプロイ後のService Instanceも参照アプリケーションがNoneになっているので使われていない?

NoHtmlRepoのプロジェクト
UIモジュールのrequiresに直接Uaa、Destinationが指定されています。

以下、余談
上記でおそらく気にしておかなければならないのは、
 ・AppRouterが存在する場合はUaaなどの別モジュールやサービスはapprouterのrequiresに含まれる
 ・AppRouterが存在しない場合、それらはUIモジュールのrequiresに含まれる
というところだと思います。

UIモジュールから同一MTA内(もしくは別MTA)のAPIなどのリソースを読み込もうとした場合、
AppRouterがいる場合はUIモジュール配下のrequiresに記載しても参照できません。
参考QA

デプロイ後の違い

HTML5 Application Repositoryを使ったMTA

MTA:HtmlRepoの配下にはRepoTestModuleというUIモジュールが存在します。
これをデプロイして作成されるのが以下のApplicationです。

  • HtmlRepo_ui_deployer
  • htmlrepo-approuter

ui_deployerはデプロイ中以外はストップしてます。
デプロイしたSpaceのサービスインスタンスを確認すると、
HTML5 Application Repository関連のインスタンスが起動していることがわかります。

デプロイされているアプリケーションを実行しようとした場合、
素直にAppRouterのURLを実行してもUIモジュールは実行されません。
Not Foundになってしまいます。

ApplicationのOverviewに記載されているURLはAppRouterアプリケーションのURLであり、
そこからAppRouterに紐づくRepository(runtime)から自分がアクセスしたいUIを特定するためにパスを追加する必要があります。

参考URLには以下のformatでパスに表示したい画面のキー情報を追加するように記載されています。
https://<approuterhost>/<businessServicePrefix>.<applicationName-applicationVersion>/<path to file>

難しい書き方になっていますが。。。
最低限、アプリケーション名称+ファイル名がわかれば実行できます。
アプリケーション名称はUIモジュールのComponent.jsから判別可能です。

RepoTestModuleのアプリケーション名称は画像赤枠部分なので、
.を抜いたcomkyosoRepoRepoTestModuleになります。
ファイル名はとりあえずindex.htmlを実行すればよいので、
https://<approuterhost>/comkyosoRepoRepoTestModule/index.html
(もしくはhttps://<approuterhost>/comkyosoRepoRepoTestModule-1.0.0/index.html)
で実行可能です。

HTML5 Application Repositoryを使っていないMTA

MTA:NoHtmlRepoの配下にはNoRepoTestModuleというUIモジュールが存在します。
これをデプロイして作成されるのが以下のApplicationです。

こちらは素直にアプリケーションのURLでUIモジュールが実行されます。

複数のUIモジュールが存在した場合にどうなるか?

一つのMTA内にUIモジュールが複数あったとき、
AppRouterを使用する場合と使用しない場合でどう変わるのかを試してみます。

上記のように、
HtmlRepoプロジェクト、NoHtmlRepoプロジェクトにTestModule2を追加しました。
それぞれのプロジェクトをデプロイすると以下のようになります。

それぞれのUIモジュールへのURLは以下の通り。

HtmlRepoプロジェクト

  • RepoTestModule
    • https://<trial>-dev-htmlrepo-approuter.cfapps.eu10.hana.ondemand.com/comkyosoRepoRepoTestModule/index.html
  • RepoTestModule2
    • https://<trial>-dev-htmlrepo-approuter.cfapps.eu10.hana.ondemand.com/comkyosoRepoRepoTestModule2/index.html

NoHtmlRepoプロジェクト

  • NoRepoTestModule
    • https://<trial>-dev-norepotestmodule.cfapps.eu10.hana.ondemand.com/NoRepoTestModule/index.html
  • NoRepoTestModule2
    • https://<trial>-dev-norepotestmodule2.cfapps.eu10.hana.ondemand.com/NoRepoTestModule2/index.html

AppRouterを使った場合は利点として書かれていた通り単一のApprouter(ホスト)内に複数のUIが存在しますが、そうでない場合はUIモジュールとアプリケーションのホストが1:1で存在しています。

AppRouterを利用しない場合はUIモジュールの数だけApplicationが乱立してしまうことになりそうです。

おわりに

CF環境にFioriアプリケーションをデプロイする場合、
画面が一つしかないという場合であればどちらでもよいですが、
基本的にはHTML5 Application Repository、AppRouterを使うほうがいいです。

ただ、AppRouterなどはおそらく新しいサービスなのでSAP CPのMTAプロジェクトについて困ったときに調べてみるとAppRouterがつかわれていない場合でのトラブルシューティングが多いです。
同一MTA内のODataとUIを連携させたいときなどはmta.xmlのサンプル等がそのまま使えないパターンが多かったので気をつけないといけません。