My head is on the cloud – my learnings about CAP
In this blog, I would like to showcase the CAP and share some findings that seemed interesting as I was learning this topic. I would like to say thanks to the developer advocates from SAP and also Amar Ubhe for his questions on one of the posts as I followed you tube videos, sap tutorials, github repos and just read A LOT about the topic. Links to those resources below.
To read this blog in spanish click here
To read about adding more props, read the next blog here
My background in building Fiori applications and XSA APIs came in handy to understand certain pieces of the puzzle along the way (such as the mta yaml file, npm module dependencies, npm installation and npm running scripts, proxy middleware, command line.
Before getting into the topic of CAP, I did a google search about what else in the world refers to or uses CAP in its definition; interestingly enough, I found the following:
- Definition: A head covering especially with a visor and no brim – reminds me of the BTP cockpit which covers what happens within one’s BTP account and it can help visualize the apps, service instances, and all the resources under the visor.
- Definition 2: An overlying rock layer that is usually hard to penetrate – you got that right, if you add the XSUAA service to your CAP project, you will find yourself in a situation that sometimes you can’t even access it lol (let’s keep the laughs for a second)
- As an acronym: CAP refers to Civil Air Patrol and it refers to Combat Air Patrol. My personal favorite of the definitions. Sine these 2 acronyms refer to air (or cloud in my case), I can find similarities with both acronyms:
- Civil Air Patrol – I am just trying to build/learn CAP on the Cloud Programming Model
- Combat Air Patrol – I am building CAP applications and making sure I am defending the target (destination).
And just for extra credit, a shockwave refers to the phenomenon that happens when the sound barrier is broken, so just as airplanes are flying fast / I want my application to be fast in the cloud 😊
Let’s begin this learning with some background about the #BTP – Business Technology Platform. To better understand the BTP, it is important to know the Cloud Foundry (CF) hierarchy / model. There is an Org made up of 1 or more spaces. Within a space there are 1 or more apps and services. Here is the official documentation https://help.sap.com/docs/btp/sap-business-technology-platform/account-model
And an image of how I understood it.
What is the org? an Org is the top most entity created when an account is provision for a customer. In the paid account world, it will be your organization. In the free tier, BTP will assign a name for you.
What is the space? A Space is the grouping of resources, applications, service instances and other resources that can interact within an environment, for example, I could have a space for development, a space for QA and so on. 1 or more spaces can exist within an Org.
What are the applications and services?
Applications are your custom applications, APIs that are built from your project. They eventually get deployed to the BTP as microservices.
Services (or Service Instances) are created and be used within your application. For example, an XSUAA service instance is used for authenticating users to your application/API. 0 or more applications and 0 or more service instances can live within a space.
Down at the app and service instance level, users can access these resources via assigned roles or role collections (group of roles).
how does that relate to CAP and what I am building?
Before I start building CAP applications, let’s identify the information that will be needed along the way when connecting via the cf cli and also when deploying your application:
- CF endpoint
- Name of your org
- Name of your space
The first three items can be found in the overview page of your BTP cockpit under the Cloud Foundry section
- Entitlements – it is the right to provision or use a resource. You’re entitled to use services such as the Business Application Studio (#BAS) or the SAP HANA Schemas & HDI containers. From the BTP cockpit, y you can navigate to this page using the left navigation list (section after security in the previous image). Some services are not enabled by default such as the BAS and you must enable them to use them.
- HANA DB service – you will need create an instance of the HANA DB that’s hosted in the cloud so that your DB structure can be deployed to. You have an option to use the SAP HANA cloud service and/or the SAP HANA schemas and HDI container service. The instance can be created using the marketplace or the cf cli.
- XSUAA service – we need to create an instance of the XSUAA service so that it can be used to authenticate our users using the CAP application. This service instance can also be created directly from the marketplace via the BTP or using the cf cli from your terminal window after logging in to your cloud foundry account.
To better understand services, please do further reading on the official CF website
There are also command line interfaces that are used for the creation/provisioning of services.
- cf cli–> https://docs.cloudfoundry.org/cf-cli/install-go-cli.html
- hana-cli –>https://www.npmjs.com/package/hana-cli
this cli is used to verify the cloud instance of your HANA databse, query tables, views, start/stop your instance. There are other scenarios where this cli can be used for, however, for the purpose of this blog, I am going to limit this to the BTP instance. To learn more about other scenarios, refer to the npm documentation page.
If you’re unfamiliar what commands can be used with any of the cli’s, you may use the –help flag after the cli name, for example: cf –help
Here is a list of links to resources for better understanding of CAP.
- Building a full stack CAP app form VS code. (also cloning your VS Code app into BAS on BTP)
- Developing Front end apps in Cloud Foundry
- Tutorials related to CAP
- The official documentation page from CAP https://cap.cloud.sap/docs/about/
After reading these tutorials and documentation, let’s start with our own implementation of the CAP. To keep our CAP simple, the following steps assume you have installed nodejs, npm, hana-cli, cf cli and cds cli.
Using the #CAP, I would like to build an application where we develop a data model using CDS entities (tables), we’d also build an OData v4 service to expose these entities and a SAPUI5 application to display our data.
Steps for solution:
- Using the cds cli, let’s build a project in the BAS (Business App Studio) or use the CAP project template from BAS
- ** At this time you could clone a repo / sync your project to a github repo or you could wait until after step 4 to make sure you have the correct initial structure – I will also comment about this at the end of step 4 **
- Verify that the mta yaml file contains a section for the database.
- At the time of this writing (April 2023) there was a bug in the template generator and it requires us to run a quick fix : cds add hana from the terminal to include the db section in the mta yaml (deployment file)
- Verify the section is added after running that command
- Change the path of the db module to db instead of gen/db à this is to make sure we’re able to re-run the project from both VS code, BAS and also to be able to use existing calc views later.
- Add the build tasks for the hana db
- Verify the package.json file contains the correct dependencies
- cds version 6
- verify the package.json file contains the dependencies for @sap.cds, express and hdb modules
- run npm install at the project level
- run hana-cli createModule to make changes in the db folder and prepare it for CAP development
*** make sure your project is sync’d to a github repository to save your changes (commit/push)***
- Notice the project contains 3 main folders (db, app, srv)
- The db folder contains our database objects (entities, views, procedures,functions,synonyms)
- Let’s start with 3 entities that follow a common pattern of list and item; Material, Vendor, and Part.
- ** When building a cds entity file, normally there are namespaces or context namespaces. I recommend using the context namespace so that there is no conflict when creating calculation views.
- Next, create a folder called data to include a sample csv file. The name of each csv file must follow the pattern of your csv file including the namespace of the context.
- The srv folder contains our OData objects (v4) *notice in CAP the odata service is also built with a cds file referencing the CDS entities from the db folder
- Add cds service
- After creating the xsuaa service instance, authorization annotations can also be added to the service. In the example below, you can see how the Parts endpoint requires the user to be authenticated and then the Vendor endpoint requires the user to have the role, Admin. In the example below, the Materials endpoint does not have any authorization requirement (yet). While working this exercise, do not add those annotations until you have created the xsuaa service instance, key, and have done the binding (next few steps).
- Run cds build à to build the project to make sure there are no errors in the cds files you just built
- We need to create a HANA hdi instance next to be able to deploy our code to the HANA cloud service instance.
- cf create-service hana hdi-shared materialDetails-db
** if you get errors that the service is unable to be created, 1) make sure your HANA DB is enabled in the entitlements section and 2) make sure that it is running – run the command hana-cli start
*** the creation of the service takes a few seconds – check the status using the command cf services
After the service is created, create a service key (to be used from the application to connect to the service)
cf create-service-key materialDetails-db SharedDevKey
cds build/all –clean à to rebuild the project so far
cds deploy à to deploy to the HANA HDI
eventually this command returns this:
Saving bindings to .cdsrc-private.json in profile hybrid
Which means it saves the service / service key locally to be able to run the application from localhost without having to save credentials.
To run the application now, run cds watch –profile hybrid à this command allows to run the odata service from localhost but, pointing to the HANA cloud database hdi instance
At this point the system spins an express server and shows our cds resources (OData service and end points) from localhost, mine looks like this:
- selecting the service returns the OData V4 service definition
- selecting the $metadata returns the $metadata document
- selecting each endpoint shows the data being returned (if data was pre-populated into cvs files but now coming directly from the cds tables)
- selecting the Fiori preview would return what seems like an elements app that is created from the OData service and the entity definition
while selecting each of these resources, look at the terminal window in the VS code tool or in your BAS terminal to see the logs of what gets called. neat to see! From here, we’re now ready to start working on the application (app folder) next.
- The app folder contains the application code to display our backend data
The app is independent from the CDS side, however, if we’re building a Fiori elements app, we can use annotations to enhance the functionality of the OData $metadata file
While keeping the cds watch command running – open a different terminal window and using the cds cli, run the command:
cds app approuter –> this command will help adding the app router, xs-security.json, the xs-app.json file, among other files to the app folder and update the mta yaml file for deployment.
Go to the command palette at the top of the window and select, > Fiori: open application generator, follow the wizard steps to give the app(ui) a name, a theme, select the project OData service, provide a template (List Report), and select the configuration. Once all those steps are selected, a project is added inside the app folder (I left the default name, project1, and that is what I see in my project).
I created a Fiori elements app to quickly showcase the consumption of the OData service into a Fiori app, but you can also select a Freestyle app if you wish.
With what we have now in place, we have a running Fiori application and consuming the OData service, however, to make it a more realistic application, we need to include security in form of using the xsuaa instance within our application. To accomplish this, we need to do a few changes:
- From the project path, run cds compile srv/ –to xsuaa > xs-security.json
to put the correct structure of what xsuaa needs in the xs-security.json file.
Next, make sure the following sections are populated, xsappname, tenant-mode, scopes, role-template, oauth2-configuration.
- We need to set route authentication in the xs-app.json file
- We need to create an instance of the xsuaa service and also a service key
cf create-service xsuaa application materialDetails-auth -c xs-security.json
cf create-service-key materialDetails-auth default
re-start the cds watch – notice the xsuaa is also added to the cds private json file
- In our OData service, we will also show case an annotation which requires a role collection to be added. To get the authorization of the role collection, you will require to log in to the BTP cockpit, find a role (or create one if it doesn’t already exist – assign a role to the role collection with the same name as your application).
- Open the BTP cockpit to create a role collection.
- Click on the plus sign icon on the top right, provide a name – same name as your app
- Click on the caret icon, open the object detail page and add the role, Admin. Add the user id (in my case the user for the BTP account).
Add this to your package json scripts
“app”: “npm start –prefix app”
** From a different terminal run the following command: ** make sure you have the watch command running from one terminal and the following command from a different terminal (2 terminals should be running – save yourself hours of debugging and read this several times if you get errors)
cds bind –exec npm run app
the browser will ask you to run the app now from port 5000 as you specified in the xs-app.json file. Now the app running is indeed using xsuaa and authentication. Similarly with your service and the Fiori app that is launched.
The front end application (Fiori / SAPUI5):
To facilitate the building of the Fiori application, let’s include one more extension called Fiori templates. When creating this application, there will be a new folder created inside the main project folder that will be used to hold our ui5 application. Let me explain a few things about this folder and the files that exist within:
index.html –> entry page of our Fiori application
Component.js –> loads the ui5 component and references the manifest.json file
manifest.json –> configuration for the data models, routes, views, dependencies, npm scripts
xs-app.json –> route authentication and route navigation is specified here. Each route also specifies the authenticationType (ie xsuaa) and its destination (where it gets re-routed to).
xs-security.json –> references the appname, the scopes and role-templates to be used in the front end application. The role collection added from the BTP cockpit should match the name of the roles added in the role-template.
mta.yaml –> deployment configuration and dependency configuration. This file is also used for the service instances used and within modules. This file is also used for building and deploying the application
cdsrc-private.json file –> this file shows the keys used services and for deployment
webapp/folder –> this folder is mostly known for traditional ui5 developers due to the already familiar structure of it.
As you can see the UI also matches the data from the db below
- The resulting project is shared in a github repo here: https://github.com/ShockwaveConsulting/materialDetails.git
- My first struggle was to understand the navigation of the BTP Cockpit (account, marketplace, security, HANA DB – normally as a developer, devs do not get access to this tool. I have created my own account so I was able to get into the cockpit. I highly suggest anyone who uses this tool, to understand the navigation so you can quickly trace where things are.
- My next struggle while learning CAP was to familiarize myself with the various clis used, specially the cds cli. I knew a little bit about the hana-cli from other videos and from tech ed sessions but while working on this exercise, I was able to truly use it and get a better grasp on it.
- While I had created cf services before, this time seemed easier to do using the cf cli and seeing those services being provisioned / shown in the BTP cockpit. I was able to get a better handle of understanding the binding and how services interact with each other and with applications.
- The biggest struggle I had was not knowing that the watch command and the cds bind –exec npm run app needed to be running simultaneously from two different terminal windows. This is probably what took me the longest to figure out.
- Understanding the tasks done from a developer from a BTP admin was somewhat challenging due to the separation of duties in an organization, however, as a developer we need to understand all the tasks even though we may not have access to those other tools. I was glad I had my own access to the BTP cockpit but I know this does not happen in other organizations.
As everything is moving into cloud environments and more and more customers are starting to do the move into the BTP and development is starting to happen in the CAP, I wanted to see how this model was done in comparison to previous knowledge I had with XSJS and also with nodejs in XSA. I am glad I have started the journey into BTP, BAS, CF, CAP (all the acronyms!!!)
Thank you again for your time in reading this blog – let me know if you have any questions, comments or suggestions.