OData Services in S/4HANA: SEGW, RAP, CRUD Operations & Postman Testing – Hands-On API Tutorial | Part 38 | FreeLearning365

  

OData Services in S/4HANA: SEGW, RAP, CRUD Operations & Postman Testing – Hands-On API Tutorial | Part 38 | FreeLearning365


OData Services in S/4HANA – Building & Exposing APIs via SEGW and RAP: A 25,000+ Word Hands-On Masterclass

Day 8 of the S/4HANA ABAP Development & Fiori Track

By @FreeLearning365 and Tech Partner @techbook24

Introduction: The API That Unlocked the Business

TechBook24's e-commerce platform is booming. The sales portal now needs to automatically create purchase orders in SAP when inventory drops below a threshold — no human intervention, no SAP GUI, just a clean, secure API call. The external system is a Node.js application running on Azure; it speaks RESTful JSON. SAP's answer is OData — a standardized protocol for building and consuming REST APIs that's deeply integrated into S/4HANA.

Arjun gets the assignment: expose a service that allows the portal to create a purchase order with all its items in a single call, retrieve order details, update them, and delete if needed. He must also ensure proper error handling and test it end-to-end before handing it over. In this tutorial, you'll join him in building this API from the ground up using both the traditional SEGW approach (OData v2) and the modern RAP framework (OData v4). You'll understand the architecture, write all the necessary ABAP code, and test everything with Postman. By the end, you'll have a complete, running OData service that mirrors real-world production APIs. Let's get started.

1. The OData Ecosystem in SAP – Gateway, SEGW, and RAP

1.1 What Is OData?

OData (Open Data Protocol) is an OASIS standard that defines a set of best practices for building and consuming RESTful APIs. It uses HTTP methods (GET, POST, PUT, DELETE) and returns data in JSON or XML format. SAP NetWeaver Gateway is the technology that enables SAP systems to expose OData services. The central design tool for OData v2 services is the Gateway Service Builder (transaction SEGW). With the move to S/4HANA and cloud, SAP introduced the Restful ABAP Programming Model (RAP) for OData v4, which is more declarative and deeply integrated with CDS.

1.2 OData v2 vs OData v4 – When to Use What

FeatureOData v2 (SEGW)OData v4 (RAP)
MaturityVery mature, widely used in current Fiori appsStrategic direction, newer, but growing adoption
Data ModelDefined in SEGW (Entity Types, Sets)Derived from CDS views, annotations
Business LogicHand-coded in DPC/MPC classesManaged via behavior definitions (managed, unmanaged)
State ManagementStateless, requires careful handlingSupports draft and transactional consistency
Batch OperationsSupported via $batchAlso supported

TechBook24's current Fiori landscape is mostly v2, so Arjun will build the v2 service first, then demonstrate how the same functionality maps to RAP v4, ensuring future-readiness.

2. Building an OData v2 Service with SEGW – The Purchase Order API

2.1 The Data Model: Entity Types and Entity Sets

Arjun designs a simple OData model: an entity type PurchaseOrder with properties like PO number, vendor, date, total value, and a navigation property to a list of PurchaseOrderItem entities. The entity set PurchaseOrderSet represents the collection. He'll implement full CRUD on both.

Transaction: SEGW → Create Project → enter ZPO_SERVICE → Create.

  • Right-click "Data Model" → "Import" → "DDIC Structure". He imports the CDS view ZC_PO_Header_Enriched (from Part 37) as the basis for the header entity type. The system creates an entity type PurchaseOrder with the fields.
  • Similarly, import a structure for items (e.g., from CDS ZC_PurchaseOrderItem) to create entity type PurchaseOrderItem.
  • Define an association from PurchaseOrder to PurchaseOrderItem (1:n) and create the corresponding navigation property ToItems. In the item entity, create a navigation back to header: ToHeader.

Screenshot Description: SEGW Data Model view showing the entity types, properties, and navigation paths.

2.2 Service Implementation – DPC and MPC Classes

After generating runtime objects (right-click project → Generate), the system creates a data provider class (DPC) and a model provider class (MPC). The DPC is where you write the actual logic for CRUD methods. Arjun opens the DPC extension class ZCL_ZPO_SERVICE_DPC_EXT in ABAP.

