Note: This exercise cannot be performed during the CodeJam because we are using a shared BTP subaccount with limited resources. However, you can complete this exercise later in your own environment. If you do not have access to a corporate BTP account, you can sign up for a BTP trial account to try it out. Knowing how to deploy the final application with real security in a production environment is valuable as it ensures that your application is secure and scalable.
In this exercise, you will deploy your CAP project with SAP HANA Cloud as a Multi-Target Application (MTA) to SAP Business Technology Platform. This is the step that takes the app from a development-time prototype running locally in BAS into a fully secured, production-grade application accessible over the internet.
👉 Perform all the steps in tutorial: Deploy CAP with SAP HANA Cloud project as MTA
A Multi-Target Application (MTA) is SAP BTP's packaging and deployment format for applications that span multiple Cloud Foundry modules and managed services. Instead of deploying each piece independently and manually wiring them together, you describe the entire application — its modules, their dependencies, and the services they consume — in a single mta.yaml descriptor file. The MTA toolchain then builds and deploys everything in the correct order with the correct bindings.
For a CAP + HANA Cloud application, the MTA graph looks like this:
┌─────────────────────────────────────────────────────────┐
│ MTA: MyHANAApp │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ MyHANAApp │ │ MyHANAApp │ │
│ │ (AppRouter) │───▶│ -srv (CAP) │ │
│ └──────────────┘ └──────┬───────┘ │
│ │ │
│ ┌──────▼───────┐ │
│ │ MyHANAApp │ │
│ │ -db-deployer │ (runs once, stops) │
│ └──────┬───────┘ │
│ │ │
│ ┌──────────────┐ ┌──────▼───────┐ │
│ │ MyHANAApp │ │ MyHANAApp-db │ │
│ │ -auth (XSUAA)│ │ (HDI container)│ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
The mta.yaml in this project defines three modules:
| Module | Type | Purpose |
|---|---|---|
MyHANAApp-srv |
nodejs |
The CAP Node.js service — serves OData endpoints, enforces authorization |
MyHANAApp-db-deployer |
hdb |
A one-shot HDI deployer — pushes the database artifacts into the HDI container, then stops |
MyHANAApp |
approuter.nodejs |
The SAP AppRouter — handles XSUAA login flows and proxies authenticated requests to the CAP service |
And two managed services:
| Service | Type | Purpose |
|---|---|---|
MyHANAApp-auth |
xsuaa |
Issues JWT tokens; defines the Admin scope referenced in @requires: 'Admin' in the CDS service definition |
MyHANAApp-db |
hana (hdi-shared plan) |
An HDI container on your HANA Cloud instance — stores all tables, views, and native artifacts |
The MyHANAApp-db-deployer module exists solely to push the compiled HDI artifacts (gen/db) into the HDI container. It connects to MyHANAApp-db, runs the deployment, and then the process exits — which Cloud Foundry reports as a "Stopped" status. This is expected and correct behaviour. The deployer does not need to keep running because it has no incoming requests to serve; all database access at runtime goes through the CAP service layer.
The before-all build hook runs two commands before any module is packaged:
build-parameters:
before-all:
- builder: custom
commands:
- npm ci
- npx cds build --productionnpx cds build --production compiles the CDS model and generates two output folders:
gen/srv— the production Node.js bundle forMyHANAApp-srvgen/db— the compiled HDI artifact set forMyHANAApp-db-deployer
The MBT tool then packages each generated folder into the MTAR archive according to the path: values in mta.yaml.
In the earlier exercises, the CAP server ran without real authentication — the @requires: 'authenticated-user' and @requires: 'Admin' annotations were present in the CDS model but were not enforced because no XSUAA service was bound. Deploying as an MTA wires the real security chain:
xs-security.json— defines theAdminscope and a matching role template. Thexsappnamein this file must be unique within your BTP subaccount.- XSUAA service (
MyHANAApp-auth) — created fromxs-security.jsonby the MTA deployment. Issues JWT tokens that contain the scopes the user has been granted. - AppRouter (
MyHANAApp) — the front door. It redirects unauthenticated users to the XSUAA login page, obtains a JWT on their behalf, and forwards it in theAuthorizationheader of every request it proxies to the CAP service. - CAP service (
MyHANAApp-srv) — validates the JWT on every request and checks that the required scope (Admin) is present before allowing access to restricted entities.
The destination srv-api is the glue between AppRouter and CAP service. It is provided by MyHANAApp-srv in mta.yaml and consumed by the AppRouter module. At runtime, the AppRouter resolves the srv-api destination to the internal URL of the CAP service, which is never directly exposed to the internet.
# MyHANAApp-srv provides the destination
provides:
- name: srv-api
properties:
srv-url: ${default-url}
# AppRouter consumes it
requires:
- name: srv-api
group: destinations
properties:
name: srv-api # matches xs-app.json route destination
url: ~{srv-url}
forwardAuthToken: true # passes the XSUAA JWT to the CAP serviceforwardAuthToken: true is critical — without it, the AppRouter would strip the JWT before forwarding, and the CAP service would reject every request as unauthenticated.
After deployment, the Admin role template defined in xs-security.json must be assigned to a user before they can access the Admin-restricted endpoints. This is done in the BTP cockpit:
- Navigate to your subaccount → Security → Role Collections
- Create a new Role Collection (e.g.
MyHANAApp-Admin) - Edit the collection and add the
Adminrole from theMyHANAAppapplication - Assign the Role Collection to your BTP user under Security → Users
Without this step, authenticated users receive a valid JWT but it will not contain the Admin scope, and the CAP service will return 403 Forbidden on restricted endpoints.
The Cloud MTA Build Tool (mbt) is the command-line tool that reads mta.yaml, runs the before-all build commands, packages each module's output folder, and produces a single deployable .mtar archive file. The .mtar is a ZIP archive containing all module artifacts plus the MTA descriptor.
mbt build -p cf
# produces: mta_archives/MyHANAApp_1.0.0.mtarThe -p cf flag targets Cloud Foundry (as opposed to Neo, the legacy SAP BTP runtime).
The cf deploy command from the MultiApps CF CLI plugin reads the .mtar file and orchestrates the full deployment:
- Uploads the archive to the CF MultiApps Controller
- Creates or updates managed services (
MyHANAApp-auth,MyHANAApp-db) - Deploys modules in dependency order (db-deployer before srv, srv before approuter)
- Binds each module to its required services
- Starts modules (db-deployer runs and stops; srv and approuter stay running)
cf deploy mta_archives/MyHANAApp_1.0.0.mtarYou can monitor progress with cf mta MyHANAApp and cf apps.
You have deployed a CAP + SAP HANA Cloud application as a fully secured MTA. The key takeaways are:
- The MTA descriptor (
mta.yaml) describes the entire application — modules, services, and their wiring — so the toolchain deploys everything consistently in one step - Three CF modules work together: the CAP service (
srv), a one-shot HDI deployer (db-deployer), and the AppRouter - The db-deployer stopping after deployment is expected — it is a run-once task, not a long-running service
- XSUAA + AppRouter + CAP form a three-layer security chain;
forwardAuthToken: trueinmta.yamlis the connector between AppRouter and CAP - After deployment you must manually assign the
Adminrole collection to users in the BTP cockpit before they can access restricted endpoints
-
What is the Cloud MTA Build Tool?
Answer
The Cloud MTA Build Tool (MBT) is a command-line tool that reads
mta.yaml, executes thebefore-allbuild commands (npm ci,npx cds build --production), packages each module's output folder, and produces a single deployable.mtararchive. The.mtaris a ZIP file containing all module artifacts and the MTA descriptor, which can then be deployed to SAP BTP withcf deploy. -
Why is the db-deployer application in a Stopped status?
Answer
The
MyHANAApp-db-deployermodule is a one-shot HDI deployer: it connects to the HDI container, pushes the compiled database artifacts, and then exits. Cloud Foundry reports a process that has exited cleanly as "Stopped". This is expected — the deployer has no incoming requests to serve at runtime. All database access goes through the running CAP service (MyHANAApp-srv), which stays in "Started" status. -
What does
forwardAuthToken: truedo inmta.yaml, and what happens if it is missing?Answer
forwardAuthToken: truetells the AppRouter to include the user's XSUAA JWT in theAuthorizationheader when it proxies a request to the CAP service backend. Without it, the AppRouter strips the token before forwarding, and the CAP service receives an unauthenticated request — every call to a@requires-protected endpoint returns403 Forbidden, even for logged-in users. -
Why do users get a
403 Forbiddenresponse immediately after a successful deployment, and how do you fix it?Answer
A successful deployment only creates the XSUAA service instance with the
Adminscope defined. It does not automatically grant that scope to any user. Users must be assigned a Role Collection that includes theAdminrole template before the scope appears in their JWT.Fix: in the BTP cockpit, create a Role Collection, add the
Adminrole fromMyHANAAppto it, and assign the Role Collection to the relevant user under Security → Users. -
What is the difference between
cf pushandcf deploy, and when would you use each?Answer
cf pushdeploys a single Cloud Foundry application from a local directory. It handles one module at a time, does not provision services, and has no concept of inter-module dependencies.cf deploy(from the MultiApps CF CLI plugin) reads an.mtararchive and orchestrates the full application deployment: it creates or updates all required managed services, deploys modules in dependency order (db-deployer before srv, srv before approuter), and wires them together according to theprovides/requiresblocks inmta.yaml— all in a single command.cf pushcf deployScope Single app module Entire multi-module application Service provisioning None — services must exist already Creates/updates services automatically Dependency ordering None Respects requires→providesgraphUse case Simple single-module apps CAP + HANA + XSUAA + AppRouter stacks For this project,
cf pushalone cannot deploy the application because it cannot provision the HANA HDI container or XSUAA service, nor can it wire thesrv-apidestination between the AppRouter and the CAP service. -
After a successful
cf deploy, how would you roll back to a previous version if something was wrong?Answer
The MultiApps CF CLI plugin maintains a deployment history per MTA. You can inspect it with:
cf mta MyHANAApp # shows the currently deployed version cf mta-ops # lists recent MTA operations
To roll back, redeploy the previous
.mtararchive:cf deploy mta_archives/MyHANAApp_1.0.0.mtar
The deployer updates modules and services back to the state described in that archive.
Important caveat — database rollbacks are not automatic. If the current deployment ran HDI schema changes (added columns, dropped tables), the db-deployer for the previous version will attempt to revert those changes. Destructive changes (dropped columns, deleted data) cannot be automatically recovered. This is why blue-green deployment is preferred for production:
cf deploy mta_archives/MyHANAApp_1.0.0.mtar --strategy blue-green
Blue-green keeps the old version running and routes traffic to it while the new version is being validated. Only when you confirm the new version is healthy does the old one get stopped — significantly reducing the risk of a bad deployment affecting users.
- MTA Build Tool — the MBT documentation, including all
mta.yamlschema options and thembt buildcommand reference - MultiApps CF CLI Plugin — the
cf deployplugin for deploying.mtararchives; includescf undeploy,cf mta, andcf mta-opscommands - CAP - Deploying to Cloud Foundry — the CAP guide for production deployments, including
mta.yamlgeneration withcds add mta - Multitarget Applications in Cloud Foundry — SAP BTP documentation on the MTA model, MTAR format, and deployment lifecycle
- SAP BTP XSUAA Configuration —
xs-security.jsonreference: scopes, role templates, and OAuth2 configuration - AppRouter Documentation — full
xs-app.jsonroute configuration, destination forwarding, and logout endpoint options - SAP BTP Cloud Foundry Runtime — overview of the CF environment on SAP BTP, including org/space structure, buildpacks, and service marketplace