Skip to content

SAP Cloud Application Programming Model (CAP)

What is CAP?

SAP Cloud Application Programming ModelSAP Cloud Application Programming Model (in short CAP) The SAP Cloud Application Programming Model is a framework of languages, libraries, and tools for building enterprise-grade services and applications. It guides developers along a ‘golden path’ of proven best practices and a great wealth of out-of-the-box solutions to recurring tasks.

CAP-based projects benefit from a primary focus on domain. Instead of delving into overly technical disciplines, we focus on accelerated development and safeguarding investments in a world of rapidly changing cloud technologies.

Overview & Design Principles

The CAP framework features a mix of proven and broadly adopted open-source and SAP technologies, as highlighted in the figure below.

CAP Overview & Design Principles

On top of open source technologies, CAP mainly adds:

  • Core Data Services (CDS) as our universal modeling language for both domain models and service definitions.
  • Service SDKs and runtimes for Node.js and Java, offering libraries to implement and consume services as well as generic provider implementations serving many requests automatically.

Agnostic Design → Safeguarding Investments

Keeping pace with a rapidly changing world of cloud technologies and platforms is a major challenge when having to hardwire too many things to today’s technologies, which might soon become obsolete. CAP avoids such lock-ins through higher-level concepts and APIs, which abstract low-level platform features and protocols to a large extent. In particular, this applies to things like:

  • Platform-specific deployment approaches and techniques
  • Platform-specific identity providers and authentication strategies
  • On/Off-boarding of tenants in SaaS solutions and tenant isolation
  • Synchronous protocols like REST, OData, or GraphQL 1
  • Asynchronous channels and brokers like SAP Event Mesh, MQ, or Kafka 1
  • Different database technologies including SQL and NoSQL

These abstractions allows us to quickly adapt to new emerging technologies or platforms, without affecting application code, thus safeguarding your investments.

CAP is Open and Opinionated → Zero Lock-in

That might sound like a contradiction, but isn’t: While CAP certainly gives opinionated guidance, we do so without sacrificing openness and flexibility. At the end of the day, you stay in control of which tools or technologies to choose, or which architecture patterns to follow as depicted in the table below.

CAP is Opinionated in…CAP is Open as…
Higher-level concepts and APIs abstracting from and avoiding lock-ins to low-level platform features and protocolsAll abstractions follow a glass-box pattern that allows unrestricted access to lower-level things, if required
Best Practices served out-of-the-box with generic solutions for many recurring tasksYou can always handle things your way in custom handlers, decide whether to adopt CQRS or Event Sourcing, for example … while CAP simply tries to get the tedious tasks out of your way.
Out-of-the-box support for SAP Fiori and SAP HANAYou can also choose other UI technologies, like Vue.js, or databases, by providing new database integrations.
Dedicated tools support provided in SAP Business Application Studio, and Visual Studio Code or Eclipse.CAP doesn’t depend on those tools. Everything in CAP can be done using the @sap/cds-dk CLI and any editor or IDE of your choice.

Key Concepts & Paradigms

The following sections highlight key concepts of CAP, which are based on two major paradigms: A declarative paradigm using CDS to capture knowledge about problem domains, and a service-centric paradigm, with ubiquitous notions of Services, Events, and Queries.

Focus on Domain, Powered by CDS

CAP places primary focus on domain, by capturing domain knowledge and intent instead of imperative coding — that means, What, not How — thereby promoting:

  • Close collaboration of developers and domain experts in domain modeling.
  • Out-of-the-box implementations for best practices and recurring tasks.
  • Platform-agnostic approach to avoid lock-ins, hence protecting investments.

The figure below illustrates the prevalent use of CDS models (in the left column), which fuel generic runtimes, like the CAP service runtimes or databases.

Anatomy of a Typical Application

Anatomy of a Typical Application

Core Data Services (CDS)

CDS is our universal modeling language to capture static, as well as behavioral aspects of problem domains in conceptual, concise, and comprehensible ways, and hence serves as the very backbone of CAP.

SAP Graph

SAP Graph is the easy-to-use API for the data of the Intelligent Enterprise from SAP. It provides an intuitive programming model that you can use to easily build new extensions and applications using SAP data.

SAP Graph

SAP One Domain Model

SAP One Domain Model is a single, coherent domain model for SAP's intelligent suite, spanning the digital core and all SAP cloud applications.

As the harmonized domain model for objects that are distributed throughout the different applications, SAP One Domain Model provides a basis for a consistent view on master data across the entire hybrid landscape.

