Skip to Content
Technical Articles
Author's profile photo Denys van Kempen

Multitenant Business Applications with CAP | Hands-on Video Tutorials

Philip MUGGLESTONE from the SAP HANA Academy and the Partner Innovation Lab just uploaded a new series of hands-on video tutorials about developing multitenant business applications for SAP Business Technology Platform (BTP) using SAP Cloud Application Programming model (CAP).

In this blog post you will find the videos embedded with references and additional information.

For more partner-focused hands-on developer series, see

Questions? Please post as comment.

Useful? Give us a like and share on social media.

Thanks!

===

Update May 23, 2022 – added video tutorial additional services

/wp-content/uploads/2016/02/sapnwabline_885687.png

Hands-On Video Tutorials

What You Will Learn

The SAP Business Technology Platform Multitenant Business Application playlist on the SAP HANA Academy YouTube channel is growing rapidly. The first part of the playlist, videos 1 to 10 cover the basics of developing multitenant business applications and were covered in a previous blog post.

Tutorial video 11-20 revisit similar topics but this time using the SAP Cloud Application Programming model, CAP in short. Topics covered are

  • Routes
  • Dependencies
  • Credential Store
  • Extend
  • Custom Domain
  • Local Development
  • HDI
  • Additional Services (added May, 2022)

YouTube Playlist

To bookmark or directly access the playlist, go to

Free Trial Account

To follow along, you’ll need a (free) SAP Business Technology Platform (BTP) trial account.

Read the Docs

For detailed information about the SAP Cloud Programming model and multitenancy, see

For the documentation, visit

/wp-content/uploads/2016/02/sapnwabline_885687.png

CAP – First Application I

Tutorial

In this video tutorial, Philip Mugglestone scaffolds a simple first multitenant application using the SAP Cloud Application Programming Model (CAP) and reviews the code before building the project and deploying it to the Cloud Foundry runtime.

Markers

0:00 – Introduction

1:05 – CAP Reference Guide

2:39 – SAP HANA Cloud

3:08 – SAP Business Application Studio

4:05 – Install Jumpstart Generator for CAP

5:00 – Scaffold Application

6:45 – Code Review – db

7:05 – Code Review – srv

9:50 – Code Review – app

10:14 – Code Review – package.json

11:20 – Code Review – xs-security.json

12:15 – Code Review – mta.yaml

14:33 – Build & Deploy

/wp-content/uploads/2016/02/sapnwabline_885687.png

CAP – First Application II

Tutorial

In this video tutorial, Philip Mugglestone shows how to subscribe and configure tenants of the simple first multitenant application already built and deployed in part one.

Markers

0:00 – Introduction

0:30 – Review Service Instances

1:26 – Review Application Log

2:30 – Create Tenant Subaccounts & Subscribe

4:30 – Trust Configuration – Assign Authorization

5:07 – Create & Map Routes

6:50 – Test Application

11:54 – Tear-down Application (Unsubscribe & Undeploy)

/wp-content/uploads/2016/02/sapnwabline_885687.png

CAP – Routes

Tutorial

In this video tutorial, Philip Mugglestone shows how to use the Cloud Foundry RESTful API (CF API) to create consumer/tenant routes programmatically during the subscription process rather than having to create them manually using the BTP Cockpit or Cloud Foundry CLI.

Markers

0:00 – Introduction

0:42 – Scaffold Project

1:30 – Code Review – mta.yaml

2:25 – Code Review – provisioning.js

3:53 – CF API Documentation

4:30 – Build & Deploy

5:15 – Authorize CFAPI technical user

5:51 – Configure CFAPI destination

7:00 – Subscribe Tenant & Test Application

8:20 – Unsubscribe & Review Routes

8:38 – Review Logs

/wp-content/uploads/2016/02/sapnwabline_885687.png

CAP – Dependencies

Tutorial

In this video tutorial, Philip Mugglestone shows how to work with dependencies in the context of multitenant business applications. Philip uses the destination service as an example of a multtenant aware reuse service and covers how to configure the relevant application callbacks as well as use the service in the application.

Markers

0:00 – Introduction

0:45 – Scaffold Project

1:52 – Code Review – mta.yaml

