Skip to content

Lesson 18 Companion — RAP Compositions ​

This companion supports:

text
Lesson 18 — RAP Compositions: Parent/Child Business Objects

Reference scenario:

text
Reservation
└── Participants

1. Core Composition Pattern ​

Parent:

abap
composition [0..*] of ZR_Reservation_Part_### as _Participants

Child:

abap
association to parent ZR_Reservation_### as _Reservation
  on $projection.ReservationUuid = _Reservation.Uuid

A RAP composition expresses:

text
whole
+
dependent part

2. 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 parent

3. 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 Reservation

One 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 = Uuid

Therefore:

abap
$projection.ReservationUuid = _Reservation.Uuid

is complete.

Expose:

text
_Reservation

exactly once.


7. Root CDS Addition ​

Add:

abap
composition [0..*] of ZR_Reservation_Part_### as _Participants

and expose:

text
_Participants

in 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 navigation

10. 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 association

The child itself does not expose independent root-style create.


12. Lock Dependency ​

abap
lock dependent by _Reservation

means:

text
modify child
→ find parent
→ use parent lock master

Only root entities are lock masters in this managed BO design.


13. Authorization Dependency ​

abap
authorization dependent by _Reservation

means the child's standard modifying operations use the parent authorization master.

For the current course:

text
parent ownership
→ child modifying permission

14. Child ETag ​

Use:

abap
etag master LocalLastChangedAt

The child can be its own ETag master while lock and authorization remain dependent on the root.


15. Root Total ETag ​

The root:

text
LastChangedAt

remains the total ETag.

A total ETag covers:

text
the complete BO composition tree

With correct managed annotations and mapping:

text
active child change
→ root total ETag changes

16. Child Draft Table ​

Declare:

abap
draft table zdrespart_###

Then:

text
Ctrl+1
→ Create draft table

Use 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
ParticipantUuid

It supplies:

text
%cid

and reads the generated UUID from:

text
MAPPED-Participant

21. 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).

LINK returns the relationship between:

text
source parent key
target child key

It 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_ref

when the parent is created in the same EML request.

It references the parent's temporary:

text
%cid

before 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 control

30. 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 children

can coexist as active/draft versions of the same BO tree.

A child created in the draft remains in:

text
child draft persistence

until activation.


34. One Save Activates the Tree ​

Fiori Save on the draft root activates:

text
root changes
child creates
child updates
child deletes

as 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 root

37. 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
mapping

38. Troubleshooting Projection ​

Check:

text
child projection exists
root redirects composition to child projection
child redirects parent to root projection
projection BDEF exposes both associations

39. 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 association

Students 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.