The following methods must be redefined:

  • PURCHASEORDERSE_GET_ENTITY – read single PO
  • PURCHASEORDERSE_GET_ENTITYSET – read list of POs
  • PURCHASEORDERSE_CREATE_ENTITY – create PO
  • PURCHASEORDERSE_UPDATE_ENTITY – update PO
  • PURCHASEORDERSE_DELETE_ENTITY – delete PO
  • Similarly for items, but also navigation via the association.

Arjun implements GET_ENTITYSET for purchase orders:

METHOD purchaseorderse_get_entityset.
    " Use CDS view or direct SELECT
    SELECT ebeln, lifnr, vendor_name, aedat, netwr
      FROM zc_po_header_enriched
      INTO CORRESPONDING FIELDS OF TABLE @et_entityset
      UP TO @io_tech_request_context->get_top( ) ROWS
      WHERE aedat BETWEEN @iv_date_from AND @iv_date_to. " assume input parameters
  ENDMETHOD.

For CREATE_ENTITY, he needs to insert into EKKO and EKPO. This is the heart of the API. The entry data comes in parameter ER_ENTITY, which is a structure of the entity type. He maps the fields to EKKO, generates a PO number using the internal number range, and then processes items if deep insert is used. We'll handle deep insert next.

3. Deep Insert – Creating a PO with Items in One Call

3.1 The Requirement

The e-commerce portal wants to send a single POST request containing the PO header and all its items, and get back the complete created PO. This is called a "deep insert" in OData. In SEGW, when you post to an entity set and include navigation properties with inline data, the system calls the CREATE_ENTITY method of the root entity, and then you must manually handle the child entities. Arjun will implement a custom CREATE_DEEP_ENTITY method instead.

3.2 Redefining CREATE_DEEP_ENTITY

He creates the method (or redefines it in the DPC extension). The method receives IT_NAVIGATION_PATH and IO_DATA_PROVIDER. He uses the IO_DATA_PROVIDER to read the deep structure. The typical signature:

METHOD /iwbep/if_mgw_appl_srv_runtime~create_deep_entity.
    DATA: ls_header  TYPE ty_po_header,
          lt_items   TYPE TABLE OF ty_po_item,
          lv_ebeln   TYPE ebeln.
    " 1. Read the deep data
    io_data_provider->read_entry_data(
      IMPORTING es_data = ls_header ).
    io_data_provider->read_navigation_data(
      EXPORTING iv_entity_name = 'PurchaseOrderItem'
                iv_nav_prop    = 'ToItems'
      IMPORTING et_data       = lt_items ).
    " 2. Generate PO number
    CALL FUNCTION 'NUMBER_GET_NEXT'
      EXPORTING
        nr_range_nr = '01'
        object      = 'EINKBELEG'
      IMPORTING
        number      = lv_ebeln.
    " 3. Insert header into EKKO
    INSERT INTO ekko VALUES lv_ebeln, ... (mapping from ls_header).
    " 4. Insert items
    LOOP AT lt_items INTO DATA(ls_item).
      INSERT INTO ekpo VALUES lv_ebeln, ls_item-ebelp, ... .
    ENDLOOP.
    " 5. Return the created entity (with generated keys)
    COMMIT WORK AND WAIT.
    CALL METHOD super->/iwbep/if_mgw_appl_srv_runtime~create_deep_entity
      EXPORTING
        iv_entity_name          = 'PurchaseOrder'
        is_data                 = ls_header
        it_navigation_path      = it_navigation_path
        io_data_provider        = io_data_provider
        io_tech_request_context = io_tech_request_context.
  ENDMETHOD.

This is simplified; in reality, Arjun uses BAPI or standard function modules for creating POs (like BAPI_PO_CREATE1) to ensure all standard validations are executed. He calls BAPI_PO_CREATE1 and then maps the returned data. That's the production-grade approach.

3.3 Testing the Deep Insert with Postman

