Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
jhodel18
Active Contributor
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!~
11 Comments
Labels in this area