3:11 – Code Review – srv/provisioning.js

3:58 – Code Review – srv/catalog-service.js

4:18 – Code Review – package.json

4:51 – Build & Deploy

5:41 – Subscribe Tenants & Test Application

6:40 – Review, Configure & Test Destinations

/wp-content/uploads/2016/02/sapnwabline_885687.png

CAP – Credential Store

Tutorial

In this video tutorial, Philip Mugglestone shows how to make use of the SAP Credential Store in the context of a multitenant application to securely manage technical user credentials and API keys.

Markers

0:00 – Introduction

0:45 – BTP Entitlements – SAP Credential Store

1:16 – Scaffold Project

3:40 – Review SAP Credential Store service instance

4:40 – Set CFAPI Credentials 5:25 – Code Review – mta.yaml

5:55 – Code Review – srv/provisioning.js

6:40 – Code Review – srv/lib/credStore.js

7:14 – Code Review – srv/catalog-service.js

8:01 – Build & Deploy

8:25 – Subscribe Tenant & Test Application

/wp-content/uploads/2016/02/sapnwabline_885687.png

CAP – Extend

Tutorial

In this video tutorial, Philip Mugglestone shows how subscribers to a multitenant application can extend the data model and services of their tenant.

Markers

0:00 – Introduction

0:55 – Code Review

2:50 – Assign Role Collections

4:10 – cds extend

5:30 – Obtain Passcode

6:30 – cds extend –templates

7:40 – Code Review – db/extend.cds, db/new.cds, srv/extensions.cds

11:15 – cds activate

11:57 – Test Extensions

12:44 – Review Application Logs

13:45 – Apply Extensions to a Different Tenant

/wp-content/uploads/2016/02/sapnwabline_885687.png

CAP – Custom Domain

Tutorial

In this video tutorial, Philip Mugglestone shows how to configure a multitenant business application with a custom domain. Philip scaffolds an example application and explains how to configure “wildcard” host mapping.

Markers

0:00 – Introduction

0:50 – Scaffold Project

1:53 – Code Review – mta.yaml

3:44 – Code Review – xs-security.json

4:35 – Code Review – srv/provisioning.js

5:35 – Review Jumpstart Generator Log – cf map-route

/wp-content/uploads/2016/02/sapnwabline_885687.png

CAP – Local Development

Tutorial

In this video tutorial, Philip Mugglestone shows how to enable “local” development of multitenant business applications – in particular from SAP Business Application Studio.

Markers

0:00 – Introduction

0:40 – Scaffold Project

1:10 – Configure redirect-uris in xs-security.json

2:10 – Build & Deploy

2:25 – Subscribe Tenants

3:55 – Set Authentication Strategy to JWT in package.json

4:40 – Install default-env plugin for CF CLI

5:20 – srv – cf de app-srv

6:05 – srv – cds watch

6:42 – app – cf de app

7:10 – Configure destinations, TENANT_HOST & EXTERNAL_REVERSE_PROXY in app/default-env.json

9:37 – npm run custom

10:20 – Test Locally Running Application

/wp-content/uploads/2016/02/sapnwabline_885687.png

CAP – HDI (Under the Hood)

Tutorial

In this video tutorial, Philip Mugglestone shows how to find out more about SAP HANA Cloud HDI containers created for each subscriber tenant by the service instance of SAP Service Manager.

Markers

0:00 – Introduction

0:45 – Review Service Manager Service Instance – HDI Containers

1:50 – Install SMSI plugin for CF CLI

2:30 – cf smsi -m -a

3:05 – SQLTools

3:20 – Connect & Review Tenant HDI Containers

4:05 – Change Data For a Tenant Subscriber

4:23 – Review Tenant HDI Containers

5:10 – Connect & Review _META_ HDI Container

/wp-content/uploads/2016/02/sapnwabline_885687.png

BTP Multitenant CAP – Additional Services

Tutorial

In this video tutorial, Philip Mugglestone shows how to configure additional backend services as part of a CAP-based multitenant business application for performance, functional or scalability reasons. Both CAP-based and regular Node.js examples of additional services are configured.

Markers

0:00 – Introduction

1:30 – Start CAP generator