Arjun opens Postman. He first fetches a CSRF token (required for modifying requests) by sending a GET with the header X-CSRF-Token: Fetch to the service root. He then uses that token in subsequent POST/PUT/DELETE.

  • GET /sap/opu/odata/sap/ZPO_SERVICE/ – returns service document.
  • POST /sap/opu/odata/sap/ZPO_SERVICE/PurchaseOrderSet with a JSON body containing the header and inline items using the navigation property "ToItems".
{
  "Lifnr": "0000001000",
  "Bsart": "NB",
  "ToItems": [
    {
      "Matnr": "MAT100",
      "Menge": "10",
      "Meins": "PC"
    }
  ]
}

Screenshot Description: Postman showing the POST request with JSON body, and the response with the newly created PO number and all details, including the items expanded.

Arjun receives a 201 Created with the full PO data. The external portal can now create orders in SAP seamlessly.

4. CRUD Operations – Complete Implementation

4.1 GET_ENTITY (Read Single PO)

This method returns a single PO based on the key (EBELN). Arjun maps the keys from IT_KEY_TAB, reads EKKO, and fills the response. He also returns associated items via the navigation method TOITEMS_GET_ENTITY (or separate method). If the PO doesn't exist, he raises /iwbep/cx_mgw_busi_exception with HTTP 404.

4.2 UPDATE_ENTITY

For update, Arjun receives the key and the changed fields. He calls BAPI_PO_CHANGE to update the PO. He also handles status transitions like blocking a PO. Proper error mapping to OData exceptions ensures the client receives meaningful error messages.

4.3 DELETE_ENTITY

He uses BAPI_PO_DELETE or marks the PO for deletion (LOEKZ). The method returns 204 No Content on success.

Each operation is tested in Postman. Arjun demonstrates updating the vendor on a PO, deleting a test PO, and reading the list with $filter, $orderby, and $expand.

5. $expand and Query Options

OData provides powerful query options: $expand to include related entities, $filter, $orderby, $top, $skip. Arjun enables these by implementing the corresponding methods. For $expand, when a request includes ?$expand=ToItems, the DPC framework calls the navigation method for items. He ensures that the method uses the provided keys and returns the item set.

He tests: GET .../PurchaseOrderSet('4500000123')?$expand=ToItems. Response includes both header and item array. This reduces round trips for the client.

Screenshot Description: Postman response showing a PO with nested items array from $expand.

6. Error Handling – Meaningful Messages, Correct HTTP Codes

6.1 Using Message Classes and Exceptions

Instead of dumps or generic messages, Arjun uses the Gateway exception class /IWBEP/CX_MGW_BUSI_EXCEPTION to return structured errors. He defines a message container, adds messages from the BAPI return table, and raises the exception. The client then receives a JSON error object with code, message, and severity. He shows how to map BAPI errors like "PO already exists" to HTTP 409 Conflict.

6.2 Common Error Scenarios and HTTP Status Codes

  • 400 Bad Request: invalid input data (e.g., missing required fields).
  • 404 Not Found: PO does not exist.
  • 409 Conflict: duplicate PO or lock issues.
  • 500 Internal Server Error: unexpected runtime errors — but these should be caught and wrapped.

Arjun implements a helper method that converts BAPIRET2 into the appropriate OData exception. He tests with Postman by sending invalid data and verifying the error payload.

7. OData v4 with RAP – The Modern Approach

7.1 Why RAP?

RAP (Restful ABAP Programming Model) is the strategic framework for building OData v4 services and transactional Fiori apps. It uses CDS views as the data definition layer, behavior definitions for transaction logic, and automatically generates the OData service. It supports managed, unmanaged, and draft scenarios.

Arjun demonstrates how the same PO API can be built with RAP, leveraging the CDS views he created in Part 37. He creates a root CDS view for PO header, a composition view for items, and defines the behavior to allow create, update, delete. The framework handles deep create, business validation, and draft. No DPC coding is required for standard operations — only custom validation methods.

7.2 Step-by-Step RAP Service Creation

  1. Create CDS view ZR_PO_HEADER as the root entity, with the @OData.publish: true annotation.
  2. Create CDS view ZR_PO_ITEM as child, with composition to parent.
  3. Define the behavior definition in ADT: right-click the root CDS → New → Behavior Definition. Choose managed scenario. Specify the operations (create, update, delete) and fields for number range (EBELN).
  4. Implement any custom validation in the behavior implementation class (e.g., check vendor limit). Arjun writes a method checkBeforeSave that raises an error if the PO net value exceeds the vendor limit — reusing the logic from the earlier BAdI.
  5. Create a service definition and service binding to expose the OData v4 service.

