In my last blog post Keep the Core Clean with CAP Model, we found out that CAP’s service API doesn’t support handling the draft-generated properties out-of-the-box, however, it’s technically feasible to handle this ourselves in the custom handler. And you might be wondering, has anyone done it? Well, the answer is yes, because I did!

Let me backtrack and recall how I got here in the first place. First, I wanted to do a side-by-side extensibility using standard OData APIs with the goal in mind to keep the core clean. Then I looked into the available frameworks to help me achieve that, which are the RAP and CAP frameworks. And then I quickly realized that there was very little support in making this happen because both frameworks only supported the OData V2 service (non-draft) for this scenario. The golden standard now (the year 2023) for building applications from scratch is using Fiori Elements with draft capabilities (OData V4 is implied here). It’s hard to settle for something less, especially when development is so much easy when using Fiori Elements with draft.

Therefore, if there’s a tiny sliver of chance of making this functionality work, then I will take it. And so I did take that opportunity since CAP doesn’t completely block me from implementing functionality through a custom handler! However, the road was bumpy and so painful because there are so many case scenarios that you need to write the custom logic for. And I believe that no developer should be subjected to such kind of torture ever again! That’s why I made the Rizing CDSX (@rizing/cds-extension) module so you don’t have to suffer like I did. If that sounds interesting to you, then please continue reading.

 

 

The Demo Project


Just like in the previous blog post that uses the CAP framework, the demo project can be found in the same GitHub repository: https://github.com/jcailan/cap-fe-samples.

 

Data Model

For the data model definition, we need to create an entity which I call Shadow Persistence Entity. This Shadow Persistence Entity (or SPE for short) simply means that the entity from a remote service is recreated as a CAP persistence entity. In some ways, it’s like tricking the CAP framework that this is the real persistence entity, but in actual fact, the data will be persisted in a remote server using an external service.

Data Model: db > remote.cds

context remote {

    @cdsx.api: 'product_external'
    entity Products {
        key ID               : UUID;

            @mandatory
            name             : String;

            @mandatory
            description      : String;
            imageUrl         : String;
            releaseDate      : DateTime;
            discontinuedDate : DateTime;

            @mandatory
            price            : Decimal(16, 2);
            height           : Decimal(16, 2);
            width            : Decimal(16, 2);
            depth            : Decimal(16, 2);

            @(
                mandatory,
                assert.range: [
                    0.00,
                    20.00
                ]
            )
            quantity         : Decimal(16, 2);

            @mandatory
            UnitOfMeasure_ID : String(3);

            @mandatory
            Currency_ID      : String(3);
            DimensionUnit_ID : String(2);

            @mandatory
            Category_ID      : String(1);
            Supplier_ID      : UUID;
            createdBy        : String;
            createdAt        : Timestamp;
            modifiedBy       : String;
            modifiedAt       : Timestamp;
    }
}

The above cds file is an example of SPE. It’s a replication of the entity definition of the Products entity for the remote service called product_external. The SPE contains the typical CAP CDS annotations except only for one annotation at the entity level — @cdsx.api. The @cdsx.api annotation is used to specify that this Products entity should be proxied by an external service called product_external. If you have already worked on CAP that consumes external services before then you are already aware that this external service is configured in the package.json file, otherwise, you might want to check my earlier blog post that discusses this topic.

 

Service Model

The service model definition is very straightforward, it just contains the projection to the SPE Products entity with the @odata.draft.enabled annotation.

Service Model: srv > ProductCDSX.cds

using {remote} from '../db/remote';

service ProductCDSX {

    @odata.draft.enabled
    entity Products as projection on remote.Products;

}

 

Remote Service Configuration

It goes without saying that I have used cds import command to import the remote service’s metadata.xml file to generate the so-called service definition file (csn file). And with this step, a remote service configuration is automatically added to my package.json file.

Configuration: package.json

	"cds": {
		"requires": {
			"product_external": {
				"kind": "odata-v2",
				"model": "srv/external/products"
			}
		}
	}

 

Rizing CDSX Module

The Rizing CDSX module (or just CDSX) is easy to set up. Of course, like any other node module, you need to install it first and then bootstrap it into CAP’s runtime by using one of CAP’s available hook events.

Bootstrap CDSX: srv > server.js

const cds = require("@sap/cds");
const cdsx = require("@rizing/cds-extension");

cds.on("bootstrap", (app) => {
	cdsx.load();
});

Just like that, it’s very easy!

 

Testing


Now it’s time to test the CAP service powered by CDSX! Since we are using the OData draft feature, it’s best that we test this using a Fiori Element app. Luckily, the sample project is already fitted with a generated Fiori Element app and is ready to test.

  • just run the command cds watch as normal
  • then launch the only web application available — launchpage.html
  • finally, click on the tile Manage Products (External Service) CDSX

And you will be able to test a Fiori Element app backed by a CAP-based OData V4 service with draft capabilities.

 

Closing


In my journey of finding the ideal solution for keeping the core clean and trying to make use of the latest available SAP frameworks, I found myself hitting some limitations. Through CAP’s guiding principle of being an open but opinionated framework, I found a tiny sliver of hope that I could bridge the gap and implement the solution myself. And that solution was developed as a reusable node module which then gave birth to what I call now the Rizing CDSX — it is easy to use and I find it very helpful as a complementary tool/framework that helps in keeping the core clean. I hope you may find it useful as well.

 

 

 

~~~~~~~~~~~~~~~~

Appreciate it if you have any comments, suggestions, or questions. Cheers!~

Sara Sampaio

Sara Sampaio

Author Since: March 10, 2022

0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x