2:35 – Source code review

12:10 – Build and deploy 

12:40 – Configure Destination service

13:35 – Register technical user

13:55 – Subscribe app

15:20 – Launch app

16:05 – Recap

/wp-content/uploads/2016/02/sapnwabline_885687.png

Share and Connect

Questions? Please post as comment.

Useful? Give us a like and share on social media.

Thanks!

If you would like to receive updates, connect with me on

For the author page of SAP PRESS, visit

Over the years, for the SAP HANA Academy, SAP’s Partner Innovation Lab, and à titre personnel, I have written a little over 300 posts here for the SAP Community. Some articles only reached a few readers. Others attracted quite a few more. For your reading pleasure and convenience, here is a curated list of posts which somehow managed to pass the 10k-view milestone and, as sign of current interest, still tickle the counters each month.

/wp-content/uploads/2016/02/sapnwabline_885687.png

Assigned Tags

      18 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Massimiliano D'Alfonso
      Massimiliano D'Alfonso

      Hi,

      great article!

      Is it possible to extend UI? For example add some fields to existing app?

      Author's profile photo Srinath Velagala
      Srinath Velagala

      Hi Denys van Kempen

      Thanks for the article. This is very helpful and gave us a good starting point. I have started working on extending this app to accomidate Fiori UI. I was successful upto building the MTA but got stuck at the deployment phase and getting the below error.

      "org.cloudfoundry.multiapps.common.SLException: Error resolving merged descriptor properties and parameters: null"
      Below is the code snippet of my MTA.yaml file. Looking forward to your response. Thanks!!
      ID: mysaasapp
      _schema-version: "3.1"
      version: 0.0.2
      modules:
      - name: mysaasapp-srv
        type: nodejs
        path: srv
        requires:
        - name: mysaasapp-uaa
        - name: mysaasapp-registry
        - name: mysaasapp-dest
        provides:
        - name: srv_api
          properties:
            url: ${default-url}
        parameters:
          disk-quota: 512M
          memory: 256M
      - name: mysaasapp
        type: html5
        path: app
        build-parameters:
          build-result: dist
          builder: custom
          commands:
          - npm install
          - npm run build:cf
          supported-platforms: []
        properties:
          TENANT_HOST_PATTERN: ^(.*)-${space}-${app-name}.${default-domain}
        requires:
        - name: mysaasapp-uaa
        - name: srv_api
          group: destinations
          properties:
            forwardAuthToken: true
            name: srv
            url: ~{url}
        provides:
        - name: app_api
          properties:
            application: ${app-name}
            url: ${default-url}
        parameters:
          disk-quota: 512M
          memory: 256M
      - name: mysaasapp-app-content
        type: com.sap.application.content
        path: .
        requires:
        - name: mysaasapp-repo-host
          parameters:
            content-target: true
        build-parameters:
          build-result: resources
          requires:
          - artifacts:
            - mysaasapp.zip
            name: mysaasapp
            target-path: resources/
      resources:
      - name: mysaasapp-uaa
        type: org.cloudfoundry.managed-service
        parameters:
          config:
            xsappname: ${xsuaa-app}
          path: ./xs-security.json
          service: xsuaa
          service-plan: application
          xsuaa-app: ${space}-~{app_api/application}
        properties:
          XSAPPNAME: ${xsuaa-app}
        requires:
        - name: app_api
      - name: mysaasapp-registry
        type: org.cloudfoundry.managed-service
        parameters:
          config:
            appName: mysaasapp
            appUrls:
              getDependencies: https://${org}-${space}-mysaasapp-srv.${default-domain}/callback/v1.0/dependencies
              onSubscription: https://${org}-${space}-mysaasapp-srv.${default-domain}/callback/v1.0/tenants/{tenantId}
            category: Utility
            description: Fiori App Activator
            displayName: Fiori App Activator
            xsappname: ~{mysaasapp-uaa/XSAPPNAME}
          service: saas-registry
          service-name: mysaasapp-registry
          service-plan: application
        requires:
        - name: mysaasapp-uaa
      - name: mysaasapp-dest
        type: org.cloudfoundry.managed-service
        parameters:
          config:
            HTML5Runtime_enabled: false
            init_data:
              instance:
                destinations:
                - Authentication: NoAuthentication
                  Name: ui5
                  ProxyType: Internet
                  Type: HTTP
                  URL: https://ui5.sap.com
                existing_destinations_policy: update
            version: 1.0.0
          service: destination
          service-plan: lite
      - name: mysaasapp-repo-host
        type: org.cloudfoundry.managed-service
        parameters:
          service: html5-apps-repo
          service-name: mysaasapp-html5-srv
          service-plan: app-host
      parameters:
        deploy_mode: html5-repo
      Author's profile photo Lakshmi Munnungi
      Lakshmi Munnungi

      Hi @svelagala

      I am also getting the same error

      Denys van Kempen  Pl provide your any inputs / comments for the above error.

      Thanks

      Lakshmi

      Author's profile photo Denys van Kempen
      Denys van Kempen
      Blog Post Author

      Hi Srinath Velagala,

      The issue is new to me. No answer 1-2-3 and the MTA does not provide sufficient information to reproduce. 

      Would you mind posting the question to the forum? > answers.sap.com

      This space is monitored by the experts who might have an answer.

      Thanks!

       

      Author's profile photo Ian Jiang
      Ian Jiang

      Hi Denys van Kempen ,

       

      With latest SAP HANA studio and generator-saphanaacademy-saas, the mta.yaml like this:

      ID: myappsaas
      _schema-version: "3.1"
      version: 0.0.1
      
      parameters:
        enable-parallel-deployments: true
      
      modules:
      
        - name: myappsaas-srv
          type: nodejs
          path: srv
          build-parameters:
            ignore:
              - default-*.json
              - .env
              - "*node_modules*"
              - package-lock.json
          parameters:
            memory: 256M
            disk-quota: 512M
          provides:
            - name: srv-api
              properties:
                srv-url: ${default-url}
          requires:
            - name: myappsaas-uaa
            - name: myappsaas-registry
            - name: app-api
              properties:
                APP_PROTOCOL: ~{protocol}
                APP_URI: ~{uri}
      
        - name: myappsaas-app
          type: approuter.nodejs
          path: app
          build-parameters:
            ignore:
              - default-*.json
              - .env
              - "*node_modules*"
              - package-lock.json
          parameters:
            memory: 256M
            disk-quota: 512M
            keep-existing-routes: true
          properties:
            TENANT_HOST_PATTERN: '^(.*)-${default-uri}'
          provides:
            - name: app-api
              properties:
                protocol: ${protocol}
                uri: ${default-uri}
          requires:
            - name: myappsaas-uaa
            - name: srv-api
              group: destinations
              properties:
                name: srv
                url: ~{srv-url}
                forwardAuthToken: true
      
      resources:
        - name: myappsaas-uaa
          type: org.cloudfoundry.managed-service
          parameters:
            service: xsuaa
            service-plan: application
            path: ./xs-security.json
        - name: myappsaas-registry
          type: org.cloudfoundry.managed-service
          requires:
            - name: srv-api
          parameters:
            service: saas-registry
            service-plan: application
            service-name: myappsaas-registry
            config:
              xsappname: myappsaas
              appName: myappsaas
              displayName: 'App'
              description: 'Business Application'
              category: 'SaaS Multitenant Apps'
              appUrls:
                onSubscription: ~{srv-api/srv-url}/callback/v1.0/tenants/{tenantId}
                onSubscriptionAsync: false
                onUnSubscriptionAsync: false
                callbackTimeoutMillis: 300000
      

      When deploy the mta to cf, I got the error:

      Processing service "myappsaas-registry"...
      Service "myappsaas-registry" is in state "create failed" and may not be operational. Actions like update of credentials and binding may fail! Consider recreating it by specifying the --delete-services option.
      Error determining actions to execute on service "myappsaas-registry": Controller operation failed: 404 Error determining actions to execute on service "myappsaas-registry": CF-ResourceNotFound(10010): Service instance not found 
      

      How could I correct the "myappsaas-registry" service configuration?

      Thanks,
      Ian

      Author's profile photo Philip MUGGLESTONE
      Philip MUGGLESTONE

      Hi Ian,

      It sounds like there may already be an app named myappsaas deployed in the SAP BTP region? SaaS app names must be unique across the region (infrastructure provider datacenter eg: eu10 or us10). It may have been deployed by someone else via a global account that's unrelated to yours.

      Or perhaps a previous attempt to deploy the app failed? Check the list of services for the BTP subaccount and delete manually if already there and then try to deploy again?

      I tested deploy of a similar project created with the saas generator (but named myappsaas0) just now and all was deployed OK.

      Hope that helps,

      Philip

      Author's profile photo Ian Jiang
      Ian Jiang

      Great. Thanks for your help.

      Author's profile photo Ian Jiang
      Ian Jiang

      Hi Philip MUGGLESTONE ,

       

      How can I config "Trust Configuration" in current BTP Cockpit? Since the current default identity provider version on BTP is disabled. Where to config user and roles in consumer subaccount?

      Without config user and roles, I got the error:

      data: 'User not authorized, source of route: /^\\/srv\\/(.*)$/, IP: ******, required scopes: myappsaasIan!t140134.User, user scopes: openid',

      Thanks,

      Ian

       

      Author's profile photo Philip MUGGLESTONE
      Philip MUGGLESTONE

      Hi Ian,

      Take a look at this video tutorial as it shows the process of assigning role collections to users when using a custom identity provider or IaS.

      You may need to explicitly create a "shadow" user in your custom identity provider using the BTP cockpit before you can assign role collections to it.

      Thanks,

      Philip

      Author's profile photo Ian Jiang
      Ian Jiang

      OK,I will have a try. Thanks a lot.

      Author's profile photo Ian Jiang
      Ian Jiang

      Hi Philip MUGGLESTONE ,

      Regarding multi-tenant persistence in BTP,  what is the difference between "SAP HANA Tenant database" and "schema separation"?

      Thanks,
      Ian

      Author's profile photo Philip MUGGLESTONE
      Philip MUGGLESTONE

      Hi Ian,

      The "SAP HANA Tenant database" you mention refers to SAP HANA on-premise. It's not relevant to multitenant scenarios in SAP BTP where we use SAP HANA Cloud. You can find documentation of the key differences between the SAP HANA editions here.

      For more context regarding schema separation see this video tutorial in the Multitenant series.

      Thanks,

      Philip

      Author's profile photo Ian Jiang
      Ian Jiang

      Great, thanks a lot.

      Author's profile photo Ian Jiang
      Ian Jiang

      Hi Philip MUGGLESTONE

      Regarding multi-tenant persistence, I got a general concept about "service manager" and "hdi". "service manager" will dynamically create "hdi" which will setup a separate schema for tenant. As a managed service on BTP, the application could subscribe "service manager" and then use it to create "hdi" and deploy the artifact to the specified HANA schema.

      It seems that the essential magic is "HDI". I was wondering if there is more useful documentation and tutorial about "HDI" and "Service manager HDI creation" for beginner? Since I am going to implement multi-tenant persistence (schema separation) with SpringBoot.

      Thanks,
      Ian

      Author's profile photo Philip MUGGLESTONE
      Philip MUGGLESTONE

      Hi Ian,

      Glad the explanations were helpful.

      You can learn more about the dynamic deployment of HDI container artefacts here.

      Just one thought, if you were to use CAP for your project then pretty much all of the multi tenancy process is done for you out-of-the-box incl. schema separation so you don't need to get into the underlying details of service manager and HDI deployers etc. The relevant guide is here.

      Thanks,

      Philip

      Author's profile photo Ian Jiang
      Ian Jiang

      Thanks very much.

      Author's profile photo Krishna Nambiar
      Krishna Nambiar

      Hi Philip MUGGLESTONE ,

      I am looking for a way to have multiple Service Plans for my SaaS application.

      Can you 9kindly provide some guidance for the same?

       

      Thanks in Advance!

      Regards,

      Author's profile photo Philip MUGGLESTONE
      Philip MUGGLESTONE

      Hi Krishna,

      Might I suggest you ask the wider SAP Community via questions? You'll reach a much broader audience of experts this way.

      Thanks and regards,

      Philip