Service Bindings Part 2: Create, Activate, Publish and Test in ADT
Walk through the full hands-on flow: create and activate the binding, publish the local service endpoint, check it in the Gateway administration, and test $metadata, reads and a create — in on-premise S/4HANA and in the ABAP cloud environment.
Explanation
📌 KEY POINTS
✅ Create the binding in ADT, activate, then Publish.
✅ Use Preview on an entity set to test the Fiori Elements app.
✅ Check $metadata to confirm entities, actions and annotations.
⚠️ Activating is not publishing — an unpublished binding returns 404.
▶ WHERE WE ARE
In Part 1 you created service definition ZUI_PURCHREQ and binding ZUI_PURCHREQ_O4 (OData V4 – UI) and activated both. Now you make the service reachable and prove it works.
━━━━━━━━━━━━━━━━━━━━
▶ ACTIVATE VS PUBLISH — TWO DIFFERENT THINGS
- Activate compiles the binding object in the ABAP repository. It proves the service definition and projections are consistent.
- Publish registers the service in the OData runtime (SAP Gateway) of this system, so HTTP requests to its URL are routed to your business object.
An activated but unpublished binding exists only as a repository object — every call to its URL returns 404.
━━━━━━━━━━━━━━━━━━━━
▶ STEP 1 — PUBLISH (ON-PREMISE S/4HANA AND PRIVATE CLOUD)
- Open ZUI_PURCHREQ_O4 in ADT.
- In the Services section, click Publish (label "Publish local service endpoint" on some releases).
- Wait for the success message. The editor now shows the Service URL and enables Preview.
What happened in the background:
- OData V4: a service group for the binding was published in the Gateway, using the local system alias. You can see it in transaction /IWFND/V4_ADMIN.
- OData V2: the service was registered as in /IWFND/MAINT_SERVICE, where it now appears.
Publishing needs Gateway administration authorization in this system. If Publish fails with an authorization message, a Basis or Gateway admin must assign it or publish for you.
━━━━━━━━━━━━━━━━━━━━
▶ STEP 1 (ALTERNATIVE) — SAP BTP ABAP ENVIRONMENT / S/4HANA CLOUD DEVELOPMENT
Click Publish in the same way to get a local service endpoint for development and preview. For real users, the service is then made available through an IAM app (for UI services) or a communication scenario (for Web APIs) — see Part 3.
━━━━━━━━━━━━━━━━━━━━
▶ STEP 2 — PREVIEW
Select the root entity set PurchaseRequest in the binding editor and click Preview. A generic Fiori Elements list report opens in the browser.
- If the list shows no columns, that is not a data problem: the projection has no @UI.lineItem annotations yet. Use the gear icon to pick columns, or add annotations (Part 6).
- Click Create, fill Description and Currency, add an item, Save. You exercise the complete stack: draft, determinations, validations, numbering and save.
- Try Save without a Description: the validation message from the Managed series should appear on the field.
━━━━━━━━━━━━━━━━━━━━
▶ STEP 3 — TEST THE RAW SERVICE
Preview hides HTTP details. Test the service directly:
- Open transaction /IWFND/GW_CLIENT (SAP Gateway Client).
- Request: GET <service URL>$metadata — you should get XML describing EntityTypes PurchaseRequest and PurchaseRequestItem, their properties, keys, navigation properties and actions.
- GET <service URL>PurchaseRequest?$top=5 — JSON list of active and draft instances.
- GET PurchaseRequest(RequestUUID=<uuid>,IsActiveEntity=true)?$expand=_Item — one request with items. IsActiveEntity is part of the key because the BO is draft-enabled.
- Check the HTTP status codes: 200 OK, 201 Created, 204 No Content, 400 for bad requests, 403 for authorization, 404 for unknown service or instance, 412 for ETag mismatch.
You can also test from a browser (GET only) or from tools like Postman for POST/PATCH (with CSRF token handling).
━━━━━━━━━━━━━━━━━━━━
▶ STEP 4 — WHAT A SUCCESSFUL TEST PROVES, AND WHAT IT DOES NOT
Proves: the service is published, metadata is consistent, the BO works for your user.
Does not prove: that other users have the right authorizations, that the service is published in QAS/PRD, that the Fiori launchpad tile exists, or that the service performs with production data volumes. Those are Parts 3 and 5.
━━━━━━━━━━━━━━━━━━━━
▶ CHECKLIST AFTER PUBLISHING
- Service URL visible in the binding editor.
- $metadata returns 200 in /IWFND/GW_CLIENT.
- Service group (V4) visible in /IWFND/V4_ADMIN, or service (V2) in /IWFND/MAINT_SERVICE.
- Preview: list, object page, create, edit, validation message all work.
- Record the binding, service URL and test results in your technical design document.
━━━━━━━━━━━━━━━━━━━━
▶ WHAT YOU HAVE AFTER PART 2
A published, tested OData V4 service for the Purchase Request. Part 3 takes it through the landscape.
Code example
// ===== Test calls for SAP Gateway Client (/IWFND/GW_CLIENT) =====// Base = service URL copied from the binding editor, e.g.// /sap/opu/odata4/sap/zui_purchreq_o4/srvd/sap/zui_purchreq/0001/ // 1. Metadata - must return 200 and list both entity typesGET {base}$metadata // 2. First 5 requests, selected fields onlyGET {base}PurchaseRequest?$select=RequestID,Description,Status,TotalAmount&$top=5 // 3. One request with its items (draft-enabled BO: IsActiveEntity is part of the key)GET {base}PurchaseRequest(RequestUUID=0f3c1a2b-0000-1eef-a1b2-c3d4e5f60718,IsActiveEntity=true)?$expand=_Item // 4. Filter - served by the CDS view (query path), no ABAP handler involvedGET {base}PurchaseRequest?$filter=Status eq 'S'&$orderby=RequestID desc // 5. Create a new DRAFT (UI services create drafts first)POST {base}PurchaseRequestContent-Type: application/json{ "Description": "Monitors for finance team", "CurrencyCode": "INR"} // 6. Activate the draft (= user clicks Save); action names come from the BDEFPOST {base}PurchaseRequest(RequestUUID=...,IsActiveEntity=false)/com.sap.gateway.srvd.zui_purchreq.v0001.Activate// Tip: copy the exact action path from the Action/ActionImport entries in $metadata. // ===== Where to look after publishing =====// /IWFND/V4_ADMIN -> OData V4 service groups (published bindings)// /IWFND/MAINT_SERVICE -> OData V2 services// /IWFND/GW_CLIENT -> send test requests// /IWFND/ERROR_LOG -> errors on the Gateway hub side// /IWBEP/ERROR_LOG -> errors on the backend sideReal project scenario
A developer finished a binding in the development system, clicked Activate, and sent the URL to the UI developer. The UI developer immediately got HTTP 404 and assumed the URL was wrong. They tried several URL variations for an hour.
The binding had never been published — in that on-premise system, Activate only created the repository object. After clicking Publish, the Service URL appeared in the editor, the service group showed up in /IWFND/V4_ADMIN, and the original URL worked.
The team added "Publish + $metadata returns 200 in GW_CLIENT" to the definition of done for every service, so a binding is only handed over with a proven URL.
Common mistakes
- Assuming Activate makes the service callable; on-premise it must also be published.
- Typing the service URL by hand instead of copying it from the binding editor.
- Concluding "no data" when preview shows an empty-looking table — usually missing @UI.lineItem annotations.
- Testing only in preview and never checking $metadata or HTTP status codes directly.
- Forgetting IsActiveEntity in keys when calling a draft-enabled service.
- Testing only with a developer user that has broad authorizations.
- Posting to a UI service and expecting an active record immediately — UI services create drafts that must be activated.
Best practices
- Definition of done for a service: published, $metadata 200, list/read/create tested, URL documented.
- Test in this order: $metadata → read → filter/expand → create → update → actions → error cases.
- Use /IWFND/GW_CLIENT for exact HTTP behavior; use preview for end-to-end UI behavior.
- Copy action and entity paths from $metadata rather than guessing namespaces.
- Test with a user that has only the intended business role, not SAP_ALL.
Interview angle
Questions you may get: "How do you make a RAP service available?", "What is the difference between activating and publishing a binding?", "How do you test an OData service in the backend?"
Strong answer: create and activate the binding, then publish it (on-premise this registers the service group in the Gateway, visible in /IWFND/V4_ADMIN for V4 or /IWFND/MAINT_SERVICE for V2), then test $metadata and CRUD calls in /IWFND/GW_CLIENT and the Fiori Elements preview. Mention draft keys (IsActiveEntity) and HTTP status codes like 412 for ETag conflicts. Stating what a successful developer test does not prove (other users' roles, other systems) shows production awareness.
Practice this lesson
Quick check
1. In an on-premise S/4HANA system, what does publishing a service binding do that activating it does not?
2. Where can you check that an OData V4 service group from a RAP binding is published in an on-premise system?
3. A field exists in the projection but the preview shows no column for it. What is the most likely cause?
Interview questions
1. You activated a new service binding and sent the URL to the UI developer, who gets HTTP 404. What is the difference between activating and publishing a binding, and how do you fix it?
Answer it in your own words first, then compare.
2. How do you test a newly published RAP OData V4 service end to end before handing it to the UI team?
Answer it in your own words first, then compare.
Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.
More lessons in this topic
- Service Bindings Part 1: From Business Object to OData Service
- Service Bindings Part 3: Moving Bindings Through DEV, QAS and PRD
- Service Bindings Part 4: UI vs Web API, OData V4 vs V2
- Service Bindings Part 5: Troubleshooting 404, 403, Metadata and Cache
- Service Bindings Part 6: Preview, $metadata and Fiori Elements Annotations