npm i -g @sap/cds-dk
VSCode Pluging : Java Extension Pack
VSCode Pluging : Language support for Java ™ for Visual Studio Code
VSCode Pluging: SAP Cloud Platform core data services plug-in for Visual Studio Code
VSCode Pluging: vscode-sqlite
VSCode Pluging: Debugger for Java
java --version
mvn -version
node -version
mvn -B archetype:generate \
-DarchetypeArtifactId=cds-services-archetype \
-DarchetypeGroupId=com.sap.cds \
-DarchetypeVersion=RELEASE \
-DgroupId=com.sap.cap \
-DartifactId=products-service \
-Dpackage=com.sap.cap.productsservice
products-service
db
folder stores database-related artifactssrv
folder stores your Java applicationIt means define a service AdminService contains domain model Products
service AdminService {
entity Products {
key ID : Integer;
title : String(111);
descr : String(1111);
}
}
mvn clean install
srv/src/main/resources/edmx
folder. This is the default path, where CAP Java runtime looks for the model definitions.mvn clean spring-boot:run
handlers
under srv/src/main/java/com/sap/cap/productsservice
AdminService.java
in the created handlers
folder, with the following content package com.sap.cap.productsservice.handlers;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Component;
import com.sap.cds.services.cds.CdsCreateEventContext;
import com.sap.cds.services.cds.CdsReadEventContext;
import com.sap.cds.services.cds.CdsService;
import com.sap.cds.services.handler.EventHandler;
import com.sap.cds.services.handler.annotations.On;
import com.sap.cds.services.handler.annotations.ServiceName;
@Component
@ServiceName("AdminService")
public class AdminService implements EventHandler {
private Map<Object, Map<String, Object>> products = new HashMap<>();
@On(event = CdsService.EVENT_CREATE, entity = "AdminService.Products")
public void onCreate(CdsCreateEventContext context) {
context.getCqn().entries().forEach(e -> products.put(e.get("ID"), e));
context.setResult(context.getCqn().entries());
}
@On(event = CdsService.EVENT_READ, entity = "AdminService.Products")
public void onRead(CdsReadEventContext context) {
context.setResult(products.values());
}
}
READ
and CREATE
events that target the Products
entity of the AdminService
.READ
operation just returns all entities kept in memory.CREATE
event extracts the payload from the CQN representation and stores it in memory.EventHandler
and register themselves as Spring Beans (@Component
). The marker interface is important, because it enables the CAP Java runtime to identify these classes among all Spring Beans.@On
, @Before
, or @After
annotations. Every event, such as an entity creation, runs through these three phases. Each phase has a slightly different semantic. You’ll learn more about these semantics in the subsequent tutorial.@ServiceName
specifies the default service name all event handler methods apply to. Here this is AdminService
, as this was also the name when defining the service in the CDS model.CdsCreateEventContext context
parameter. The event we’re extending is the CREATE
event. The type of the context variable is specific to this extended CREATE
event. The onCreate
method returns void
, as the result is set by running: context.setResult(…)
.mvn clean spring-boot: run
curl -X POST http://localhost:8080/odata/v4/AdminService/Products \
-H "Content-Type: application/json" \
-d '{"ID": 42, "title": "My Tutorial Product", "descr": "You are doing an awesome job!"}'
namespace sap.capire.products;
using { Currency, cuid, managed, sap.common.CodeList } from '@sap/cds/common';
entity Products : cuid, managed {
title : localized String(111);
descr : localized String(1111);
stock : Integer;
price : Decimal(9,2);
currency : Currency;
category : Association to Categories;
}
entity Categories : CodeList {
key ID : Integer;
parent : Association to Categories;
children : Composition of many Categories on children.parent = $self;
}
@Sisn/cds/common
package (a globally available reuse package):Currency
cuid
managed
CodeList
localized
Keywordlocalized
keyword can be used to mark elements, which require translation. The ability to store translations for different languages and to store a default fallback translation is automatically handled by CDS for you. You will see this in action in more detail in the next tutorial.deep inserts
and upserts
along these structures.Categories
entities define a parent
and children
element. This enables a hierarchy of categories. The children of a category are modelled as a composition. A category with all of its children defines a deep nested structure. Deleting a category would automatically delete all of its children. However, the parent of a category is modelled as an association. Deleting a category obviously shouldn’t delete its parent.cuid
and managed
Aspectscuid
and managed
are aspects. Aspects extend an entity with additional elements. The cuid
aspect adds a key
element ID
of type UUID
to the entity.managed
aspect adds four additional elements to the entity. These capture the time of the creation and last update of the entity, and the user, which performed the creation and last update.CodeList
Aspect and the Currency
TypeCodeLists
can be used to store global, translatable definitions based on codes, such as currencies, countries, or languages. Especially for UIs, a CodeList
can be useful to provide a value help for certain input fields.Currency
definition is a type. It defines an association to a Currencies
entity. The Currencies
entity is based on ISO 4217 and uses three-letter alpha codes as keys such as EUR
or USD
and provides the possibility to store the corresponding currency symbol such as €
or $
.AdminService
, which directly defined the entity Products
. As you now have defined the Products
entity in your domain model, the AdminService
just needs to expose it. In addition, you defined the Categories
entity, which should also be part of your service.using { sap.capire.products as db } from '../db/schema';
service AdminService {
entity Products as projection on db.Products;
entity Categories as projection on db.Categories;
}
npm install --save-dev sqlite3
cds deploy --to sqlite
srv/src/main/resources
, locate, and open the application.yaml
file. This file was created when you initialized the application.---
spring:
profiles: sqlite
datasource:
url: "jdbc:sqlite:/Users/{youruser}/Documents/workspace/products-service/sqlite.db"
driver-class-name: org.sqlite.JDBC
initialization-mode: never
hikari:
maximum-pool-size: 1
AdminService
will be automatically served via OData and you can just delete the AdminService.java
file that was created earlier.AdminService.java
file in the handlers
folder.mvn spring-boot:run
mvn spring-boot:run -Dspring-boot.run.profiles=sqlite
curl -X POST http://localhost:8080/odata/v4/AdminService/Categories \
-H "Content-Type: application/json" \
-d '{"ID": 1, "name": "TechEd", "descr": "TechEd related topics", "children": [{"ID": 10, "name": "CAP Java", "descr": "Run on Java"}, {"ID": 11, "name": "CAP Node.js", "descr": "Run on Node.js"}]}'
products-service
application for reuse.products-service
reuse module, should be @Sisn/capire-products
index.cds
file can be added to the products-service
. This ensures a better decoupling from other applications.index.cds
in the ~/projects/products-service
folder and place the following content inside this fileusing from './db/schema';
using from './srv/admin-service';
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
23 | |
11 | |
10 | |
8 | |
8 | |
6 | |
6 | |
6 | |
5 | |
5 |