- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
Wednesday
When you build ERP-style extensions, it’s common to have data and logic running in SAP (or any OData-compatible backend) and workflows running on ServiceNow. In my case, I used SAP Cloud Application Programming (CAP) to expose an OData V2 service. Then I wired it to ServiceNow using a small SAPUI5 app that communicates with both the CAP OData endpoint and the ServiceNow Table API.
In this blog, I’ll walk through a simple end-to-end example so you can adapt it for your own ERP Canvas or custom apps.
Prerequisites
- Basic familiarity with CAP (Node.js flavor).
- A ServiceNow instance with a table you can write to (or a POC table).
- SAPUI5 or Fiori tooling (Business Application Studio, VS Code with UI5 tooling, etc.).
Scenario Overview
The architecture has three main pieces:
- CAP service
- Exposes an OData V2 endpoint
- Contains an entity for CRUD example
- ServiceNow Table API
- REST endpoint to insert records to ServiceNow table
- UI5 App (Bridge)
- Uses CAP OData as default model
- Uses JSON model to call ServiceNow REST API
Goal: Post records into CAP OData and ServiceNow from a single UI.
STEP 1 – Create and expose your CAP OData service
- Initialise project:
cds init cap-odata-servicenow cd cap-odata-servicenow - Define a simple data model in db/schema.cds:
namespace demo; entity Products { key ID : UUID; Name : String(111); Description : String(255); ReleaseDate : Date; Price : Decimal(9,2); Rating : Integer; } - Expose it via service in srv/service.cds:
using demo from '../db/schema'; service CatalogService { entity Products as projection on demo.Products; } - Enable OData V2 compatibility (optional but useful when integrating with tools expecting V2):
npm install /cds-odata-v2-adapter-proxy
Wire the adapter into your server.js (or equivalent) so that V2/OData/OData.svc serves the V2 endpoint.
- Run the CAP app locally:
cds watch
URL generated (example): http://localhost:4004/V2/OData/OData.svc/
STEP 2 – Create UI5 app and consume both systems
Next, create a small SAPUI5/Fiori app. In my project, the manifest defines two data sources:
- serviceNowService – the CAP OData V2 endpoint.
- mainService – the ServiceNow Table API.
An excerpt from manifest.json looks like this:
"dataSources": {
"serviceNowService": {
"uri": "/V2/OData/OData.svc/",
"type": "OData",
"settings": {
"annotations": [],
"localUri": "localService/serviceNowService/metadata.xml",
"odataVersion": "2.0"
}
},
"mainService": {
"uri": "/api/now/table/sn_hr_core_saps4hanapoc_import",
"type": "REST"
}
},
"models": {
"": {
"dataSource": "serviceNowService",
"preload": true,
"settings": {}
},
"serviceNowRest": {
"type": "sap.ui.model.json.JSONModel",
"uri": "/api/now/table/<table_name>"
}
}
A few key points:
- The default model ("") is an OData model bound to serviceNowService (your CAP OData service).
- The serviceNowRest model is a JSONModel pointing to the ServiceNow Table API endpoint.
- This lets the same app talk to both systems: OData via the default model and REST via the JSON model.
STEP 3 – Controller logic to POST data
In the main view controller (View1.controller.js), I implemented two handlers:
- onPostOData – Posts a new Products entry to the CAP OData service.
- onPostServiceNowRest – Posts an HR import row to the ServiceNow table via REST.
Here is the core logic (simplified) from View1.controller.js:
onPostOData: function () {
var oModel = this.getView().getModel(); // default OData model
var oEntry = {
Name: "New Product",
Description: "Sample Description",
ReleaseDate: "/Date(1622505600000)/",
Price: 99.99,
Rating: 5
};
oModel.create("/Products", oEntry, {
success: function (oData, response) {
MessageToast.show("Product created successfully! (Status: " + response.statusCode + ")");
},
error: function (oError) {
var statusCode = oError.statusCode || (oError.response && oError.response.statusCode) || "Unknown";
MessageToast.show("Error creating Products. (Status: " + statusCode + ")");
}
});
},
This is enough for a working E2E proof of concept:
- Click “Create Product” → data goes to CAP OData.
- Click “Create HR Import Row” → data goes to ServiceNow Table API.
STEP 4 – Run UI and verify
- In your XML view, add two buttons and bind them to the controller methods:
<Button text="Post to OData" press=".onPostOData" /> <Button text="Post to ServiceNow" press=".onPostServiceNowRest" /> - Run the UI5 app (e.g. npm start or via ui5 serve depending on your tooling).
- Open the app in the browser and try both buttons:
- Validate that CAP receives and persists the Products record.
- Verify in ServiceNow that a new row was inserted into your table.
Once this works locally, you can deploy:
- CAP service → SAP BTP (or another Node runtime).
- UI5 app → wherever you host your Fiori/UI5 apps.
- Ensure the URLs and destinations are adjusted accordingly.
STEP 5 – Extending into ERP Canvas
In more advanced scenarios, you can:
- If you want to create/read/update data in SAP using an exposed OData v2 endpoint, use Zero Copy Connector for ERP to model operations over the CAP OData service (for example, using a “Model creation using OData Service” pattern similar to other ServiceNow guides). ServiceNow
- Use the CAP OData service as your SAP-side abstraction and the ServiceNow Table API as your workflow/case-management side.
- Keep your CAP logic focused on data & business rules, and let ServiceNow handle approvals, tasks, and notifications.
The simple UI5 bridge shown here is mainly for:
- Prototyping end-to-end flows.
- Testing connectivity and payloads.
- Providing a reference for how CAP OData and ServiceNow REST can be used together.
Tips:
- Use OAuth/credentials for ServiceNow securely
- Add error logging when scaling production use
- Maintain consistent field mapping between SAP ⇆ SNOW
Conclusion
We successfully connected the CAP OData service with ServiceNow using a UI5 application. This flexible architecture enables bi-directional integration, real-time data operations, and plug-in to ERP Canvas or automation frameworks. This serves as an excellent boilerplate for larger projects.