Event Information
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.
Links to specific highlights
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 README.md
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:
COMMANDS
c | compile ...individual models (= the default)
d | deploy ...data 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 (
ID INTEGER,
name NVARCHAR(5000),
PRIMARY KEY(ID)
);
...
00:39:39: We can also do this for HANA, thus: cds srv/cat-service.cds --to hana
which produces something like this:
using MY_BOOKSHOP_BOOKS as MY_BOOKSHOP_BOOKS;
entity MY_BOOKSHOP_AUTHORS {
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:
srv/cat-service.cds
node_modules/@sap/cds/common.cds
[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 cds.services” 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!
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,
Jordi
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:
https://answers.sap.com/tags/9f13aee1-834c-4105-8e43-ee442775e5ce
Cheers!
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:
https://answers.sap.com/questions/12671107/context-sapcommon-with-syntax-errors-on-version.html
Maybe someone can help me.
Thx in advance Stefan