By mapping objects to a central domain model, SAP One Domain Model enables applications to speak different languages, aligns configuration and transactional data, and sets the foundation for integration and extension scenarios.

Proven Best Practices, Served Out-of-the-Box

The CAP runtimes in Node.js and Java provide many generic implementations for recurring tasks and best practices, distilled from proven SAP applications. Benefits are significantly accelerated development, minimized boilerplate code, as well as increased quality through single points to fix and optimize.

Querying & Views

All data access in CAP is through dynamic queries, which allows clients to request the exact information they really need. These powerful intrinsic querying capabilities are key enablers for serving requests automatically.

Services & Events

All behavioral aspects in CAP are based on ubiquitous notions of Services and Events, as expressed in this manifest:

  1. All active things are Services — local ones, remote ones, as well as databases
  2. Services are declared in CDS — reflected and used in generic service providers
  3. Services provide uniform APIs — consumed by other services or frontends
  4. Services react on Events — covering synchronous and asynchronous APIs
  5. Services consume other Services — in event handler implementations
  6. All data is passive — that is, without its own behavior, adhering to REST

Services in CAP are stateless and with a minimal footprint, which allows you to modularize solutions into single-purposed (nano) services or functions-as-a-service.

Hexagonal Architecture à la CAP

Hexagonal Architecture

Grow-as-you-go

Following the principle of convention over configuration, there’s no need to set up things upfront. CAP allows you to jumpstart projects within seconds and have a team starting development right away, using generic providers, on top of a lightweight in-memory database → see Getting Started in a Nutshell.

CAP also offers mocks for many platform features, which allow fast dev-test-run cycles with minimal development environment complexity — aka Airplane Mode. Similarly, CAP greatly facilitates integration scenarios by simply importing an API from, say, an SAP S/4 backend or from SAP API Hub and running mocks for this locally.

Over time, you add things gradually, only when they’re needed. For example, you can move ahead to running your apps in close-to-productive setups for integration tests and delivery, without any change in models or code. → see Grow-as-you-Go.

Finally, projects are encouraged to parallelize workloads. For example, following a contracts-first approach, a service definition is all that is required to automatically run a full-fledged REST or OData service. So, projects could spawn two teams in parallel: one working on the frontend, while the other one works on the backend part. A third one could start setting up CI/CD and delivery in parallel.

Create first CAP service

Create a first project to showcase a custom micro service.

  • Open a new VS Code Window and open a new terminal CTRL-SHIFT-Ö (or using menu)
  • Locate your project folder root, for example cd .\VSC\playground\
  • Jumpstart new project cds init workshop
  • Change into generated project cd workshop
  • Open generated project in VS Code code .
  • Install dependencies npm install -> a new folder node_modules will be created
  • For an automated jumpstart, you can just watch changes using cds watch
  • Add script helper to ./package.json
    json
    "scripts": {
        ...
        "watch": "cds watch"
    },
  • Define your first service interface inside ./srv/world.cds
    js
    service say {
        function hello(to : String) returns String;
    }
  • Open local server http://localhost:4004
  • Implement service inside ./srv/world.js
    js
    module.exports = (say) => {
        say.on('hello', req => `Hello ${req.data.to}!`)
    }
  • Test it in browser http://localhost:4004/say/hello(to='world')
  • Your first service is up and running!

Test your service with REST Client

To be able to test your (and also external) service similar to POSTMAN, install the REST Client VS Code extension.

  • Install VS Code extension REST Client from Huachao Mao
  • Inside project root create folder ./test
  • Create REST Client test file ./test/world.http
    javascript
    @host = http://localhost:4004
    
    # @name helloWorld
    GET {{host}}/say/hello(to='world')
    ###
    
    # @name echo
    POST {{host}}/say/echo
    Content-Type: application/json
    
    {
        "to": "r2d2"
    }
    ###
  • Add new service handler to ./srv/world.cds
    js
    service say {
        action echo(to: String) returns String;
        ...
    }
  • Implement service handler ./srv/world.js
    js
    module.exports = (say) => {
        say.on('echo', req => `echo > ${req.data.to}!`)
        ...
    }
  • Test GET and POST service using ./test/world.http
  • Add extension using CTRL+SHIFT+P > Configure Recommended Extensions (Workspace Folder)
    "recommendations": [
      ...
      "humao.rest-client",
    ]

Add Deployment Information