He then tests the RAP service in the same way with Postman, noting the differences in URL structure (v4 uses /sap/opu/odata4/...) and the JSON format (no "d" wrapper). Deep create works out-of-the-box.

8. Testing with Postman – Complete Walkthrough

8.1 Setup and CSRF Token

Arjun configures Postman with Basic Auth (SAP user credentials). He creates a collection for the API. First request: GET /sap/opu/odata/sap/ZPO_SERVICE/ with header X-CSRF-Token: Fetch. He extracts the token from the response header for subsequent requests.

8.2 CRUD Test Cases

  • Create PO: POST with JSON body (deep insert). Verify 201 and returned data.
  • Read list: GET with $top=5. Verify 200 and array.
  • Read single: GET with key. Verify 200.
  • Update: PUT or PATCH (depending on implementation) with changed fields.
  • Delete: DELETE. Verify 204.

He also demonstrates $filter=Netwr gt 50000, $orderby=Aedat desc, and $count=true. Every step is shown with actual request and response screenshots in the article.

9. Pro Tips and Common Pitfalls

  • CSRF token expiry: Tokens are session-based; if you get 403, fetch a new token. Use the x-csrf-token header in every modifying request.
  • Deep insert and transaction consistency: Always commit only after successful processing of all child entities. Use COMMIT WORK AND WAIT.
  • Performance: For GET_ENTITYSET, use $top, $skip to avoid returning millions of rows. Implement paging via io_tech_request_context->get_top( ) and get_skip( ).
  • Authorization: Never rely solely on API authentication; implement authority checks in the DPC using standard SAP authorization objects.
  • Testing: Always test with Postman before handing over to UI developers. Use different user roles to verify security.

10. Pros, Cons, and Alternatives

MethodProsCons
SEGW + ABAP DPCFull control, works with any data source, matureHigh coding effort, no draft support, v2 only
RAP (Managed)Low-code, draft & draft handling, auto-OData, v4Strictly CDS-based, less control over processing, requires S/4HANA >= 1809
SAP Cloud Application Programming Model (CAP)Cloud-native, great for side-by-side extensions, polyglotNot for direct on-stack ABAP, separate environment

11. The Full Hands-On Lab – Building the Entire API Step by Step

Arjun documents the following full-day lab that you can replicate:

  1. Create a new SEGW project ZPO_SERVICE.
  2. Import DDIC structures for header and item.
  3. Generate runtime objects and implement DPC extension for GET_ENTITYSET (list POs).
  4. Implement CREATE_DEEP_ENTITY for PO with items using BAPI_PO_CREATE1.
  5. Implement GET_ENTITY, UPDATE_ENTITY (BAPI_PO_CHANGE), DELETE_ENTITY.
  6. Add error handling: create message class, map BAPIRET2 to OData exceptions.
  7. Register and activate the service in /IWFND/MAINT_SERVICE.
  8. Test in gateway client (SEGW: Service Implementation → Gateway Client).
  9. Test in Postman: all CRUD and deep insert.
  10. Bonus: build a RAP version with CDS views and behavior definition, and test OData v4.

Every step is accompanied by code snippets, transaction descriptions, and expected outputs. The resulting service is ready for integration with the e-commerce portal.

12. Conclusion – The API Economy Is Here

Arjun's OData service is now live. The Node.js portal successfully creates POs in SAP, and the procurement team can monitor them in real time. He's demonstrated both the battle-tested SEGW approach and the modern RAP way, equipping TechBook24 with a future-proof API strategy. This skill set makes him indispensable — because every digital transformation initiative needs APIs.

Tomorrow, we'll step into the world of Fiori App Development — taking the CDS views and OData services you've built and creating stunning, responsive user interfaces with Fiori Elements and SAPUI5. You'll build a complete Fiori List Report for purchase orders, deploy it to the Launchpad, and customise it. The backend work you've done sets the perfect stage.

Keep coding, keep connecting.

End of Part 38 – OData Services Deep Dive. Brought to you by @FreeLearning365 and tech partner @techbook24.

Post a Comment

0 Comments