SAP Cloud Application Programming Model (CAP), BTP üzerinde cloud-native uygulama geliştirmek için tasarlanmış açık kaynaklı bir framework. Node.js veya Java ile yazılabilen, CDS tabanlı şema tanımı, otomatik OData servisleri ve HANA Cloud entegrasyonuyla — SAP ekosistemi için Spring Boot benzeri bir deneyim sunuyor.
CAP mı RAP mı?
Projede sık karşılaştığımız soru bu. İkisi de CDS kullanıyor ve OData üretiyor, ama çalıştıkları ortam ve hedefleri farklı:
| RAP | CAP | |
|---|---|---|
| Çalıştığı ortam | S/4HANA backend (ABAP) | BTP — Cloud Foundry veya Kyma |
| Runtime | ABAP | Node.js veya Java |
| Kullanım | In-app extension | Side-by-side extension, özgün uygulama |
| Veri | SAP tabloları (HANA) | Özgün model veya remote service |
| OData versiyonu | V4 (otomatik) | V4 veya V2 (yapılandırılabilir) |
Pratik kural: S/4HANA'nın içini değiştiriyorsanız → RAP. BTP'de yeni bir uygulama veya S/4HANA'yı dışarıdan genişletiyorsanız → CAP.
Proje Yapısı
my-cap-app/
├── db/
│ └── schema.cds # Veri modeli (entities, types, aspects)
├── srv/
│ ├── orders-service.cds # Servis tanımı
│ └── orders-service.js # Node.js handler (veya .java)
├── app/ # Opsiyonel: Fiori/UI5 uygulaması
├── test/ # Jest veya JUnit testleri
├── .cdsrc.json # CAP yapılandırması
└── package.json
CDS Data Model
CAP'ta her şey şemayla başlar. managed aspect, otomatik olarak createdAt, createdBy, modifiedAt, modifiedBy alanlarını ekler.
// db/schema.cds
namespace tdev.orders;
entity Orders : managed {
key ID : UUID;
customer : String(100) @mandatory;
date : Date;
status : String(20) default 'OPEN'
@assert.range enum { OPEN; CONFIRMED; CLOSED; };
items : Composition of many OrderItems on items.order = $self;
}
entity OrderItems {
key ID : UUID;
order : Association to Orders;
product : String(100);
quantity : Integer @assert.range: [1, 9999];
price : Decimal(13,2);
total : Decimal(13,2); // virtual — handler hesaplıyor
}
Servis Tanımı
// srv/orders-service.cds
using tdev.orders from '../db/schema';
@path: '/orders'
service OrdersService {
@Capabilities: {
Insertable: true,
Updatable: true,
Deletable: true
}
entity Orders as projection on orders.Orders;
entity OrderItems as projection on orders.OrderItems;
/** Özel action: tüm siparişi kapat */
action closeOrder(orderID: UUID) returns Orders;
/** Aylık sipariş özeti */
function monthlySummary(year: Integer, month: Integer)
returns array of { month: String; total: Decimal; count: Integer; };
}
Service Handler (Node.js)
// srv/orders-service.js
const cds = require('@sap/cds')
module.exports = class OrdersService extends cds.ApplicationService {
async init() {
const { Orders, OrderItems } = this.entities
// CREATE öncesi validasyon
this.before('CREATE', Orders, async (req) => {
const { customer, date } = req.data
if (!customer?.trim()) {
return req.reject(400, 'Müşteri adı boş olamaz')
}
if (date && new Date(date) < new Date()) {
return req.reject(400, 'Sipariş tarihi geçmişte olamaz')
}
})
// READ sonrası hesaplanan alan
this.after('READ', OrderItems, (items) => {
items.forEach(item => {
item.total = (item.quantity ?? 0) * (item.price ?? 0)
})
})
// Custom action
this.on('closeOrder', async (req) => {
const { orderID } = req.data
const count = await UPDATE(Orders)
.set({ status: 'CLOSED' })
.where({ ID: orderID, status: { '!=': 'CLOSED' } })
if (!count) req.reject(404, `Sipariş bulunamadı: ${orderID}`)
return SELECT.one(Orders).where({ ID: orderID })
})
return super.init()
}
}
Hybrid Development
CAP'ın en değerli özelliklerinden biri: lokal geliştirmede SQLite (hatta in-memory), üretimde HANA Cloud. Geçiş için tek satır config değişikliği yeterli.
// .cdsrc.json
{
"requires": {
"[development]": {
"db": {
"kind": "sqlite",
"credentials": { "url": ":memory:" }
}
},
"[production]": {
"db": { "kind": "hana-cloud" }
}
}
}
# Geliştirme: in-memory SQLite, hot reload
cds watch
# HANA Cloud'a deploy
cds deploy --to hana
# MTA ile BTP'ye deploy (önerilen)
mbt build
cf deploy mta_archives/my-cap-app.mtar
S/4HANA Remote Service Entegrasyonu
BTP'deki CAP uygulamasından S/4HANA verisi okumak için SAP Cloud SDK ve destination hizmeti kullanılır. CAP bu karmaşıklığı büyük ölçüde soyutluyor:
// package.json — cds.requires bölümü
{
"cds": {
"requires": {
"S4SalesOrder": {
"kind": "odata-v4",
"model": "srv/external/API_SALES_ORDER_SRV",
"credentials": {
"destination": "S4HANA_SYSTEM",
"requestTimeout": 30000
}
}
}
}
}
// srv/orders-service.js — remote service kullanımı
const s4 = await cds.connect.to('S4SalesOrder')
this.on('READ', 'RemoteSalesOrders', async (req) => {
// CAP OData sorgusunu S/4HANA'ya iletir
return s4.run(req.query)
})
// Hybrid: lokal ve remote verini birleştirme
this.on('READ', Orders, async (req) => {
const [local, remote] = await Promise.all([
SELECT.from(Orders).where(req.query.SELECT.where),
s4.run(SELECT.from('A_SalesOrder'))
])
// merge logic...
})
Yerel test için mocking: cds watch --profile hybrid ile uzak servisleri gerçek sistemden, yerel DB'yi SQLite'dan kullanabilirsiniz. cds mock S4SalesOrder ile de fixture verisiyle tam offline çalışabilirsiniz.
Authorization
CAP, role-based authorization'ı CDS annotation seviyesinde destekler. XSUAA ile entegre çalışır:
// srv/orders-service.cds
service OrdersService @(requires: 'authenticated-user') {
@restrict: [
{ grant: 'READ', to: 'OrderViewer' },
{ grant: ['CREATE','UPDATE'], to: 'OrderEditor' },
{ grant: '*', to: 'OrderAdmin' }
]
entity Orders as projection on orders.Orders;
@restrict: [{ grant: 'closeOrder', to: 'OrderAdmin' }]
action closeOrder(orderID: UUID) returns Orders;
}
Multi-Tenancy
Birden fazla müşteriye sunan SaaS uygulamaları için @sap/cds-mtxs paketi ile multi-tenancy etkinleştirilir. Tenant onboarding, schema isolation ve metadata extensibility framework tarafından yönetilir:
// .cdsrc.json
{
"requires": {
"multitenancy": true,
"extensibility": true,
"cds.xt.SaasProvisioningService": { "kind": "mtx" }
},
"mtx": {
"element-prefix": "Z_",
"namespace-blocklist": []
}
}
CAP'ı Olgunlaştıran Özellikler
2024–2025 itibarıyla CAP ekosistemi önemli eklentilerle güçlendi:
- @cap-js/attachments — dosya yükleme, SAP Document Management entegrasyonu
- @cap-js/sdm — SAP Document Management Service adaptörü
- @cap-js/audit-logging — kişisel veri erişim kaydı (GDPR)
- @sap-ai-sdk/core — Generative AI Hub entegrasyonu, LLM çağrıları
- CAP Telemetry — OpenTelemetry ile BTP Application Logging entegrasyonu
CAP, BTP üzerindeki uygulama geliştirmede artık bir tercih değil, defacto standart. Özellikle S/4HANA'yı dışarıdan genişletmek veya tamamen bağımsız BTP uygulamaları geliştirmek için olgunluğu ve ekosistemi her geçen çeyrekte güçleniyor.