Skip to Content
Event Information
Author's profile photo DJ Adams

Annotated links: Episode 2 of Hands-on SAP dev with qmacro

This is a searchable description of the content of a live stream recording, specifically “Episode 2 – Starting to build a bookshop backend service with CAPM” in the “Hands-on SAP dev with qmacro” series. There are links directly to specific highlights in the video recording. For links to annotations of other episodes, please see the “Catch the replays” section of the series blog post.

This episode, titled “Starting to build a bookshop backend service with CAPM“, was streamed live on Fri 01 Feb 2019 and is approximately one hour in length. The stream recording is available on YouTube.


Below is a brief synopsis, and links to specific highlights – use these links to jump directly to particular places of interest in the recording, based on ‘hh:mm:ss’ style timestamps.

Brief synopsis

In the previous episode we set up our tools and development environment ready for some SAP Cloud Application Programming Model (CAPM) action of the Node.js (JavaScript) flavour. So now we’re ready to start exploring our first data and service definitions in the language of CAPM, i.e. CDS (Core Data & Services).

We follow the “Create a Business Service with Node.js using Visual Studio Code” tutorial on the SAP Developers tutorial navigator and start to explore what CAPM and CDS can do for us.

00:06:15: This time I’m holding my coffee mug the right way round to show the Coffee Corner Radio podcast logo to the camera!

00:06:46: A recap of what we did in the previous episode and how far into the tutorial we got.

00:08:55: Talking about what we get out of the box from CAP – built in core services for CRUD+Q, not boilerplate code that we must take over and manage ourselves.

00:10:05: Starting the CAP project with cds init my-bookshop.

00:10:50: Looking at what was installed when we installed the @sap/cds package and wondering why the @sap/generator-cds package has a different name pattern (all the other packages are cds-...). On this subject, Fred later makes what I think is a nice oblique reference to Conway’s Law: “Organizations which design systems … are constrained to produce designs which are copies of the communication structures of these organizations“.

Talking of @sap/generator-cds, we can see that this provides a “binary” (executable) cds-gen by looking at the output of npm info @sap/generator. This is used in turn by the cds command.

00:11:55: Taking a first quick look at what’s been generated in the my-bookshop project, and noting that the file contains a tutorial similar to what we’re following here. We also briefly explore the @sap packages inside the node_modules directory, especially the “binaries” in the .bin directory such as cds, cds-gen, cdsc, mime and uuid.

00:15:02: Initialising this project as a git repository so we can see and track changes, and then opening up the project in VS Code.

00:16:50: Looking at some VS Code specific items that have been created as part of the cds init based project generation, in particular the contents of the .vscode directory, relating to the launch and debug facilities that VS Code offers.

00:17:45: Creating the cat-service.cds file in the srv directory, and noticing immediately what the extension for CDS is doing for us (in terms of highlighting errors and even suggesting completions).

00:19:00: Thinking about what we’re doing with this first line:

using { Country, managed } from '@sap/cds/common';

This refers to common.cds inside the @sap/cds package itself; the file provides some basic types and definitions that are common to many projects. Definitions for languages, currencies and countries are in this file, for example. We explore this common.cds file here, looking at the managed type and the concept of aspects.

00:23:39: Noting the convention for names of entity definitions is capitalised and in the plural (e.g. “Books”) – this comes from CAP Best Practices – see the Using our Naming Conventions section.

00:25:38: Using the F8 shortcut to jump between errors that have been found in the CDS definition so far (which of course is because we’re using the VS Code extension for the CDS language that is pointing out these nrrors).

00:28:25: Looking in detail at how the managed aspect is used on the definition of the Orders entity, and what that aspect brings to the entity in terms of extra fields that are automatically filled on certain events.

00:32:05: Looking at the sap.common context, which is like a namespace, but within a file.

