Technology Blog Posts by Members
cancel
Showing results for 
Search instead for 
Did you mean: 

While executing tasks we all need the right tools to get the job done. This goes for every profession as it goes for an SAP CAP – developer. We are provided a whole set of different tools thanks to the CAP – team. But making the right choice of tool for the right task, using it in an efficient way is up to us. That’s why I’m writing this blogpost to share a few of my daily CAP – tools and experiences with all of you. Maybe it can help you in your current or future CAP – developments. Feel free to share your favorite tools and experiences or which tools are missing in my toolbox in your opinion.

Note: some features might only be available from certain releases. I tried to add the link to the CAPire documentation to as many features possible, where the version is shown.

Project setup tools

When setting up a new CAP project the following tools help me to quickly have a working POC up and running.

Initializing the project with all basic required files:

 

cds init my-cap-projects-toolbox
cd my-cap-projects-toolbox

 

 

Adding and enabling typescript in the project:

https://cap.cloud.sap/docs/node.js/typescript#enable-typescript-support

 

cds add typescript
npm i

 

 

Add a basic 'db/datamodel.cds' file:

 

using {cuid} from '@sap/cds/common';

namespace my.cap.toolbox;

entity Books : cuid {
    title       : String;
    description : String;
    author      : Association to Authors;
}

entity Authors : cuid {
    firstName : String;
    lastName  : String;
    fullName  : String = firstName || ' ' || lastName;
    books     : Composition of many Books on books.author = $self;
}

 

 

Add a basic service 'srv/ToolboxService.cds' file:

 

using my.cap.toolbox as toolbox from '../db/schema';

service ToolboxService {
    
    entity Authors as projection on toolbox.Authors;

    entity Books as projection on toolbox.Books;
}

 

 

Providing initial data to the project:

 

cds add data --records 5

 

(--content-type json for JSON format) (--force to override existing data)

https://cap.cloud.sap/docs/tools/cds-cli#data

 

Adding a .http file to test all CRUD operations on the exposed entities:

 

cds add http

 

https://cap.cloud.sap/docs/tools/cds-cli#http

 

Providing handlers for the exposed entities:

 

cds add handler

 

If you encounter issues while adding this because of a different local or global package installation you can also execute the command as such (if correct version installed):

 

npx cds add handler

 

https://cap.cloud.sap/docs/tools/cds-cli#handler

 

Add this point I’m ready to start a full working CAP application, this using the command below:

 

cds watch

 

Indeed, we do not have to use the cds-ts or cds-tsx command anymore:

https://cap.cloud.sap/docs/releases/dec24#cds-watch-for-typescript

By executing a CRUD request from the generated 'test/httpToolboxService.http' file we can immediately test our created service:

vvdries_0-1734939215999.png

When performing a follow-up GET-request we see the entry was added to the db.

Since a custom handler was added by executing the cds add handler command we could write custom logic and debug the service. To debug the service (in SAP Business Application Studio) you could simply open a new terminal by pressing the ‘+’-button, choosing he ‘JavaScript Debug Terminal’ option, followed by running the ‘cds watch ‘ command. This will start the application in debug mode (I noticed that the debugger was not triggered in case of ‘cds watch’, when using ‘cds-ts’ watch it did):

vvdries_1-1734939255574.png

 

Let us add a breakpoint in the “After READ” handler:

vvdries_2-1734939281256.png

Execute the GET command to read all Authors from your .http file and see how to breakpoint in your custom handler is triggered:

vvdries_3-1734939302955.png

To enhance my CAP – projects configuration even more I add the ‘Hybrid-testing’ feature to it. This allows me to test my application with different profiles and to use bound instances of my application.

More information about this feature can be found on the SAP CAPire documentation:

Or in my blogpost called ‘SAP CAP Hybrid Testing’.

Once your application has been deployed and you desperately need to debug the remote application, there is the amazing blog post of Arley ‘Set Up Remote Debugging to Diagnose CAP Applications (Node.js Stack) at Runtime on SAP BTP, Cloud Fo...’ which will help you to get the job done.

Or you can try out the (at this moment in Beta) ‘cds debug’ command (only VS-Code I believe at the moment): https://cap.cloud.sap/docs/releases/nov24#cds-debug

If you would like to see more great TypeScript examples/explanations you can have a look at the Devtoberfest session ‘It's Time for TypeScript (CAP edition)’ of Mike Doyle: https://www.youtube.com/watch?v=5DX6FwR5fss

Interested in more ‘TypeScript’ and ‘cds add’ features?

Then the Devtoberfest session ‘CAP Tools - What's new’ of Christian Georgi is the place to be: 

https://www.youtube.com/watch?v=c1s8n-_mR3M

Setting up, configuring, running, testing, and debugging couldn’t be easier thanks to these great CAP – tools and features. No time wasted by providing initial data or finding the correct configuration. The manual tasks were reduced to the minimum so we developers can focus on what we like most, developing a CAP application.

 

Project development tools

When developing CAP applications, you might be surprised how many solutions there are already out there answering your needs. You do not have to develop every feature yourself, you just need to use them! The only thing you need to do is the visit the SAP CAPire plugins documentation page and use whatever is required for your feature to build.

Further I would like to share some insights and tools which I found extremely handy during my latest CAP developments. The reason I picked out the once mentioned below, is that they were not so obvious at first, or a little harder to find.

 

