Skip to Content
Technical Articles
Author's profile photo Thomas Jung

New SAP Cloud Application Programming Model Sample for Many-to-Many Relationships and Fiori Annotations

If you are looking for something fun yet educational this holiday season to play around with, might I suggest this new SAP Cloud Application Programming Model sample that was just released:

https://github.com/SAP-samples/cloud-cap-hana-swapi

I was recently looking around for a fun yet decently complex sample data model to reuse in an CAP example. I stubbled across SWAP – the Star Wars API. It had the interesting level of complexity I was looking for. It’s filled with many-to-many bi-directional relationships. Yet the data model is easy to understand on the surface.  There are Star Wars films that contain planets, characters, starships, etc. I also thought it make a good example of complex Fiori based maintenance. Going in I wasn’t exactly sure how the many-to-many relationships would work with Fiori Draft and deep editing; but it turns out the functionality worked out nicely.

Although the Star Wars API had been abandoned, this also provided a good challenge. I kept the original project’s data files as JSON and wrote converter scripts using CAP CQL to convert the data into the new version of the data model.

Overall I think this sample provides examples of a lot of deeper and more complex topics in the SAP Cloud Application Programming Model and Fiori area; but does so with some data that is a bit of fun to play around with.

Description

SWAPI – the Star Wars API. This sample is based upon the sample at swapi.dev which in turn was based upon swapi.co. The original source can be found at https://github.com/Juriy/swapi.

The original project was a data set and data model based in Python that exposed data from the Star Wars movies sourced originally from the community wiki: Wookiepedia. It encompasses data about the People, Films, Species, Starships, Vehicles and Planets from Star Wars.

The projects described above have fallen out of maintenance but still offered the opportunity for a fun yet challenging learning experience from a non-trivial data model. The many bi-directional, many-to-many relationships with the data provides a good basis for an SAP Cloud Application Programming Model and Fiori Draft UI sample.

Data Model

I’ve used the new openAPI functionality in CAP to generate both the Swagger UI test framework but also entity diagrams for the data model.

Films

StarWarsFilm%20Service

StarWarsFilm Service

People

StarWarsPeople%20Service

StarWarsPeople Service

Planets

StarWarsPlanet%20Service

StarWarsPlanet Service

Species

StarWarsSpecies%20Service

StarWarsSpecies Service

Starships

StarWarsStarship%20Service

StarWarsStarship Service

Vehicles

StarWarsVechicle%20Service

StarWarsVechicle Service

Requirements

Download and Installation

The original data model and data source files are in in the oldPython\resources folder.

The rest of the operations can be performed within the cap folder and there are scripts in the package.json file major operations.

You can use npm run build to perform the cds build and should be ran before deployment to HANA or whenever you make changes to the data model.

You can run npm run hana to deploy the content to your HANA database. Just be sure from the terminal that you are logged into the cf/xs cli and targeting the Account/Org/Space where you want the content to live. By default this command will create an HDI Container instance named starwars.

You can run the command npm run load. This command will read the original JSON data files from the source project and load them into your HANA database using Cloud Application Programming Model CQL. The loading script is convertData.js

The command npm start or cds run will start the service running locally. It will open the standard CAP test page where you expolore the OData Services or the Fiori UI.

From the Cloud Application Programming Model preview (which opens locally when using npm start or cds run), you can access the Swagger UI test tool (with entity diagrams), test the OData services or metadata calls directly in the browser, or access the Fiori preview UI for each of the main entities.

CAP%20Preview%20Test%20Page

CAP Preview Test Page

Fiori%20Preview%20List%20for%20Film%20Entity

Fiori Preview List for Film Entity

Fiori%20Preview%20Overview%20Edit%20Mode%20for%20Film%20Entity

Fiori Preview Overview Edit Mode for Film Entity

 

Note

Star Wars and all associated names are copyright Lucasfilm ltd. All data in this sample has been freely collected from Wookiepedia under CC-BY-SA.

