Service Definitions Part 2: Exposing Projection Entities as a Business Service
Decide which projection entities form one business service, write the service definition with meaningful aliases, and verify the result in the binding's entity list and $metadata.
Explanation
📌 KEY POINTS
✅ A service is a business capability: "maintain purchase requests" — expose everything it needs, nothing more.
✅ Always expose the root and all composition children used by the app.
✅ Aliases become entity set names in OData and in client code.
💡 After activation, check the binding's entity list and $metadata.
━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE
Part 1 introduced the object. Now: how to decide what goes into one service.
━━━━━━━━━━━━━━━━━━━━
▶ 1. THINK IN CAPABILITIES
A service supports one business capability for one consumer type:
- ZUI_PURCHREQ — buyers maintain purchase requests in a Fiori app.
- ZUI_PURCHREQ_APPROVE — approvers review and approve.
- ZAPI_PURCHREQ — external systems create and read requests.
Each has its own projections and service definition. A "one service for everything" approach makes every change risky for all consumers.
━━━━━━━━━━━━━━━━━━━━
▶ 2. WHAT TO EXPOSE FOR A TRANSACTIONAL APP
- The root projection (ZC_PurchReq).
- All composition children the app shows or edits (ZC_PurchReqItem).
- Entities needed for navigation from the object page (e.g. a read-only supplier projection, if you want navigation, not just a value help).
- Value-help entities, when they are not reachable otherwise (Part 6).
━━━━━━━━━━━━━━━━━━━━
▶ 3. ALIASES
- The alias becomes the entity set name: /PurchaseRequest, /PurchaseRequestItem.
- Use singular business nouns in CamelCase; avoid prefixes like ZC_.
- Once consumers use a service, aliases are part of the contract (Part 3).
━━━━━━━━━━━━━━━━━━━━
▶ 4. VERIFY
After activation and binding:
- The binding editor lists the entity sets and their navigation.
- $metadata shows EntityTypes, EntitySets, NavigationProperties and actions.
- The preview shows whether the app works end to end.
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
- Write down the capability and the consumer.
- List the entities the app needs (root, children, navigation targets).
- Write the service definition (code example).
- Activate, bind (V4 – UI), publish, and check entity sets and navigation in $metadata.
✅ CHECKPOINT: your service contains exactly what the capability needs.
Code example
// ===== Buyer app: maintain purchase requests =====@EndUserText.label: 'Purchase Request - maintain (buyer)'define service ZUI_PURCHREQ { expose ZC_PurchReq as PurchaseRequest; // root expose ZC_PurchReqItem as PurchaseRequestItem; // composition child expose ZC_SupplierVH as Supplier; // value help / navigation target} // ===== Approver app: separate capability, separate projections =====@EndUserText.label: 'Purchase Request - approve (approver)'define service ZUI_PURCHREQ_APPROVE { expose ZC_PurchReqApprove as PurchaseRequest; expose ZC_PurchReqItemApprove as PurchaseRequestItem;} // ===== What appears in $metadata (V4, simplified) =====// <EntitySet Name="PurchaseRequest" EntityType="...PurchaseRequestType">// <NavigationPropertyBinding Path="_Item" Target="PurchaseRequestItem"/>// </EntitySet>// <EntitySet Name="PurchaseRequestItem" .../>// <EntitySet Name="Supplier" .../>// <Action Name="approve" IsBound="true"> ... (only in the approver service,// if its projection BDEF uses it)Real project scenario
A project had one large service exposing purchase requests, orders, suppliers, approvals and reports for five apps. Every change to one app required regression tests of all five, and the $metadata was so large that apps started slowly.
The team split it by capability: a buyer service, an approver service and a reporting service, each with dedicated projections. Changes became local, metadata shrank, and app start times improved noticeably.
Common mistakes
- One huge service for many apps.
- Forgetting composition children, so object pages cannot show items.
- Exposing entities "just in case".
- Technical aliases that leak object names into client code.
- Not verifying entity sets and navigation after activation.
Best practices
- One service per capability and consumer type.
- Expose root, children and required navigation/value-help targets.
- Use stable business aliases.
- Verify in the binding and $metadata every time the service changes.
- Keep services small for fast metadata loading.
Interview angle
Questions: "How do you decide what goes into a service definition?", "Why not one service for everything?"
Strong answer: design services per business capability and consumer type; expose the root, the composition children and required navigation/value-help targets; use business aliases; verify via binding and $metadata. Explain the cost of monolithic services: coupling, regression effort and large metadata.
Practice this lesson
Quick check
1. A service exposes 18 helper entities "because every association might be needed". What is the best correction?
2. A project exposed base interface entities directly in its services. What is the main risk?
3. Which object should normally be exposed in a RAP service definition?
Interview questions
1. Write a service definition for an order app with header, items and a customer link, and explain each line.
Answer it in your own words first, then compare.
2. How do you decide which entities go into a service definition?
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 Definitions Part 1: What a Service Definition Does
- Service Definitions Part 3: API Boundary, Naming and Versioning
- Service Definitions Part 4: Troubleshooting Activation and Exposure Gaps
- Service Definitions Part 5: UI vs Integration APIs — Reuse or Separate?
- Service Definitions Part 6: Exposing Multiple Entities and Navigation