Open Types

One would wonder why you need such an annotation. Well, in a certain very dynamic project, we have an application that needs to send a dynamic structure to the backend application. Not being able to send the data in such a structure would force us to create unlogic data models.

Let us use our added .http test file and send a POST request to our CAP application.

We add a non-existing property called “favoriteFood” to the payload and we see we get the error-message:

 

[error] - 400 > {
  code: '400',
  message: 'Property "favoriteFood" does not exist in ToolboxService.Authors'
}

 

vvdries_0-1734939637109.png

We can annotate our entity with the ‘@open’ aspect to allow such behavior:

vvdries_1-1734939658279.png

When we try to send the same payload again we see that in our custom handler the property is available in the req.data:

vvdries_2-1734939701408.png

Note that this property will not be present in the response of the created entry. More information about open types can be found on the SAP CAPire documentation.

 

cds.odata.X

The cds.odata contains two great functions which allow you to either parse or urlify the input. I’m not entirely sure if this is against best practices to use this OData function from '@sap/cds', feel free to enlighten me about it. 😊

vvdries_3-1734939738074.png

Continuing on this dynamic solution we needed to be able to provide a dynamic query/selection that needs needs be adjustable by admin users. Imagine you have a database table maintained by an admin via a UI application. The UI application allows the user in a friendly way to save the following string to a database, and thus can be maintained by the UI:

 

Authors?$select=ID,lastName&$expand=Books($select=ID,title ;$orderby=title)

 

When a consuming user wants to read the Authors entity, the string above could be used to select data from the entity. But executing such an OData query to your database could get tricky without the right tool.

But with the functionality cds.odata.parse this is only 1 line taking care of the job:

 

cds.odata.parse("Authors?$select=ID,lastName&$expand=books($select=ID,title ;$orderby=title)")

 

It generates you a SELECT query executable onto your database:

vvdries_4-1734939797317.png

Such a solution could be a done via the simple lines below:

vvdries_5-1734939816949.png

The reversed action is possible as well, but again not 100% sure if this is against the best practice rule.

 

Entity selections

There are many cases where you will be querying remote services and they might not have naming conventions following yours. That’s why you will be providing aliases for those external entities. In the example below we are consuming the Northwind OData service and we select and alias a few properties:

vvdries_6-1734939844761.png

When implementing a custom handler for this entity it is important to know how you are selecting from this remote service.

Note that in the example below we are selecting from “Orders” being a string:

vvdries_7-1734939872197.png

Which results in a response not considering our alias and selection:

vvdries_8-1734939884785.png

When selecting from the imported and cds-typer generated entity Orders:

vvdries_9-1734939901066.png

We see that our selection and aliases have been applied onto the selection and thus the result:

vvdries_10-1734939913593.png

 

I would encourage you to always go for the second example of selection unless you have a specific need for it of course. One could call it selection on service and selection on database level if it makes sense to distinguish it that way. Maybe you already noticed, but that means that if we use this string entity prefixed by our service name concatenated by a “.” we can select from different service “.cds” files.

Long story short you could be selecting like this:

 

await northwindSrv.run(SELECT.from("ServiceName.EntityName"))

 

Where your ServiceName is the name of your service defined in a service.cds file.

The following screenshot will clarify a lot:

vvdries_0-1734941565017.pngSo as the above screenshot shows, you have a ToolboxService.cds (green) which has handlers implemented in a ToolboxService.ts file. This implements a READ handler, which SELECT from a ToolboxService2.cds file (red), that only exposes the ID of Orders with a different alias (blue) and results in only the ID’s returned with the alias “myID” from ToolboxService2. This shows you can on one hand seriously connect, reuse, and implement service in a very extendable way. But that on the other hand if you do not document or have an aligned way of working, you can really create a huge nest of code that is very hard to understand.

 

Temporal Data

Temporal in a nutshell could be explained as data which is still valid and not expired. This is of course a very basic explanation for the Temporal data concept. More information about can be found on the SAP CAPire documentation.

You can define such an entity using the “temporal” aspect. Your entity could look like this:

vvdries_12-1734940069225.png

While the initial data looks like this:

vvdries_13-1734940082163.png

As you notice there are valid from and valid to properties defined because of the temporal aspect. Exposing the entity and retrieving the data would result in the following response:

vvdries_14-1734940097612.png

In the response above you see that only the “valid” entry is returned.

If you would like to retrieve all the entries, you could implement a custom handler and perform the data selections as follows:

vvdries_15-1734940109461.png

Notice that we here select from “Bikes” as a string and not from the generated cds-typer import. Exactly the opposite of the Northwind example. You could thus expose two entities, one for valid entries and one for all the entries.

vvdries_16-1734940148439.png

Not to forget that you could also use the foreseen temporal query parameters in the SAP CAP documentation. Which is the preferred way to implement your temporal consumption. But now you see how this temporal behaves under the hood. 😊

 

Conclusion

Via this way I hope to have shared some of the amazing tools offered by CAP, which I use daily to get the job done. There obviously are many more tools, all useful when facing certain challenges. Too many to list, but perhaps less obvious once are now shared in my opinion. Happy to hear if they were a secret to you and if they can be useful in your future projects.

Happy developments!

 

 

 

4 Comments
Labels in this area