Add SAP BTP deployment information and deploy the service to your trial account.

  • Check, if Cloud MTA Build Tool version 1.1.1 is available mbt -v
  • If not installed, add it globally using npm install -g mbt
  • Add MTA development descriptor ./mta.yaml to project root cds add mta
  • Run the MTA Build Tool mbt build -t ./
  • Got errors, see Troubleshooting guide
  • Watch ./gen folder and see generated workshop_1.0.0.mtar archive
  • Open your trial cockpit SAP BTP Cockpit (Trial)
  • Login to your SAP BTP space cf login entering API endpoint, credentials and select space
  • Deploy your first service cf deploy workshop_1.0.0.mtar
  • If you need to cleanup things later, you can undeploy to completely remove all artifacts
    cf undeploy workshop --delete-service-brokers --delete-services
  • Add script helpers to ./package.json to automate tasks
    json
    "scripts": {
        ...
        "build": "mbt build -t ./",
        "cf:deploy": "cf deploy workshop_1.0.0.mtar",
        "cf:undeploy": "cf undeploy workshop --delete-service-brokers --delete-services",
        "cf:login": "cf login -a https://api.cf.eu10.hana.ondemand.com/"
    },

Enrich the service with a REST endpoint using destination service

  • Add destination to ./package.json before scripts section
    json
    "cds": {
        "requires": {
            "API_JSONPLACEHOLDER_SRV": {
                "kind": "rest",
                "credentials": {
                    "destination": "jsonplaceholder",
                    "path": "",
                    "requestTimeout": 30000
                }
            }
        }
    },
  • Add local test environment ./default-env.json
    json
    {
        "VCAP_SERVICES": {},
        "destinations": [
            {
                "name": "jsonplaceholder",
                "url": "https://jsonplaceholder.typicode.com"
            }
        ]
    }
  • Add service interface to ./srv/world.cds
    js
    service say {
        ...
        function rest() returns String;
    }
  • Implement rest service inside ./srv/world.js
    js
    module.exports = (say) => {
        ...
        say.on('rest', async req => {
            // https://jsonplaceholder.typicode.com/
            const restSrv = await cds.connect.to('API_JSONPLACEHOLDER_SRV')
            const data = await restSrv.get('/todos/1')
    
            console.log('data', data)
    
            return data.title
        })
    }
  • Test it in browser http://localhost:4004/say/rest())
  • Watch console output
    userId: 1, id: 1, title: 'delectus aut autem', completed: false
  • Add ./mta.yaml destination ressource dependency and inline destination
yaml
modules:
 # --------------------- SERVER MODULE ------------------------
  - name: workshop-srv
 # ------------------------------------------------------------
    type: nodejs
    path: gen/srv
    requires:
      - name: workshop_xsuaa    
      - name: workshop_destination
#      - name: workshop_connectivity # add connectivity service for on-premise detsinations
    provides:
      - name: srv-api      # required by consumers of CAP services (e.g. approuter)
        properties:
          srv-url: ${default-url}
          
resources:
  - name: workshop_xsuaa
    type: org.cloudfoundry.managed-service
    parameters:
      path: ./xs-security.json
      service-plan: application
      service: xsuaa    
  - name: workshop_destination
    type: org.cloudfoundry.managed-service   
    parameters:
      service: destination
      service-plan: lite  
      config:     
        init_data:
          subaccount:
            existing_destinations_policy: ignore # update
            destinations:
              - Name: jsonplaceholder
                Type: HTTP
                Description: test REST service
                URL: https://jsonplaceholder.typicode.com
                ProxyType: Internet            
                Authentication: NoAuthentication
  • Create security profile ./xs-security.json
json
{
  "xsappname": "workshop",
  "tenant-mode": "dedicated",
  "description": "Security profile of called application",
  "scopes": [
    {
      "name": "uaa.user",
      "description": "UAA"
    }
  ],
  "role-templates": [
    {
      "name": "Token_Exchange",
      "description": "UAA",
      "scope-references": [
        "uaa.user"
      ]
    }
  ],
  "attributes": []
}
  • Build and deploy it to cloud

Domain driven design with SAP One Domain Model

Add support for SAP One Domain Model

  • Add @sap/odm package using npm install @sap/odm
  • See cookbook Domain Modeling with CDS
  • Reuse existing models and learn from SAP

Ressources

Tutorial

For a quickstart you can follow the tutorial Build an Application End-to-End using CAP, Node.js and VS Code with the prerequisite Set Up Local Development Using VS Code to prepare your local environment.