I have been waiting for this feature and can’t stop myself from trying it. I thought the syntax would be complicated and was surprised when I realized they were so simple and readable.
Side effects are useful in UI scenarios based on draft-enabled BOs to notify a Fiori Elements UI that data changes of defined fields require the recalculation of other data values, permissions or messages .
Earlier we had to use annotations in Fiori Application to refresh the target elements on the UI automatically. This new features reduce the dependency on UI development and help backend developers to test functions in ADT preview itself.
Multiple variants are already available and this blog post describes most used cases and other features are yet to be explored.
- Side effects in the same entity on field change
- Side effects in different entities on a field change
- Side effects in different entities on a custom action.
- booking-fee is changed or
- new booking is created or
Existing booking is deleted or- Flight price is changed.
- Develop the Fiori elements application using RAP-CDS-Modeling.
- Define the required determinations and actions on the specified entities.
- Implement the business logic in respective Behavior Pool classes
- Identify the source properties and target properties/entities for side effects
- Define the side effects in Behavior definition ( note: Only once side effects can be defined in a behavior definition )
- Expose the side effects in Projection level behavior definition so that they are available UI consumption.
- Develop the fiori elements application using RAP-CDS-Modeling.
- Travel ZRK_SDE_I_TRAVEL and Booking zrk_sde_i_booking entities have been generated and defined its Behavior definition ZRK_SDE_I_TRAVEL .
- As the focus of the blog post is not about data model and to keep the blog post simple, Source code is published in git repository.
- Travel ZRK_SDE_I_TRAVEL and Booking zrk_sde_i_booking entities have been generated and defined its Behavior definition ZRK_SDE_I_TRAVEL .
- Define the required determinations and actions on the specified entities.
- Determination Calculate_Total_price in Travel entity.
determination Calculate_Total_price on modify { field BookingFee; }
- Determination Calculate_Total_price in Booking entity.
determination calculate_Total_Price on modify { create; field flightprice; }
- Internal action ReCalcTotalPrice in Travel entity which is in turn executed in above 2 steps so that business logic is implemented once and consistent.
internal action ReCalcTotalPrice;
- Custom action Apply_Discount in Booking entity
action Apply_Discount parameter zrk_sde_a_apply_disc result [1] $self;
- Determination Calculate_Total_price in Travel entity.
- Implement the business logic in respective Behavior Pool classes.
*************** calculate_Total_Price at Travel Entity METHOD Calculate_Total_price. "update involved instances MODIFY ENTITIES OF zrk_sde_i_travel IN LOCAL MODE ENTITY Travel EXECUTE recalctotalprice FROM CORRESPONDING #( keys ). ENDMETHOD. *************** calculate_Total_Price at Booking Entity METHOD calculate_Total_Price. READ ENTITIES OF zrk_sde_i_travel IN LOCAL MODE ENTITY Booking BY _Travel FIELDS ( TravelUUID ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_travels). "update involved instances MODIFY ENTITIES OF zrk_sde_i_travel IN LOCAL MODE ENTITY Travel EXECUTE recalctotalprice FROM VALUE #( FOR <fs_key> IN lt_travels ( %tky = <fs_key>-%tky ) ). ENDMETHOD. *************** Internal action - Implementation METHOD ReCalcTotalPrice. READ ENTITIES OF zrk_sde_i_travel IN LOCAL MODE ENTITY Travel FIELDS ( BookingFee ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_travels). LOOP AT lt_travels ASSIGNING FIELD-SYMBOL(<Fs_travel>). <Fs_travel>-TotalPrice = <Fs_travel>-BookingFee. READ ENTITIES OF zrk_sde_i_travel IN LOCAL MODE ENTITY Travel BY _Booking FIELDS ( FlightPrice ) WITH VALUE #( ( %tky = <fs_travel>-%tky ) ) RESULT DATA(lt_bookings). LOOP AT lt_bookings ASSIGNING FIELD-SYMBOL(<fs_booking>). <Fs_travel>-TotalPrice = <Fs_travel>-TotalPrice + <fs_booking>-FlightPrice. ENDLOOP. ENDLOOP. "update involved instances MODIFY ENTITIES OF zrk_sde_i_travel IN LOCAL MODE ENTITY Travel UPDATE FIELDS ( TotalPrice ) WITH VALUE #( FOR travel IN lt_travels ( %tky = travel-%tky TotalPrice = travel-TotalPrice ) ). ENDMETHOD.
METHOD Apply_Discount. LOOP AT keys ASSIGNING FIELD-SYMBOL(<fs_key>). DATA(lv_disc_percent) = <fs_key>-%param-Discount_percent. ENDLOOP. READ ENTITIES OF zrk_sde_i_travel IN LOCAL MODE ENTITY Booking FIELDS ( FlightPrice ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_bookings). LOOP AT lt_bookings ASSIGNING FIELD-SYMBOL(<fs_booking>). <fs_booking>-FlightPrice = <fs_booking>-FlightPrice * ( 100 - lv_disc_percent ) / 100. ENDLOOP. "update involved instances MODIFY ENTITIES OF zrk_sde_i_travel IN LOCAL MODE ENTITY Booking UPDATE FIELDS ( FlightPrice ) WITH VALUE #( FOR <fs_book> IN lt_bookings ( %tky = <fs_book>-%tky FlightPrice = <fs_book>-FlightPrice ) ). READ ENTITIES OF zrk_sde_i_travel IN LOCAL MODE ENTITY Booking FIELDS ( FlightPrice ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_bookings_upd). RESUlT = VALUE #( FOR <fs_res> IN lt_bookings_upd ( %tky = <fs_res>-%tky %param = <fs_res> ) ) . ENDMETHOD.
- Identify the source properties and target properties/entities for side effects.
- Determination Calculate_Total_price in Travel entity.
Source : Field – Booking fee ,
Target : Field – Total price - Determination Calculate_Total_price in Booking entity.
Source : Field – Flight price ,
Target : Field – Total price from Travel entity - Custom action.
Source : Action – Apply_Discount
Target : Field – Total price from Travel entity
- Determination Calculate_Total_price in Travel entity.
- Define the side effects in Behavior definition ( note: Only once side effects can be defined in a behavior definition )
define behavior for ZRK_SDE_I_TRAVEL alias Travel ... side effects { field BookingFee affects field TotalPrice; }
define behavior for zrk_sde_i_booking alias Booking ... side effects { field FlightPrice affects field _Travel.TotalPrice; action Apply_Discount affects field _Travel.TotalPrice ; }
- Expose the side effects in Projection level behavior definition so that they are available UI consumption.
projection; strict ( 2 ); use draft; use side effects; <<<<<<======= define behavior for ZRK_SDE_C_TRAVEL alias Travel use etag { }
- Observe the activities done by the framework.
- Metadata definition:
As we can see here, all the 3 side effects are converted by the framework in Odata-v4 annotations .
<Annotations Target="SAP__self.TravelType"> <Annotation Term="SAP__common.Label" String="Projection View for ZRK_SDE_I_TRAVEL"/> <Annotation Term="SAP__common.SideEffects" Qualifier="SAP__Field_BookingFee"> <Record Type="SAP__common.SideEffectsType"> <PropertyValue Property="SourceProperties"> <Collection> <PropertyPath>BookingFee</PropertyPath> </Collection> </PropertyValue> <PropertyValue Property="TargetProperties"> <Collection> <String>TotalPrice</String> </Collection> </PropertyValue> </Record> </Annotation> </Annotations> <Annotations Target="SAP__self.BookingsType"> <Annotation Term="SAP__common.Label" String="ZRK_SDE_C_BOOKING"/> <Annotation Term="SAP__common.SideEffects" Qualifier="SAP__Field_FlightPrice"> <Record Type="SAP__common.SideEffectsType"> <PropertyValue Property="SourceProperties"> <Collection> <PropertyPath>FlightPrice</PropertyPath> </Collection> </PropertyValue> <PropertyValue Property="TargetProperties"> <Collection> <String>_Travel/TotalPrice</String> </Collection> </PropertyValue> </Record> </Annotation> </Annotations> <Annotations Target="SAP__self.Apply_Discount(SAP__self.BookingsType)"> <Annotation Term="SAP__core.OperationAvailable" Path="_it/__OperationControl/Apply_Discount"/> <Annotation Term="SAP__common.SideEffects" Qualifier="SAP__Action_Apply_Discount"> <Record Type="SAP__common.SideEffectsType"> <PropertyValue Property="TargetProperties"> <Collection> <String>_it/_Travel/TotalPrice</String> </Collection> </PropertyValue> </Record> </Annotation> </Annotations>
- Network calls:
As we can see network calls, Read calls for the target properties/entries are automatically fired when the source properties are changed /actions are triggered.
- Metadata definition:
Conclusion: