Deploy to Cloud Foundry
A comprehensive guide on deploying applications built with SAP Cloud Application Programming Model (CAP) to SAP BTP Cloud Foundry environment.
Intro & Overview
After completing the functional implementation of your CAP application by following the Getting Started or Cookbook guides, you would finally deploy it to the cloud for production. The essential steps are illustrated in the following graphic:
First, you apply these steps manually in an ad-hoc deployment, as described in this guide. Then, after successful deployment, you automate them using CI/CD pipelines.
This guide is available for Node.js and Java.
Use the toggle in the title bar or press v to switch.
Prerequisites
The following sections are based on a new project that you can create like this:
cds init bookshop --add sample
cd bookshop
Alternatively, download or clone the sample repository
Exercise the following steps in the bookshop
subfolder of the cloud-cap-samples
repo:
git clone https://github.com/sap-samples/cloud-cap-samples samples
cd samples/bookshop
cds init bookshop --java --add sample
cd bookshop
If you want to use a ready-to-be-deployed sample, see our java/samples.
In addition, you need to prepare the following:
1. SAP BTP with SAP HANA Cloud Database up and Running
- Access to SAP BTP, for example a trial
- An SAP HANA Cloud database running in your subaccount
- Entitlement for
hdi-shared
service plan for your subaccount - A Cloud Foundry space
Starting the SAP HANA database takes several minutes
Therefore, we recommend doing these steps early on. In trial accounts, you need to start the database every day.
2. Latest Versions of @sap/cds-dk
Ensure you have the latest version of @sap/cds-dk
installed globally:
npm -g outdated #> check whether @sap/cds-dk is listed
npm i -g @sap/cds-dk #> if necessary
Likewise, ensure the latest version of @sap/cds
is installed in your project:
npm outdated #> check whether @sap/cds is listed
npm i @sap/cds #> if necessary
3. Cloud MTA Build Tool
Run
mbt
in a terminal to check whether you've installed it.If not, install it according to the MTA Build Tool's documentation.
For macOS/Linux machines best is to install using
npm
:shnpm i -g mbt
For Windows, please also install
GNU Make
.
4. Cloud Foundry CLI w/ MTA Plugins
Run
cf -v
in a terminal to check whether you've installed version 8 or higher.If not, install or update it according to the Cloud Foundry CLI documentation.
In addition, ensure to have the MTA plugin for the Cloud Foundry CLI installed.
shcf add-plugin-repo CF-Community https://plugins.cloudfoundry.org cf install-plugin multiapps cf install-plugin html5-plugin
Prepare for Production
If you followed CAP's grow-as-you-go approach so far, you've developed your application with an in-memory database and basic/mock authentication. To prepare for production you need to ensure respective production-grade choices are configured:
We'll use the cds add <facets>
CLI command for that, which ensures the required services are configured correctly and corresponding package dependencies are added to your package.json.
1. Using SAP HANA Database
cds add hana --for production
Learn more about using SAP HANA for production.
2. Using XSUAA-Based Authentication
Configure your app for XSUAA-based authentication:
cds add xsuaa --for production
This will also generate an xs-security.json
file
The roles/scopes are derived from authorization-related annotations in your CDS models. Ensure to rerun cds compile --to xsuaa
, as documented in the Authorization guide whenever there are changes to these annotations.
For trial and extension landscapes, OAuth configuration is required
Add the following snippet to your xs-security.json and adapt it to the landscape you're deploying to:
"oauth2-configuration": {
"redirect-uris": ["https://*.cfapps.us10-001.hana.ondemand.com/**"]
}
Learn more about SAP Authorization and Trust Management/XSUAA.
3. Using MTA-Based Deployment
We'll be using the Cloud MTA Build Tool to execute the deployment. The modules and services are configured in an mta.yaml
deployment descriptor file, which we generate with:
cds add mta
Learn more about MTA-based deployment.
4. Using App Router as Gateway
The App Router acts as a single point-of-entry gateway to route requests to. In particular, it ensures user login and authentication in combination with XSUAA.
Two deployment options are available:
Managed App Router: for SAP Build Work Zone, the Managed App Router provided by SAP Fiori Launchpad is available. See the end-to-end tutorial for the necessary configuration in
mta.yaml
and on each SAP Fiori application.Custom App Router: for scenarios without SAP Fiori Launchpad, the App Router needs to be deployed along with your application. Use the following command to enhance the application configuration:
shcds add approuter
Learn more about the SAP BTP Application Router.
5. User Interfaces
SAP Cloud Portal
If you intend to deploy user interface applications, you also need to set up the HTML5 Application Repository in combination with the SAP Cloud Portal service:
cds add portal
SAP Build Work Zone, Standard Edition beta
For single-tenant applications, you can use SAP Build Work Zone, Standard Edition:
cds add workzone
6. Optional: Add Multitenancy
To enable multitenancy for production, run the following command:
cds add multitenancy --for production
If necessary, modifies deployment descriptors such as mta.yaml for Cloud Foundry.
Learn more about MTX services.
You're set!
The previous steps are required only once in a project's lifetime. With that done, we can repeatedly deploy the application.
7. Freeze Dependencies
Deployed applications should freeze all their dependencies, including transient ones. Create a package-lock.json file for that:
npm update --package-lock-only
If you use multitenancy, also freeze dependencies for the MTX sidecar:
npm update --package-lock-only --prefix mtx/sidecar
In addition, you need install and freeze dependencies for your UI applications:
npm i --prefix app/browse
npm i --prefix app/admin-books
Learn more about dependency management for Node.js
Regularly update your package-lock.json
to consume latest versions and bug fixes
Do so by running this command again, for example each time you deploy a new version of your application.
Build & Assemble
Build Deployables with cds build
Run cds build
to generate additional deployment artifacts and prepare everything for production in a local ./gen
folder as a staging area. While cds build
is included in the next step mbt build
, you can also run it selectively as a test, and to inspect what is generated:
cds build --production
Learn more about running and customizing cds build
.
Assemble with mbt build
Prepare monorepo setups
The CAP samples repository on GitHub has a more advanced (monorepo) structure, so tell the mbt
tool to find the package-lock.json
on top-level:
ln -sf ../package-lock.json
Now, we use the mbt
build tool to assemble everything into a single mta.tar
archive:
mbt build -t gen --mtar mta.tar
Got errors? See the troubleshooting guide.
Learn how to reduce the MTA archive size during development.
Deploy to Cloud
Finally, we can deploy the generated archive to Cloud Foundry:
cf deploy gen/mta.tar
You need to be logged in to Cloud Foundry.
This process can take some minutes and finally creates a log output like this:
[…]
Application "bookshop" started and available at
"[org]-[space]-bookshop.landscape-domain.com"
[…]
Copy and open this URL in your web browser. It's the URL of your App Router application.
For multitenant applications, you have to subscribe a tenant first
In this case, the application is accessible via a tenant-specific URL after onboarding.
Inspect Apps in BTP Cockpit
Visit the "Applications" section in your SAP BTP cockpit to see the deployed apps:
Assign the admin role
We didn't do the admin role assignment for the AdminService
. You need to create a role collection and assign the role and your user to get access.
Got errors? See the troubleshooting guide.
Upgrade Tenants
The CAP Java SDK offers main
methods for Subscribe/Unsubscribe in the classes com.sap.cds.framework.spring.utils.Subscribe/Unsubscribe
that can be called from the command line. This way, you can run the tenant subscribe/unsubscribe for the specified tenant. This would trigger also your custom handlers, which is useful for the local testing scenarios.
In order to register all handlers of the application properly during the execution of a tenant operation main
method, the component scan package must be configured. To set the component scan, the property cds.multitenancy.component-scan
must be set to the package name of your application.
The handler registration provides additional information that is used for the tenant subscribe, for example, messaging subscriptions that are created.
WARNING
You can stop the CAP Java back end when you call this method, but the MTX Sidecar application must be running!
This synchronization can also be automated, for example using Cloud Foundry Tasks on SAP BTP and Module Hooks in your MTA.
The main
method optionally takes tenant ID (string) as the first input argument and tenant options (JSON string) as the second input argument. Alternatively, you can use the environment variables MTCOMMAND_TENANTS
and MTCOMMAND_OPTIONS
instead of arguments. The command-line arguments have higher priority, so you can use them to override the environment variables.
The method returns the following exit codes.
Exit Code | Result |
---|---|
0 | Tenant subscribed/unsubscribed successfully. |
3 | Failed to subscribe/unsubscribe the tenant. Rerun the procedure to make sure the tenant is subscribed/unsubscribed. |
To run this method locally, use the following command where <jar-file>
is the one of your applications:
java -cp <jar-file> -Dloader.main=com.sap.cds.framework.spring.utils.Subscribe/Unsubscribe org.springframework.boot.loader.launch.PropertiesLauncher <tenant> [<tenant options>]
java -cp <jar-file> -Dloader.main=com.sap.cds.framework.spring.utils.Subscribe/Unsubscribe org.springframework.boot.loader.PropertiesLauncher <tenant> [<tenant options>]
In the SAP BTP, Cloud Foundry environment, it can be tricky to construct such a command. The reason is that the JAR file is extracted by the Java buildpack and the place of the Java executable isn't easy to determine. Also the place differs for different Java versions. Therefore, we recommend adapting the start command that is generated by the buildpack and run the adapted command:
sed -i 's/org.springframework.boot.loader.launch.JarLauncher/org.springframework.boot.loader.launch.PropertiesLauncher/g' /home/vcap/staging_info.yml && sed -i 's/-Dsun.net.inetaddr.negative.ttl=0/-Dsun.net.inetaddr.negative.ttl=0 -Dloader.main=com.sap.cds.framework.spring.utils.Subscribe/Unsubscribe/g' /home/vcap/staging_info.yml && jq -r .start_command /home/vcap/staging_info.yml | sed 's/^/ MTCOMMAND_TENANTS=my-tenant [MTCOMMAND_TENANTS=<tenant options>]/' | bash
sed -i 's/org.springframework.boot.loader.JarLauncher/org.springframework.boot.loader.PropertiesLauncher/g' /home/vcap/staging_info.yml && sed -i 's/-Dsun.net.inetaddr.negative.ttl=0/-Dsun.net.inetaddr.negative.ttl=0 -Dloader.main=com.sap.cds.framework.spring.utils.Subscribe/Unsubscribe/g' /home/vcap/staging_info.yml && jq -r .start_command /home/vcap/staging_info.yml | sed 's/^/ MTCOMMAND_TENANTS=my-tenant [MTCOMMAND_TENANTS=<tenant options>]/' | bash
sed -i 's/org.springframework.boot.loader.JarLauncher/-Dloader.main=com.sap.cds.framework.spring.utils.Subscribe/Unsubscribe org.springframework.boot.loader.PropertiesLauncher/g' /home/vcap/staging_info.yml && jq -r .start_command /home/vcap/staging_info.yml | sed 's/^/ MTCOMMAND_TENANTS=my-tenant [MTCOMMAND_TENANTS=<tenant options>]/' | bash
Appendices
Deploy using cf push
As an alternative to MTA-based deployment, you can choose Cloud Foundry-native deployment using cf push
, or cf create-service-push
respectively.
Prerequisites
Install the Create-Service-Push plugin:
cf install-plugin Create-Service-Push
This plugin acts the same way as cf push
, but extends it such that services are created first. With the plain cf push
command, this is not possible.
Add a manifest.yml
cds add cf-manifest
This creates two files, a manifest.yml and services-manifest.yml in the project root folder.
- manifest.yml holds the applications. In the default layout, one application is the actual server holding the service implementations, and the other one is a 'DB deployer' application, whose sole purpose is to start the SAP HANA deployment.
- services-manifest.yml defines which Cloud Foundry services shall be created. The services are derived from the service bindings in package.json using the
cds.requires
configuration.
Version-control manifest files
Unlike the files in the gen folders, these manifest files are genuine sources and should be added to the version control system. This way, you can adjust them to your needs as you evolve your application.
Build the Project
This prepares everything for deployment, and -- by default -- writes the build output, that is the deployment artifacts, to folder ./gen in your project root.
cds build --production
Learn how cds build
can be configured.
The --production
parameter ensures that the cloud deployment-related artifacts are created by cds build
. See section SAP HANA database deployment for more details.
Push the Application
This command creates service instances, pushes the applications and binds the services to the application with a single call:
cf create-service-push
During deployment, the plugin reads the services-manifest.yml file and creates the services listed there. It then reads manifest.yml, pushes the applications defined there, and binds these applications to service instances created before. If the service instances already exist, only the cf push
operation will be executed.
You can also apply some shortcuts:
- Use
cf push
directly to deploy either all applications, orcf push <app-name>
to deploy a single application. - Use
cf create-service-push --no-push
to only create or update service-related data without pushing the applications.
In the deployment log, find the application URL in the routes
line at the end:
name: bookshop-srv
requested state: started
routes: bookshop-srv.cfapps.sap.hana.ondemand.com
Open this URL in the browser and try out the provided links, for example, …/browse/Books
. Application data is fetched from SAP HANA.
Ensure successful SAP HANA deployment
Check the deployment logs of the database deployer application using
cf logs <app-name>-db-deployer --recent
to ensure that SAP HANA deployment was successful. The application itself is by default in state started
after HDI deployment has finished, even if the HDI deployer returned an error. To save resources, you can explicitly stop the deployer application afterwards.
No Fiori preview in the cloud
The SAP Fiori Preview, that you are used to see from local development, is only available for the development profile and not available in the cloud. For productive applications, you should add a proper SAP Fiori application.
WARNING
Multitenant applications are not supported yet as multitenancy-related settings are not added to the generated descriptors. The data has to be entered manually.