00:35:58: Bringing up the integrated terminal (with the shortcut Ctrl-]`) and maximising it with a custom keyboard shortcut. Here we use cds compile to see what is produced. In fact we don’t even use the compile command as that is the default, as we can see here:


  c | compile    ...individual models (= the default)
  d | deploy models to a database
  s | serve      ...service models to REST clients
  b | build      ...whole modules or projects
  i | init       ...jump-starts a new project
  e | env        get/set current cds configuration
  r | repl       cds's read-eval-event-loop
  h | help       shows usage for cds and individual commands
  v | version    prints detailed version information

So invoking cds srv/cat-service.cds we get a whole load of output, which is in fact Core Schema Notation (CSN), specifically a plain JavaScript object representation thereof (there are different representations possible – see the cds.compile documentation for details).

00:36:57: But this is too much to wrap our heads around right now, so we look at what else we can do here. Looking in the node_modules/.bin/ directory we see the cdsc executable which is the CDS compiler, and what the cds command uses for compilation. LET’S RUN IT! We see that it shows us all sorts of output in a help format, and we can explore what different types of compiler output are possible.

00:38:50: The options we see translate into parameters available for the cds compile command, like this one which we run now: cds srv/cat-service.cds --to sql which perhaps is more palatable to us right now:

CREATE TABLE my_bookshop_Authors (
  name NVARCHAR(5000),

00:39:39: We can also do this for HANA, thus: cds srv/cat-service.cds --to hana which produces something like this:

  key ID : Integer;
  NAME : String(5000);
  BOOKS : association[*] to MY_BOOKSHOP_BOOKS on BOOKS.AUTHOR_ID = ID;

00:40:44: Even though we don’t even have a persistence layer (a database) yet, we can start this service up, with cds run, which we do now, and we see a local server start up, listening by default on port 4004 (there’s a story behind why the port is 4004 … and it’s not because of the first commercial the Intel microprocessor as I’d thought … but I’ll leave that for another time :-)). We can change this port by setting the value of the PORT environmental variable too (e.g. PORT=1234 cds run).

00:44:10: Changing the service name from CatalogService to Banana we can see what effect this has on how the service is served.

00:44:50: We now examine the output from cds run and make sure we understand what’s going on:

[cds] - server listens at http://localhost:4004
[cds] - serving CatalogService at /catalog
[cds] - service definitions loaded from:


[cds] - launched in: 1350.885ms

The service definitions are loaded of course not only from our srv/cat-service.cds file but also the common.cds file that we’re using for the Country and managed definitions.

00:45:30: We can now explore what has been generated and is running for us (in the form of the OData V4 service document and metadata document), even though we have only a very simple definition, and no data!

00:45:35: Slightly controversially I make known my dislike for the choice of font for the “Welcome to” at this point 😉

00:46:35: Thanks to a question from MEXICO_MAN we explore how we might define multiple services in a single CDS definition file at this point. We add a second service definition to cat-service.cds:

service Mexico {
  entity Things {
    key ID : Integer;
    name   : String;

and when we reinvoke cds run we see:

[cds] - serving CatalogService at /catalog
[cds] - serving Mexico at /mexico

And we see the corresponding second group of links in the root web page. Nice!

00:52:40: Getting towards the end of this episode, we create a JavaScript based implementation of our service, by creating a file of the same name but with a .js extension, i.e. cat-service.js, in the same directory. By following this convention we can have the runtime use our JavaScript code to enhance the implementation of our definitions. This is Step 5 in the tutorial, by the way.

00:54:35: Finally we extend the implementation of the function for srv.on ('READ', 'Books', ...) in the cat-service.js implementation by changing the body of the function from a single expression that is returning an array, to a block that executes a console.log statement, and then returns the array.

After fixing an error due to the fact that I missed the definition of the “stock” property in the original Books entity definition, we can see the output from the console.log statement, which is a very small step towards a future investigation into logging and debugging (which we do in Episode 4). Hurray!

Assigned tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Jordi Hemelaer
      Jordi Hemelaer

      Hi DJ,

      Thanks for the tutorials!

      I followed your bookshop-example to build a CDS-based service wich I deployed to Cloud Foundry and use in a UI5-application. But I was wondering if it is possible to update a record in the service. When I try to update a record in my service, I get the “Method PUT not allowed for ENTITY.COLLECTION”-error. Same goes for PATCH.

      Could you help me out, please?

      Thanks in advance!

      Kind regards,


      Author's profile photo DJ Adams
      DJ Adams
      Blog Post Author

      Hey Jordi - you're welcome!

      Might I please suggest you ask this question on the community Q&A so that others can see it and perhaps also take part in responding? There's a tag for CAP, and the section is here:


      Author's profile photo Stefan Porges
      Stefan Porges

      Hi DJ,

      many thanks for your great videos. It is really a pleasure to follow. But I got a problem, and looks like, that I'm not able to find a solution on my own. So I created a question here:

      Maybe someone can help me.

      Thx in advance Stefan