You can create a CAP project in either Node.js or Java. You have to choose one way or the other and follow through. The tabs Node.js and Java provide detailed steps for each alternative way.
In SAP Business Application Studio, go to your IncidentManagement dev space.
Make sure the IncidentManagement dev space is in status RUNNING.
Choose the burger menu and choose Terminal → New Terminal.
Terminal
Navigate to the projects folder from the root directory.
Shell
cd projects
Your main interaction is through the cds command. It’s used to build, run, and debug your CAP application. You can also use cds to enrich your application with additional capabilities such as messaging, multitenancy, or cloud integration. You can learn more about the tool’s capabilities in Command Line Interface (CLI).
This command creates a folder incident-management with your newly created CAP project.
Choose the Explorer icon and then choose Open Folder. Type /home/user/projects/ in the field and select incident-management. Choose OK to open the project in SAP Business Application Studio.
Open SAP Business Application Studio folder
You can also use the Cmd+Shift+E (macOS) or Ctrl+Shift+E (Windows/Linux) key combination to quickly navigate to the Explorer.
While you’re in the incident-management folder, choose the burger menu and then choose Terminal → New Terminal.
Install dependencies with the following command:
Shell
npm install
Start a CAP server:
Shell
cds watch
The CAP server serves all the CAP sources from your project. It also “watches” all the files in your projects and conveniently restarts whenever you save a file. Changes you’ve made are immediately served without you having to run the command again. In this newly created project the CAP server tells you that there are no models or service definitions yet that it can serve.
Here is the output that you get:
Shell
cds serve all --with-mocks --in-memory?
live reload enabled for browsers
___________________________
No models found in db/,srv/,app/,schema,services.
Waiting for some to arrive...
In SAP Business Application Studio, go to your IncidentManagement dev space.
Make sure the IncidentManagement dev space is in status RUNNING.
Choose the burger menu and choose Terminal → New Terminal.
Terminal
Navigate to the projects folder from the root directory.
Shell
cd projects
Your main interaction is through the cds command. It’s used to build, run, and debug your CAP application. You can also use cds to enrich your application with additional capabilities such as messaging, multitenancy, or cloud integration. You can learn more about the tool’s capabilities in Command Line Interface (CLI).
This command creates a folder incident-management with your newly created CAP Java project.
Choose the Explorer icon and then choose Open Folder. Type /home/user/projects/ in the field and select incident-management. Choose OK to open the project in SAP Business Application Studio.
Open SAP Business Application Studio folder
You can also use the Cmd+Shift+E (macOS) or Ctrl+Shift+E (Windows/Linux) key combination to quickly navigate to the Explorer.
While you’re in the incident-management folder, choose the burger menu and then choose Terminal → New Terminal.
Navigate to the srv folder.
Shell
cd srv
Run the following command to start a CAP Java server:
Shell
mvn cds:watch
The CAP server serves all the CAP sources from your project. It also “watches” all the files in your projects and conveniently restarts whenever you save a file. Changes you’ve made are immediately served without you having to run the command again. In this newly created project the CAP server tells you that there are no models or service definitions yet that it can serve.
Here is the output that you get:
Shell
[INFO] Scanning for projects...
[INFO][INFO] --------------------< customer:incident-management >--------------------
[INFO] Building incident-management 1.0.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO][INFO] --- cds-maven-plugin:3.4.1:watch (default-cli) @ incident-management ---
[INFO] CdsMojo: building project [/home/user/projects/incident-management], clean [true]cds-dk [8.4.1], cds [8.4.1], compiler [5.4.2], home [/home/user/projects/incident-management/node_modules/@sap/cds-dk/node_modules/@sap/cds]{ build: { target: '.',
tasks: [{for: 'java', src: 'srv', options: { model: ['db', 'srv']}}]}}no CDS model found for[java] build task [/home/user/projects/incident-management/srv] - nothing to be done
The CAP server also prints a message BUILD FAILURE stating that the build has failed. After this message, the CAP server waits for any changes on the filesystem and tries a rebuild. So, let’s go on and add a domain model.
Step 2Add a domain model
+
In the db folder, create a new schema.cds file.
Paste the following code snippet in the schema.cds file.
CDS
using{cuid,managed,sap.common.CodeList}from'@sap/cds/common';namespacesap.capire.incidents;/**
* Incidents created by Customers.
*/entityIncidents:cuid,managed{customer:AssociationtoCustomers;title:String@title:'Title';urgency:AssociationtoUrgencydefault'M';status:AssociationtoStatusdefault'N';conversation:Compositionofmany{keyID:UUID;timestamp:typeofmanaged:createdAt;author:typeofmanaged:createdBy;message:String;};}/**
* Customers entitled to create support Incidents.
*/entityCustomers:managed{keyID:String;firstName:String;lastName:String;name:String=trim(firstName||' '||lastName);email:EMailAddress;phone:PhoneNumber;incidents:AssociationtomanyIncidentsonincidents.customer=$self;creditCardNo:String(16)@assert.format:'^[1-9]\d{15}$';addresses:CompositionofmanyAddressesonaddresses.customer=$self;}entityAddresses:cuid,managed{customer:AssociationtoCustomers;city:String;postCode:String;streetAddress:String;}entityStatus:CodeList{keycode:Stringenum{new='N';assigned='A';in_process='I';on_hold='H';resolved='R';closed='C';};criticality:Integer;}entityUrgency:CodeList{keycode:Stringenum{high='H';medium='M';low='L';};}typeEMailAddress:String;typePhoneNumber:String;
What happens here?
The provided CDS code snippet defines several entities and their relationships.
The Incidents entity represents incidents created by customers, with fields for customer, title, urgency, status, and a composition of many conversations. Each conversation has an ID, timestamp, author, and message.
The Customers entity represents customers who can create support incidents. It includes fields for ID, first name, last name, e-mail, phone, credit card number, and a composition of many addresses. The name field is calculated from the firstName and lastName fields. Elements can be specified with a calculation expression, in which you can refer to other elements of the same entity. These calculated elements are used for convenience. For more information, see Calculated Elements.
The Addresses entity represents the addresses of customers, with fields for customer, city, postcode, and street address.
The Status and Urgency entities represent the status and urgency of incidents, respectively. Both are of type CodeList and include a code field with a set of predefined values.
The EMailAddress and PhoneNumber are defined as types of String.
The code also includes the use of cuid and managed from @sap/cds/common, which are common features for defining entities in CDS. The cuid feature provides a unique identifier for an entity, while managed adds common administrative fields such as createdAt and createdBy.
As soon as you paste the code in your newly created file, the CAP server that is still running reacts immediately with a new output:
Shell
[cds] - loaded model from 2 file(s): db/schema.cds <path-to>/node_modules/@sap/cds/common.cds[cds] - connect using bindings from: { registry: '~/.cds-services.json' }[cds] - connect to db > sqlite { url: ':memory:' }/> successfully deployed to in-memory database.
This output means that the CAP server detected the changes in schema.cds and automatically created an in-memory SQLite database when restarting the server process. However, the CAP server also prints this message:
Shell
No service definitions found in loaded models.
Waiting for some to arrive...
At this stage, the CAP server that is still running detects the changes in schema.cds and automatically creates an in-memory SQLite database when restarting the server process. However, there are still no service definitions.
Step 3Create services
+
It’s a good practice in CAP to create single-purposed services. Therefore, let’s define a ProcessorService that support engineers use to process incidents created by customers. Let’s also define an AdminService that administrators use to perform admin activities such as analyzing audit logs.
To create the services’ definition:
In the srv folder, create a new services.cds file.
Paste the following code snippet in the services.cds file:
CDS
using {sap.capire.incidents as my} from '../db/schema';/** * Service used by support personell, i.e. the incidents' 'processors'. */service ProcessorService { entity Incidents as projection on my.Incidents; @readonly entity Customers as projection on my.Customers;}/** * Service used by administrators to manage customers and incidents. */service AdminService { entity Customers as projection on my.Customers; entity Incidents as projection on my.Incidents;}
This time, the CAP server reacted with additional output:
Shell
[cds] - serving ProcessorService { path: '/odata/v4/processor'}[cds] - serving AdminService { path: '/odata/v4/admin'}[cds] - server listening on { url: 'http://localhost:4004'}[cds] - [ terminate with ^C ]
As you can see in the log output, the new file created two generic service providers: ProcessorService that serves requests on the /odata/v4/processor endpoint and AdminService that serves requests on the /odata/v4/admin endpoint. If you open the link http://localhost:4004 from SAP Business Application Studio in your browser, you see the generic index.html page:
index.html
You have to stop the CAP server with Ctrl + C and start it again with the cds watch command.
In the srv folder, create a new services.cds file.
Paste the following code snippet in the services.cds file:
CDS
using { sap.capire.incidents as my } from '../db/schema';/** * Service used by support personell, i.e. the incidents' 'processors'. */service ProcessorService { entity Incidents as projection on my.Incidents; @readonly entity Customers as projection on my.Customers;}/** * Service used by administrators to manage customers and incidents. */service AdminService { entity Customers as projection on my.Customers; entity Incidents as projection on my.Incidents; }
This time, the CAP server reacted with additional output:
Shell
2024-12-06T14:02:29.740Z INFO 10998 --- [ restartedMain] c.s.c.services.impl.ServiceCatalogImpl : Registered service AdminService
2024-12-06T14:02:29.742Z INFO 10998 --- [ restartedMain] c.s.c.services.impl.ServiceCatalogImpl : Registered service ProcessorService
2024-12-06T14:02:29.743Z INFO 10998 --- [ restartedMain] .s.c.r.CdsRuntimeBeanDefinitionRegistrar : Auto-configuration of DataSource beans is explicitly disabled.
2024-12-06T14:02:30.161Z INFO 10998 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080(http)2024-12-06T14:02:30.175Z INFO 10998 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]2024-12-06T14:02:30.175Z INFO 10998 --- [ restartedMain] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.31]2024-12-06T14:02:30.199Z INFO 10998 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2024-12-06T14:02:30.199Z INFO 10998 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 944 ms
2024-12-06T14:02:30.217Z INFO 10998 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2024-12-06T14:02:30.339Z INFO 10998 --- [ restartedMain] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:ef5eb10f-0fc9-413e-9358-0c9e2365c3aa user=SA
2024-12-06T14:02:30.340Z INFO 10998 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2024-12-06T14:02:30.348Z INFO 10998 --- [ restartedMain] o.s.b.a.h2.H2ConsoleAutoConfiguration : H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:ef5eb10f-0fc9-413e-9358-0c9e2365c3aa'2024-12-06T14:02:30.388Z INFO 10998 --- [ restartedMain] c.s.c.f.s.c.adapter.AdapterBeanFactory : Servlet CdsODataV4Servlet mapped to /odata/v4
2024-12-06T14:02:30.391Z INFO 10998 --- [ restartedMain] c.s.c.f.s.c.adapter.AdapterBeanFactory : Servlet IndexPageServlet mapped to /
2024-12-06T14:02:30.393Z INFO 10998 --- [ restartedMain] c.s.c.f.s.c.adapter.AdapterBeanFactory : Servlet CdsFioriPreviewServlet mapped to /$fiori-preview
2024-12-06T14:02:30.573Z INFO 10998 --- [ restartedMain] c.s.c.services.impl.ServiceCatalogImpl : Registered service PersistenceService$Default2024-12-06T14:02:30.614Z INFO 10998 --- [ restartedMain] .s.c.a.o.v.m.p.EdmxProviderConfiguration : Initialized Default EDMX V4 Provider
2024-12-06T14:02:30.619Z INFO 10998 --- [ restartedMain] .s.c.a.o.v.m.p.EdmxProviderConfiguration : Initialized Default EDMX I18n Provider
2024-12-06T14:02:30.650Z INFO 10998 --- [ restartedMain] c.sap.cds.services.impl.utils.BuildInfo : git.commit.id: 9d82be78fe5d02e889632e16057953cbfc609d5b
2024-12-06T14:02:30.650Z INFO 10998 --- [ restartedMain] c.sap.cds.services.impl.utils.BuildInfo : maven.version: 3.4.1
2024-12-06T14:02:30.689Z INFO 10998 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 357292024-12-06T14:02:30.703Z INFO 10998 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080(http) with context path '/'2024-12-06T14:02:30.709Z INFO 10998 --- [ restartedMain] c.incident_management.Application : Started Application in 1.725 seconds (process running for 2.035)
You can see in the log output, the new file created two generic service providers: ProcessorService and AdminService.
In the bottom right of your SAP Business Application Studio window, look for the popup A service is listening to port 8080.
Choose Open in a New Tab.
Open in a new tab
You see the generic index.html page:
index.html
You need to stop the CAP server with Ctrl + C and start it again with the mvn cds:watch command.
Since we already have an SQLite in-memory database that was automatically created in the previous step, let’s now fill it with initial data.
Run the following command in the incident-management root folder of your project:
Shell
cds add data
Check the output.
Shell
Adding feature 'data'...
Creating db/data/sap.capire.incidents-Addresses.csv
Creating db/data/sap.capire.incidents-Customers.csv
Creating db/data/sap.capire.incidents-Incidents.csv
Creating db/data/sap.capire.incidents-Incidents.conversation.csv
Creating db/data/sap.capire.incidents-Status.csv
Creating db/data/sap.capire.incidents-Status.texts.csv
Creating db/data/sap.capire.incidents-Urgency.csv
Creating db/data/sap.capire.incidents-Urgency.texts.csv
Successfully added features to your project.
You can find the generated CSV templates within the db folder, in a newly created data folder.
Step 5Fill in the initial data
+
Important distinction between initial data and test data
You need to distinguish between (real) initial data meant for production (configuration, code lists) and test data meant for development and testing purposes only. For more information, see Initial vs Test Data.
Replace the respective generated CSV templates with the following content:
db/data/sap.capire.incidents-Addresses.csv:
CSV
ID,customer_ID,city,postCode,streetAddress
17e00347-dc7e-4ca9-9c5d-06ccef69f064,1004155,Rome,00164,Piazza Adriana
d8e797d9-6507-4aaa-b43f-5d2301df5135,1004161,Munich,80809,Olympia Park
ff13d2fa-e00f-4ee5-951c-3303f490777b,1004100,Walldorf,69190,Dietmar-Hopp-Allee
ID,up__ID,timestamp,author,message
2b23bb4b-4ac7-4a24-ac02-aa10cabd842c,3b23bb4b-4ac7-4a24-ac02-aa10cabd842c,1995-12-17T03:24:00Z,Harry John,Can you please check if battery connections are fine?
2b23bb4b-4ac7-4a24-ac02-aa10cabd843c,3a4ede72-244a-4f5f-8efa-b17e032d01ee,1995-12-18T04:24:00Z,Emily Elizabeth,Can you please check if there are any loose connections?
9583f982-d7df-4aad-ab26-301d4a157cd7,3583f982-d7df-4aad-ab26-301d4a157cd7,2022-09-04T12:00:00Z,Sunny Sunshine,Please check why the solar panel is broken.
9583f982-d7df-4aad-ab26-301d4a158cd7,3ccf474c-3881-44b7-99fb-59a2a4668418,2022-09-04T13:00:00Z,Bradley Flowers,What exactly is wrong?
db/data/sap.capire.incidents-Incidents.csv:
CSV
ID,customer_ID,title,urgency_code,status_code
3b23bb4b-4ac7-4a24-ac02-aa10cabd842c,1004155,Inverter not functional,H,C
3a4ede72-244a-4f5f-8efa-b17e032d01ee,1004161,No current on a sunny day,H,N
3ccf474c-3881-44b7-99fb-59a2a4668418,1004161,Strange noise when switching off Inverter,M,N
3583f982-d7df-4aad-ab26-301d4a157cd7,1004100,Solar panel broken,H,I
Notice that cds add data created eight files, while we’re adding data to just six of them. We’re leaving the files sap.capire.incidents-Status.texts.csv and sap.capire.incidents-Urgency.texts.csv empty because they hold translated text that are filled once the application is localized and translations are created.
Upon detecting these new files, the CAP server prints a message stating that the content of the files has been filled into the database automatically:
Shell
[cds] - connect to db > sqlite { database: ':memory:'} > init from db\data\sap.capire.incidents-Addresses.csv
> init from db\data\sap.capire.incidents-Customers.csv
> init from db\data\sap.capire.incidents-Incidents.csv
> init from db\data\sap.capire.incidents-Incidents.conversation.csv
> init from db\data\sap.capire.incidents-Status.csv
> init from db\data\sap.capire.incidents-Status.texts.csv
> init from db\data\sap.capire.incidents-Urgency.csv
> init from db\data\sap.capire.incidents-Urgency.texts.csv
/> successfully deployed to in-memory database.
Make sure that your CAP server is still running. You can start it with cds watch.
Now that the database is filled with some initial data, you can send complex OData queries served by the built-in generic service providers. With the generic index.html page opened in your browser, paste the following queries at the end of the current URL and check the result:
2024-12-06T14:12:46.228Z INFO 10998 --- [ restartedMain] c.s.c.s.impl.persistence.CsvDataLoader : Filling sap.capire.incidents.Incidents.conversation from ../db/data/sap.capire.incidents-Incidents.conversation.csv
2024-12-06T14:12:46.229Z INFO 10998 --- [ restartedMain] c.s.c.s.impl.persistence.CsvDataLoader : Filling sap.capire.incidents.Incidents from ../db/data/sap.capire.incidents-Incidents.csv
2024-12-06T14:12:46.230Z INFO 10998 --- [ restartedMain] c.s.c.s.impl.persistence.CsvDataLoader : Filling sap.capire.incidents.Customers from ../db/data/sap.capire.incidents-Customers.csv
2024-12-06T14:12:46.231Z INFO 10998 --- [ restartedMain] c.s.c.s.impl.persistence.CsvDataLoader : Filling sap.capire.incidents.Status from ../db/data/sap.capire.incidents-Status.csv
2024-12-06T14:12:46.232Z INFO 10998 --- [ restartedMain] c.s.c.s.impl.persistence.CsvDataLoader : Filling sap.capire.incidents.Addresses from ../db/data/sap.capire.incidents-Addresses.csv
2024-12-06T14:12:46.233Z INFO 10998 --- [ restartedMain] c.s.c.s.impl.persistence.CsvDataLoader : Filling sap.capire.incidents.Urgency from ../db/data/sap.capire.incidents-Urgency.csv
2024-12-06T14:12:46.244Z INFO 10998 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 357292024-12-06T14:12:46.249Z INFO 10998 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080(http) with context path '/'2024-12-06T14:12:46.250Z INFO 10998 --- [ restartedMain] c.incident_management.Application : Started Application in 0.211 seconds (process running for 617.577)
Make sure that your CAP server is still running. You can start it with mvn cds:watch.
Now that the database is filled with some initial data, you can send complex OData queries served by the built-in generic service providers. With the generic index.html page opened in your browser, paste the following queries at the end of the current URL and check the result:
When you revisit the Incidents or the Customers endpoint, you see unformatted data instead of the nicely formatted output from above.
No JSON Viewer
However, unformatted data doesn’t mean you’ve made a mistake in the tutorial. Rather, this is the correct output without any formatting. If you’d like to see a formatted output in your browser, you can add an extension to your browser. Here are a few exemplary JSON formatters for different browsers:
Share feedback on this tutorial or join the conversation in SAP Community.
Submit detailed feedbackDiscuss in Community
Steps
Step 1 of 5
1. Create a CAP project2. Add a domain model3. Create services4. Generate comma-separated values (CSV) templates5. Fill in the initial data
Joule
AI Notice
Joule is an AI assistant. Generative AI may produce inaccurate, incomplete, or biased information. Always verify important details before acting on them.
Conversations are sent to SAP-hosted large language models for processing. Do not include personal data, credentials, or confidential information in your messages.
Joule's responses are based on the SAP tutorial catalog and may not reflect the latest product changes. For authoritative guidance, consult the linked tutorials and official SAP documentation.