Appearance
Lesson 18 Companion — RAP Compositions
This companion supports:
text
Lesson 18 — RAP Compositions: Parent/Child Business ObjectsReference scenario:
text
Reservation
└── Participants1. Core Composition Pattern
Parent:
abap
composition [0..*] of ZR_Reservation_Part_### as _ParticipantsChild:
abap
association to parent ZR_Reservation_### as _Reservation
on $projection.ReservationUuid = _Reservation.UuidA RAP composition expresses:
text
whole
+
dependent part2. Composition Rules
For this two-node BO:
text
exactly one root
root = Reservation
child = Participant
root can be composition source
child defines one direct to-parent association
child cannot exist without parent3. Child Persistence Reference
abap
@EndUserText.label : 'Reservation Participants'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zrespart_### {
key client : abap.clnt not null;
key participant_uuid : sysuuid_x16 not null;
reservation_uuid : sysuuid_x16 not null;
participant_no : abap.numc(4);
participant_name : abap.char(60);
participant_email : abap.char(100);
participant_role : abap.char(40);
local_last_changed_at : abp_locinst_lastchange_tstmpl;
}Use the exact table annotation style already established in the course if your existing table templates differ slightly.
4. Why Two UUID Fields
text
ParticipantUuid
→ identifies one Participant
ReservationUuid
→ identifies its parent ReservationOne Reservation may own many Participant UUIDs.
5. Child CDS Reference
abap
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Reservation Participant'
define view entity ZR_Reservation_Part_###
as select from zrespart_### as Participant
association to parent ZR_Reservation_### as _Reservation
on $projection.ReservationUuid = _Reservation.Uuid
{
_Reservation,
key Participant.participant_uuid as ParticipantUuid,
Participant.reservation_uuid as ReservationUuid,
Participant.participant_no as ParticipantNo,
Participant.participant_name as ParticipantName,
Participant.participant_email as ParticipantEmail,
Participant.participant_role as ParticipantRole,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
Participant.local_last_changed_at as LocalLastChangedAt
}6. To-Parent Association Requirements
The ON condition must identify the parent through its full key.
For this BO:
text
parent key = UuidTherefore:
abap
$projection.ReservationUuid = _Reservation.Uuidis complete.
Expose:
text
_Reservationexactly once.
7. Root CDS Addition
Add:
abap
composition [0..*] of ZR_Reservation_Part_### as _Participantsand expose:
text
_Participantsin the root select list.
8. Base Child DCL Reference
abap
@EndUserText.label: 'Reservation Participant Access'
@MappingRole: true
define role ZR_Reservation_Part_###
{
grant select on ZR_Reservation_Part_###
where ( _Reservation.ResponsibleUser ) = aspect user;
}The child read policy follows parent ownership.
9. Root Behavior Addition
Inside the root behavior:
abap
association _Participants { create; with draft; }This enables:
text
read related children
create child through parent
same-state draft navigation10. Child Behavior Reference
abap
define behavior for ZR_Reservation_Part_### alias Participant
persistent table zrespart_###
draft table zdrespart_###
authorization dependent by _Reservation
lock dependent by _Reservation
etag master LocalLastChangedAt
{
update;
delete;
field ( numbering : managed, readonly )
ParticipantUuid;
field ( readonly )
ReservationUuid,
LocalLastChangedAt;
field ( mandatory:create, readonly:update )
ParticipantNo;
association _Reservation { with draft; }
mapping for zrespart_###
{
ParticipantUuid = participant_uuid;
ReservationUuid = reservation_uuid;
ParticipantNo = participant_no;
ParticipantName = participant_name;
ParticipantEmail = participant_email;
ParticipantRole = participant_role;
LocalLastChangedAt = local_last_changed_at;
}
}11. Why No Standard Child Create
In managed RAP:
text
root
→ CREATE
child
→ CREATE BY associationThe child itself does not expose independent root-style create.
12. Lock Dependency
abap
lock dependent by _Reservationmeans:
text
modify child
→ find parent
→ use parent lock masterOnly root entities are lock masters in this managed BO design.
13. Authorization Dependency
abap
authorization dependent by _Reservationmeans the child's standard modifying operations use the parent authorization master.
For the current course:
text
parent ownership
→ child modifying permission14. Child ETag
Use:
abap
etag master LocalLastChangedAtThe child can be its own ETag master while lock and authorization remain dependent on the root.
15. Root Total ETag
The root:
text
LastChangedAtremains the total ETag.
A total ETag covers:
text
the complete BO composition treeWith correct managed annotations and mapping:
text
active child change
→ root total ETag changes16. Child Draft Table
Declare:
abap
draft table zdrespart_###Then:
text
Ctrl+1
→ Create draft tableUse generated draft persistence.
Do not manually write technical draft columns.
17. Draft Association Contract
Root:
abap
association _Participants { create; with draft; }Child:
abap
association _Reservation { with draft; }Draft-enabled BO-internal associations always navigate to the same active/draft state.
18. Create-by-Association Reference
abap
MODIFY ENTITIES OF ZR_Reservation_###
ENTITY Reservation
CREATE BY \_Participants
FIELDS (
ParticipantNo
ParticipantName
ParticipantEmail
ParticipantRole
)
WITH VALUE #(
(
Uuid = reservation_uuid
%target = VALUE #(
(
%cid = 'PART-001'
ParticipantNo = '0001'
ParticipantName = 'Taylor Reed'
ParticipantEmail = 'taylor@example.com'
ParticipantRole = 'Attendee'
)
)
)
)
MAPPED DATA(mapped)
FAILED DATA(failed)
REPORTED DATA(reported).19. %target
Each CBA source row contains:
text
parent identity
+
%target%target is the nested child-create table.
20. Managed Child Numbering
The external consumer does not fill:
text
ParticipantUuidIt supplies:
text
%cidand reads the generated UUID from:
text
MAPPED-Participant21. Read-by-Association Reference
abap
READ ENTITIES OF ZR_Reservation_###
ENTITY Reservation
BY \_Participants
ALL FIELDS
WITH VALUE #(
( Uuid = reservation_uuid )
)
RESULT DATA(participants)
LINK DATA(participant_links)
FAILED DATA(failed_read).22. LINK
LINK returns the relationship between:
text
source parent key
target child keyIt is useful when several source parents are read together.
23. Deep Create Reference
abap
MODIFY ENTITIES OF ZR_Reservation_###
ENTITY Reservation
CREATE FIELDS (
ReservationNo
CustomerName
ReservationDate
Fee
CurrencyCode
)
WITH VALUE #(
(
%cid = 'ROOT-001'
ReservationNo = '99180001'
CustomerName = 'Composition Student'
ReservationDate = cl_abap_context_info=>get_system_date( )
Fee = '450.00'
CurrencyCode = 'EUR'
)
)
CREATE BY \_Participants
FIELDS (
ParticipantNo
ParticipantName
)
WITH VALUE #(
(
%cid_ref = 'ROOT-001'
%target = VALUE #(
(
%cid = 'CHILD-001'
ParticipantNo = '0001'
ParticipantName = 'Morgan Lee'
)
)
)
)
MAPPED DATA(mapped)
FAILED DATA(failed)
REPORTED DATA(reported).24. %cid_ref
Use:
text
%cid_refwhen the parent is created in the same EML request.
It references the parent's temporary:
text
%cidbefore the final managed key is available.
25. Child Projection Reference
abap
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Reservation Participant Projection'
@Metadata.allowExtensions: true
define view entity ZC_Reservation_Part_###
as projection on ZR_Reservation_Part_###
{
key ParticipantUuid,
ReservationUuid,
ParticipantNo,
ParticipantName,
ParticipantEmail,
ParticipantRole,
LocalLastChangedAt,
_Reservation : redirected to parent ZC_Reservation_###
}26. Root Projection Redirection
Add to:
text
ZC_RESERVATION_###abap
_Participants
: redirected to composition child ZC_Reservation_Part_###Projection composition targets must be projection entities.
27. Projection Child DCL
abap
@EndUserText.label: 'Reservation Participant Projection Access'
@MappingRole: true
define role ZC_Reservation_Part_###
{
grant select on ZC_Reservation_Part_###
where inheriting conditions from entity ZR_Reservation_Part_###;
}28. Projection Behavior Reference
Root addition:
abap
use association _Participants { create; with draft; }Child:
abap
define behavior for ZC_Reservation_Part_### alias Participant
use etag
{
use update;
use delete;
use association _Reservation { with draft; }
}29. Why No New Behavior Pool
The child belongs to the existing managed BO.
Standard managed behavior is provided by the RAP runtime.
A new custom handler is only needed when the child gains custom:
text
validation
determination
action
feature control30. Service Definition Reference
abap
@ObjectModel.leadingEntity.name: 'ZC_RESERVATION_###'
define service ZUI_RESERVATION_###
{
expose ZC_Reservation_### as Reservations;
expose ZC_Reservation_Part_### as Participants;
expose I_CurrencyStdVH as Currencies;
}All BO projection nodes relevant to the UI service should be exposed.
31. Parent UI Facet
abap
@UI.facet: [
{
id: 'Reservation',
purpose: #STANDARD,
type: #IDENTIFICATION_REFERENCE,
label: 'Reservation',
position: 10
},
{
id: 'Participants',
purpose: #STANDARD,
type: #LINEITEM_REFERENCE,
label: 'Participants',
position: 20,
targetElement: '_Participants'
}
]Use #LINEITEM_REFERENCE for a [0..*] child collection.
32. Child Line Items
abap
@Metadata.layer: #CORE
annotate entity ZC_Reservation_Part_### with
{
@UI.lineItem: [ { position: 10, label: 'Participant No.' } ]
ParticipantNo;
@UI.lineItem: [ { position: 20, label: 'Name' } ]
ParticipantName;
@UI.lineItem: [ { position: 30, label: 'Email' } ]
ParticipantEmail;
@UI.lineItem: [ { position: 40, label: 'Role' } ]
ParticipantRole;
}33. Draft Runtime
During an edit draft:
text
active root
draft root
active children
draft childrencan coexist as active/draft versions of the same BO tree.
A child created in the draft remains in:
text
child draft persistenceuntil activation.
34. One Save Activates the Tree
Fiori Save on the draft root activates:
text
root changes
child creates
child updates
child deletesas one draft BO transaction.
35. Child Read Authorization
Behavior authorization protects modifying operations.
DCL still protects reads.
Therefore protect:
text
ZR_RESERVATION_PART_###
ZC_RESERVATION_PART_###separately from the parent DCL.
36. Troubleshooting CDS
If activation fails:
text
create child CDS first
check parent key in ON condition
expose _Reservation once
check composition target name
expose _Participants in root37. Troubleshooting BDEF
Check:
text
child persistent table
child draft table
lock dependent association
authorization dependent association
ETag field
managed UUID field
root association create
with draft on both sides
mapping38. Troubleshooting Projection
Check:
text
child projection exists
root redirects composition to child projection
child redirects parent to root projection
projection BDEF exposes both associations39. Troubleshooting Service/UI
If child table is missing:
text
child exposed in Service Definition?
binding reloaded?
root facet targetElement correct?
child @UI.lineItem present?
projection association create-enabled?40. Certification Focus
Key repair concepts:
text
composition
association to parent
create by association
lock dependent by
authorization dependent by
with draft
%target
%cid_ref
LINK
redirected to composition child
redirected to parent
use associationStudents should be able to trace a multi-node BO from persistence to Fiori.
Next steps
Apply Lessons 15–18 to your Purchase Request BO in Project 4 — Service-Ready Purchase Request Application. Complete the checkpoint before continuing with Lesson 19 — RAP Business Events.