Assigned Tags

      37 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Yogananda Muthaiah
      Yogananda Muthaiah

      really interesting Thomas Jung

      This holiday season will make me busy to try this out.  Happy Christmas to you and your family.  Happy Vacation and stay safe!

      Author's profile photo Julio Alberto Martinez Real
      Julio Alberto Martinez Real

      Amazing job.

      Do you have some example with edit + send file to service?

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      send file to service? Not sure what you mean by that.

      Author's profile photo Julio Alberto Martinez Real
      Julio Alberto Martinez Real

      Hi Thomas its an honor to talk with you.

      I was asking for the scenario when you need to edit data and send a file (an image of the film for example) to your odata service. Does odata support this kind of services?

       

      Im reasearchin about CAP. It seems an easy way to expose entities as an odata service.

       

      Thanks again for your job.

       

       

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      No media processing in this sample, but another one does have some:
      https://github.com/SAP-samples/hana-opensap-cloud-2020/blob/main/db/schema/masterData.cds#L402

      https://github.com/SAP-samples/hana-opensap-cloud-2020/blob/main/srv/handlers/md-service.js#L32

      Author's profile photo Fredrick Mumali
      Fredrick Mumali

      This is much better than the normal bookshop sample.  Thanks for sharing. Happy holidays Thomas Jung !

      Author's profile photo Jorge Sousa Villafaina
      Jorge Sousa Villafaina

      Very funny and interesting!! Thanks for sharing!

      Author's profile photo Maximiliano Luis Vai
      Maximiliano Luis Vai

      Thomas ,How do You create so many entities in the cap model or what is the methodology ?

      Thanks you,

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      Actually in this case I was converting an existing data model defined in JSON schema from the original project.  I was lazy and wrote a script to convert the base model and i18n entries over from that.  For all the additional annotations, compositions and annotations I didn’t really use a methodology.  I just typed it all in by hand.

      Author's profile photo Mustafa Bensan
      Mustafa Bensan

      Hi Thomas,

      What naming convention are you following for the data model?  I notice that in most cases the entity names have a capitalised first letter, such as Starship, Vehicles and Planet, whereas in some cases the entity name starts with a lower case letter, such as directors, producers, eyeColors and skinColors.

      Thanks,

      Mustafa.

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      The "real" entity names begin with capital letters whereas the views begin lower case.

      Author's profile photo Amina Alavi
      Amina Alavi

      Amazing job Thomas!

      I am trying this out in BAS in the trial account and was successfully able to clone it under my projects .  But now I ran into an issue when I run "npm run build" command. I am running it within the cap folder. This is the error. Am I missing a step?

      Error

      Thanks,

      Amina

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      Looks like you've not done an npm install. You need to do so to install the dependent packages before you can run the project.

       

      Author's profile photo Amina Alavi
      Amina Alavi

      It worked!! Thanks

      Author's profile photo Max Schnürle
      Max Schnürle

      Thank you Thomas Jung  quite helpful Blog!

       

      Do you know if it is possible in CAP(Fiori Elements) to display the people(collection) as a UI Line Item right in the list Report page already?

       

      Best Regards

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      Do you mean from the UI where the Films is the lead entity?  You can expand and add attributes from any child entity of the main entity IF the association cardinality is 1:1.  But in this case there are many people for each Film entity therefore you couldn't logically expand that on the UI Line Item of the List Report. But you could use People the primary entity of a UI and then it would be in the List Report.

      Author's profile photo Jose Luis Jeßberger
      Jose Luis Jeßberger

      Hi Thomas Jung  love this project  😀 way more to see than in the bookshop example.

      Im stuck at the point where i try to fill the db with data with npm run load.

      I did the npm install , still the same :-/

      EDIT: i solved the issue "The node binary is used for ...etc" with the command "npm config set scripts-prepend-node-path auto"

      The error: Couldnt find a cds model still persits

      Error%20Error%20chicken%20Terror

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      Have you performed a cds build first?  The error seems to indicate that you are missing the csn.json that would be created by the cds build. You'd want to build and probably deploy to HANA before you try and load data.  Have those two steps been sucessful?

      Author's profile photo Jose Luis Jeßberger
      Jose Luis Jeßberger

      I think so. Isnt npm run building them ?

      That are the commands i used:

      • I had a hana instance running and was logged in to cf:api
      • Git clone <URL>
      • Cd cap
      • //Than i went to the package.json
      • //i looked at the "scripts" part of the package.json
      • Npm run  //o build the artifacts for hana
      • Npm run hana
      • // I checked the Hdi container with all tables in the database explorer
      • Npm install
      • Npm run load

      Thats where it went wrong. I had no data loaded. and the shown issue in my previous post.

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      Just tested in both VSCode and BAS and it worked for me. I noticed you were getting a blank folder in path and thought that might be an issue on Linux (but not Windows where I had primarily test). I corrected that blank folder, but tested both ways in the Business Application and it worked fine.

       

      Check in the Explorer to make sure in that path of /cap/gen/srv/srv/ you have a csn.json file.  When I do a cds build that's where the model output is going in both VSCode and BAS.

      Author's profile photo Jose Luis Jeßberger
      Jose Luis Jeßberger

      Thank you so much. It works now. I still dont know why but finaly I can experiment with the swapi app.

      Im doing your hana hands on tutorials and a few tuts on developer.sap. learned alot from you and the Team. Marius Obert has helped me alot too. Thanks for your effort <3

       

      Author's profile photo Matthias Lakämper
      Matthias Lakämper

      Hi Thomas Jung

      i use my holiday-summer-time to check your wonderful starwars-project.

      I run the Project in Visual-Studio-Code on Windows10 locally.

      Actually i run in the error: VError: Found 0 matching services.

      i have executed:

      cds build

      cds watch

      where am i going wrong?

      Kind Regards,
      Matthias Lakämper

       

       

      Author's profile photo Matthias Lakämper
      Matthias Lakämper

      Hi,
      it works now, i have deployed to cf.

      Isn´t it possible to run the project local?

       

      Kind Regards,
      Matthias

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      Yes you can run the project locally.  When you deploy to HANA a default-env.json file will be created with the credentials. This can also be copied to the root of the project to tell the cds run how to connect to HANA for testing.  Or you can use the hana-cli developer tool to create the default-env.json as well. The default-env.json simulates the environment and the service bindings you would have when you fully deploy to Cloud Foundry and allows you to test locally but still connect to the backing services such as your HANA DB.

      Author's profile photo Gowtham Raja M
      Gowtham Raja M

      i am getting below error when i run "npm run hana" as below

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      Interesting. I've never seen this error before.  You don't get an error on the service instance itself but it seems to be that it already existed. It's only when it creates the key that you get an error.  First is your HANA instance running?  If you are using HANA Cloud Trial, remember that the instance stops every night (to save money) and has to manually be started each day

      Author's profile photo Gowtham Raja M
      Gowtham Raja M

      Yes i am using hana cloud trial. I have started the instance and its up and running

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      I'm afraid I can't recreate this issue. I'm using the same project and also on a trial account. It works fine

       

      So there doesn't appear to be any issue with this specific sample nor a general infrastructure issue. It would seem to be contained to your account. If you perform a cf services - how many HANA HDI instances do see?  Do you have a lot of other instances created in this account already?  And what i fyou try and create the service-key yourself.  Do you get the same error when creating from the command line manually?

      Author's profile photo Gowtham Raja M
      Gowtham Raja M

      i have deleted the application and try adding the project again. Now when i run "npm run hana" it is giving the error as attached

       

       

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      That error is pretty straight forward that there is no connection possible to your HANA Database.  This generally either means that the HANA DB isn't running (see earlier comment about the trial database stopping every day) or that your allow list on the trial instance is restricted and rejecting the connection.

      Author's profile photo Yogesh Chacha
      Yogesh Chacha

      Thomas,

      I am getting the below error message, npm run hana has successfully created HDI service on CF, however when I run the app it gives "[cds] - Error: No database credentials provided".

       

      Please help, Thanks!

       

      [odata] - GET /-data/Entities
      [odata] - POST /StarWarsFilmFilm {
      '$count': 'true',
      '$select': 'HasActiveEntity,HasDraftEntity,ID,IsActiveEntity,director,episode_id,producer,release_date,title',
      '$filter': '(IsActiveEntity eq false or SiblingEntity/IsActiveEntity eq null)',
      '$expand': 'DraftAdministrativeData($select=DraftUUID,InProcessByUser,LastChangedByUser)',
      '$skip': '0',
      '$top': '30'
      }
      [cds] - Error: No database credentials provided
      at singleTenantInstanceManager (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/libx/_runtime/hana/pool.js:63:41)
      at credentials4 (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/libx/_runtime/hana/pool.js:78:9)
      at /home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/libx/_runtime/hana/pool.js:168:9
      at new Promise (<anonymous>)
      at pool4 (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/libx/_runtime/hana/pool.js:167:7)
      at Object.acquire (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/libx/_runtime/hana/pool.js:250:24)
      at HanaDatabase.acquire (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/libx/_runtime/hana/Service.js:129:28)
      at HanaDatabase.begin (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/libx/_runtime/db/Service.js:45:23)
      at HanaDatabase._begin [as dispatch] (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/lib/srv/srv-tx.js:201:43)
      at HanaDatabase.send (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/lib/srv/srv-api.js:52:17) {
      id: '1180409',
      level: 'ERROR',
      timestamp: 1677106411468
      }

       

      Regards

      -Yogesh

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      How are you running the app?  With CDS hybrid testing you need to specify the profile you are using.  In this sample project I have the npm command "watch".  It will start the application with the hybrid profile and it will find the database credentials correctly then based upon the earlier cds bind.

      Author's profile photo Yogesh Chacha
      Yogesh Chacha

      Thomas,

      Thanks for the quick response

      I am running the following commands in CF

      cf login

      npm install

      npm run build

      npm run hana --> it creates starwars instance in SAP HANA Schemas & HDI Containers, however it removes the ./gen/srv/srv directory

      npm run load --> this process fails with "Error: Couldn't find a CDS model for '/home/user/projects/cloud-cap-hana-swapi/cap/gen/srv/srv/csn.json' in /home/user/projects/cloud-cap-hana-swapi/cap" as the ./gen/srv/srv folder is missing

      re-running the "npm run build" command

      npm run build

      npm run load

       

      user: cap $ npm run load

      > cap-hana-swapi@1.1.7 load
      > node convertData

      Model Location: /home/user/projects/cloud-cap-hana-swapi/cap/gen/srv/srv/csn.json
      Clearing existing DB tables
      Error: No database credentials provided
      at singleTenantInstanceManager (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/libx/_runtime/hana/pool.js:63:41)
      at credentials4 (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/libx/_runtime/hana/pool.js:78:9)
      at /home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/libx/_runtime/hana/pool.js:168:9
      at new Promise (<anonymous>)
      at pool4 (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/libx/_runtime/hana/pool.js:167:7)
      at Object.acquire (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/libx/_runtime/hana/pool.js:250:24)
      at HanaDatabase.acquire (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/libx/_runtime/hana/Service.js:129:28)
      at HanaDatabase.begin (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/libx/_runtime/db/Service.js:45:23)
      at HanaDatabase._begin [as dispatch] (/home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/lib/srv/srv-tx.js:201:43)
      at /home/user/projects/cloud-cap-hana-swapi/cap/node_modules/@sap/cds/lib/srv/srv-dispatch.js:20:32
      user: cap $

      When I run the below command, it connects to database, since the npm run load command failed, it has no data. The problem is loading data into HANA database, rest all the steps are working fine.

      cds watch --profile hybrid --livereload false

       

      [cds] - connect using bindings from: { registry: '~/.cds-services.json' }
      [cds] - connect to db > hana {
      database_id: 'xxxxxxxxxxxxxx',
      host: 'xxxxxxxxxx.hanacloud.ondemand.com',
      port: '443',
      driver: 'com.sap.db.jdbc.Driver',
      url: 'jdbc:sap://xxxxxxx.hanacloud.ondemand.com:443?encrypt=true&validateCertificate=true&currentschema=xxxxxxxxxxxx',
      schema: 'xxxxxxxxxxxxxxx',
      hdi_user: 'xxxxxxxxxxxxx',
      hdi_password: '...',
      user: 'xxxxxxxxx',
      password: '...',
      certificate: '...'
      }

      [cds] - connect to messaging > file-based-messaging
      [Open API] - serving DataService at /api-docs/-data
      [cds] - serving DataService { path: '/-data', impl: 'srv/data-service.js' }
      [Open API] - serving StarWarsFilm at /api-docs/StarWarsFilm
      [cds] - serving StarWarsFilm { path: '/StarWarsFilm' }
      [Open API] - serving StarWarsPeople at /api-docs/StarWarsPeople
      [cds] - serving StarWarsPeople { path: '/StarWarsPeople' }
      [Open API] - serving StarWarsPlanet at /api-docs/StarWarsPlanet
      [cds] - serving StarWarsPlanet { path: '/StarWarsPlanet' }
      [Open API] - serving StarWarsSpecies at /api-docs/StarWarsSpecies
      [cds] - serving StarWarsSpecies { path: '/StarWarsSpecies' }
      [Open API] - serving StarWarsStarship at /api-docs/StarWarsStarship

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      If you use a default-env.json to store your credentials locally for testing, then nothing special is needed to run his script.  But if you are using CAP hybrid testing (.cdsrc-private.json), then you have to pipe the command through the cds cli to fill the credentials into the environment. You can do this with cds bind --exec .  I've added an example of this to the packag.json of the sample code repo.

      Author's profile photo Yogesh Chacha
      Yogesh Chacha

      Thomas,

      Thanks for the quick turnaround, much appreciated!

      The load2 process loaded some of the tables and then it failed with the following error, at least now I can see some data in the App, Thanks!

      Insert into People
      Insert into Planet2People
      Insert into Starship
      Insert into Starship2Pilot
      Insert into Vehicles
      Insert into Vehicle2Pilot
      Insert into Species
      Insert into Species2People
      Insert into Film
      Insert into Film2People
      Insert into Film2Planets
      Insert into Film2Starships
      Insert into Film2Vehicles
      Insert into Film2Species
      Done
      node:internal/process/promises:279
      triggerUncaughtException(err, true /* fromPromise */);
      ^

      [UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "Error: transaction rollback, deferred fk constraint violation: deferred foreign key violation on table 62733362C436424585115B4F8DB777E0:STAR_WARS_VEHICLE2PILOT".] {
      code: 'ERR_UNHANDLED_REJECTION'

       

      Regards

      -Yogesh

       

      Author's profile photo Thomas Jung
      Thomas Jung
      Blog Post Author

      Interesting - you are getting a foreign key constraint, but I changed the logic a few releases back to no longer use so much parallelization due to the FK checks.  But I'm unable to recreate the issue.  I just cleared my HDI container, recreated and loaded the data without any error:

      Although I can't recreate, I've reduced the parallelization further in a new version of the script I just pushed.  This will force the program to wait until all vehicles are loaded before it tries to load the Vechcle2Pilot table (and the same for other related loads).

      cloud-cap-hana-swapi/convertData.js at main · SAP-samples/cloud-cap-hana-swapi (github.com)

      Author's profile photo Yogesh Chacha
      Yogesh Chacha

      Thomas,

      Thanks! it worked like a charm.

      DB Tables Cleared
      Reading people.json
      Reading planets.json
      Reading films.json
      Reading species.json
      Reading starships.json
      Reading vehicles.json
      Reading transport.json
      Insert into Planet
      Insert into People
      Insert into Planet2People
      Insert into Starship
      Insert into Starship2Pilot
      Insert into Vehicles
      Insert into Vehicle2Pilot
      Insert into Species
      Insert into Species2People
      Insert into Film
      Insert into Film2People
      Insert into Film2Planets
      Insert into Film2Starships
      Insert into Film2Vehicles
      Insert into Film2Species
      Done
      user: cap $

       

      Regards

      -Yogesh