Technology Blog Posts by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Srivatsa
Explorer
371

Local Handler Class

In an unmanaged RAP scenario, the local handler class is where you write the ABAP code to implement the behavior defined in the behavior definition. This includes implementing the standard CRUD (Create, Read, Update, Delete) operations and any custom actions.

  • Role of the Local Handler Class:

    • It acts as the "brain" of your RAP business object, containing the code that interacts with the database and enforces business rules.
    • It processes requests from the service layer and performs the necessary actions.
    • It handles data manipulation, validation, and authorization.
    • Keys in Local Handler Class:

      • Keys are crucial within the local handler class because they are used to identify specific instances of the business object.
      • For example, when updating a customer, the customer_id key is used to locate the correct customer record in the database.
      • When creating a new entity (like an attachment), the handler might need to generate a new unique key.
      • Key fields are often used in WHERE clauses in database operations to ensure that the correct data is being accessed or modified.
      • Entities:

        • Within the local handler class, the term "entities" refers to the data being processed—typically, a table of instances.
        • When creating new customers, the "entities" parameter would hold the data for the new customer records.
        • When updating customers, "entities" would contain the modified data for the customers being updated.
        • When deleting, "entities" would identify which customer instances to delete.
        • CRUD Operation Examples:

          • Create:

            • This method handles the creation of new customer records.
            • It iterates through the entities to be created.
            • It generates a new customer_id (if it's not provided).
            • It inserts the new customer data into the zztmfcustomer database table.
            • It handles error situations (e.g., if the database insertion fails).
            • It returns the created customer IDs with %cid (client ID) to the framework.
            • Read:

              • This method retrieves customer data based on the provided keys.
              • It iterates through the keys (which contain the customer_id).
              • It selects the customer data from the zztmfcustomer table using the customer_id in the WHERE clause.
              • It appends the retrieved data to the result.
              • It handles the case where a customer with the given ID is not found.
              • Update:

                • This method updates existing customer records.
                • It iterates through the entities containing the updated data.
                • It uses the MODIFY statement to update the corresponding record in the zztmfcustomer table, using the customer_id in the WHERE clause to identify the record.
                • It handles potential errors during the update.
                • Delete:

                  • This method deletes customer records.
                  • It iterates through the keys (containing the customer_id of the records to be deleted).
                  • It deletes the records from the zztmfcustomer table using the customer_id in the WHERE clause.
                  • It includes error handling.
    METHODS create FOR MODIFY IMPORTING entities FOR CREATE Customer.
    METHODS modify FOR MODIFY IMPORTING entities FOR UPDATE Customer.
    METHODS delete FOR MODIFY IMPORTING keys FOR DELETE Customer.
    METHODS read   FOR READ   IMPORTING keys FOR READ Customer RESULT result.​

ASSOCIATION :

The Associated Child entities should be created only from a Parent Entity, in the above they are specified as Root\_Associated Entity , however the other operations of the class can be handled directly by declaring a method.

METHODS create_ContactMedium   FOR MODIFY IMPORTING entities FOR CREATE Customer\_ContactMedium.
    METHODS create_CreditProfile   FOR MODIFY IMPORTING entities FOR CREATE Customer\_CreditProfile.
    METHODS create_EventInput      FOR MODIFY IMPORTING entities FOR CREATE Customer\_EventInput.
    METHODS create_EventSubscription FOR MODIFY IMPORTING entities FOR CREATE Customer\_EventSubscription.
    METHODS create_Characteristic  FOR MODIFY IMPORTING entities FOR CREATE Customer\_Characteristic.
    METHODS create_PaymentMethod   FOR MODIFY IMPORTING entities FOR CREATE Customer\_PaymentMethod.
    METHODS create_RelatedParty    FOR MODIFY IMPORTING entities FOR CREATE Customer\_RelatedParty.
    METHODS create_TimePeriod      FOR MODIFY IMPORTING entities FOR CREATE Customer\_TimePeriod

Custom Action: copy

The behavior definition allows defining custom actions.

We defined a copy action for the Customer entity.

Why use it?

Efficiency: Quickly create similar records

Consistency: Maintain default values.

User Experience: Convenient for repetitive data entry.

Implementing the copy Action: Add a method in the local handler class to implement the copy logic.

define behavior for ZC_TMF_Customer alias Customer
authorization master ( instance )
draft table ZZTMFCUSTOMER_d
etag master last_changed_at
lock master total etag last_changed_at
early numbering
{
  // Root entity
  create;
  update;
  delete;
  action copy;

Implement the Method logic:

METHOD copy.


  DATA: lv_new_id TYPE zztmfcustomer-id,
        ls_customer TYPE zztmfcustomer,
        lt_accountref TYPE TABLE OF zztmfaccountref,
        lt_agreementre TYPE TABLE OF zztmfagreementre,
        lt_contactmedium TYPE TABLE OF zztmfcontactme,
        lt_creditprofile TYPE TABLE OF zztmfcreditpro,
        lt_eventinput TYPE TABLE OF zztmfeventinput,
        lt_eventsubscr TYPE TABLE OF zztmfeventsubscr,
        lt_characteris TYPE TABLE OF zztmfcharacteris,
        lt_paymentme TYPE TABLE OF zztmfpaymentme,
        lt_relatedpart TYPE TABLE OF zztmfrelatedpart,
        lt_timeperiod TYPE TABLE OF zztmftimeperiod.

  LOOP AT entities ASSIGNING FIELD-SYMBOL(<ls_entity>).

    " 1. Read original customer
    SELECT SINGLE * FROM zztmfcustomer  WHERE id = @<ls_entity>-customer_id INTO _customer.
    IF sy-subrc <> 0.
      CONTINUE.
    ENDIF.

    " 2. Get new customer id
    SELECT MAX( id ) FROM zztmfcustomer INTO _new_id.
    lv_new_id =  lv_new_id + 1.

    " 3. Insert new customer (copy, but new id)
    ls_customer-id = lv_new_id.
    INSERT zztmfcustomer FROM _customer.

    " 4. Copy AccountRef
    SELECT * FROM zztmfaccountref  WHERE id = @<ls_entity>-customer_id INTO TABLE _accountref.
    LOOP AT lt_accountref ASSIGNING FIELD-SYMBOL(<ls_acc>).
      <ls_acc>-id = lv_new_id.
    ENDLOOP.
    IF lt_accountref IS NOT INITIAL.
      INSERT zztmfaccountref FROM TABLE _accountref.
    ENDIF.

    " 5. Copy AgreementRe
    SELECT * FROM zztmfagreementre  WHERE id = @<ls_entity>-customer_id INTO TABLE _agreementre.
    LOOP AT lt_agreementre ASSIGNING FIELD-SYMBOL(<ls_agr>).
      <ls_agr>-id = lv_new_id.
    ENDLOOP.
    IF lt_agreementre IS NOT INITIAL.
      INSERT zztmfagreementre FROM TABLE _agreementre.
    ENDIF.

    " 6. Copy ContactMedium
    SELECT * FROM zztmfcontactme  WHERE id = @<ls_entity>-customer_id INTO TABLE _contactmedium.
    LOOP AT lt_contactmedium ASSIGNING FIELD-SYMBOL(<ls_con>).
      <ls_con>-id = lv_new_id.
    ENDLOOP.
    IF lt_contactmedium IS NOT INITIAL.
      INSERT zztmfcontactme FROM TABLE _contactmedium.
    ENDIF.

    " 7. Copy CreditProfile
    SELECT * FROM zztmfcreditpro  WHERE id = @<ls_entity>-customer_id INTO TABLE _creditprofile.
    LOOP AT lt_creditprofile ASSIGNING FIELD-SYMBOL(<ls_cred>).
      <ls_cred>-id = lv_new_id.
    ENDLOOP.
    IF lt_creditprofile IS NOT INITIAL.
      INSERT zztmfcreditpro FROM TABLE _creditprofile.
    ENDIF.

    " 8. Copy EventInput
    SELECT * FROM zztmfeventinput  WHERE id = @<ls_entity>-customer_id INTO TABLE _eventinput.
    LOOP AT lt_eventinput ASSIGNING FIELD-SYMBOL(<ls_evi>).
      <ls_evi>-id = lv_new_id.
    ENDLOOP.
    IF lt_eventinput IS NOT INITIAL.
      INSERT zztmfeventinput FROM TABLE _eventinput.
    ENDIF.

    " 9. Copy EventSubscription
    SELECT * FROM zztmfeventsubscr  WHERE id = @<ls_entity>-customer_id INTO TABLE _eventsubscr.
    LOOP AT lt_eventsubscr ASSIGNING FIELD-SYMBOL(<ls_evs>).
      <ls_evs>-id = lv_new_id.
    ENDLOOP.
    IF lt_eventsubscr IS NOT INITIAL.
      INSERT zztmfeventsubscr FROM TABLE _eventsubscr.
    ENDIF.

    " 10. Copy Characteristic
    SELECT * FROM zztmfcharacteris  WHERE id = @<ls_entity>-customer_id INTO TABLE _characteris.
    LOOP AT lt_characteris ASSIGNING FIELD-SYMBOL(<ls_char>).
      <ls_char>-id = lv_new_id.
    ENDLOOP.
    IF lt_characteris IS NOT INITIAL.
      INSERT zztmfcharacteris FROM TABLE _characteris.
    ENDIF.

    " 11. Copy PaymentMethod
    SELECT * FROM zztmfpaymentme  WHERE id = @<ls_entity>-customer_id INTO TABLE _paymentme.
    LOOP AT lt_paymentme ASSIGNING FIELD-SYMBOL(<ls_pay>).
      <ls_pay>-id = lv_new_id.
    ENDLOOP.
    IF lt_paymentme IS NOT INITIAL.
      INSERT zztmfpaymentme FROM TABLE _paymentme.
    ENDIF.

    " 12. Copy RelatedParty
    SELECT * FROM zztmfrelatedpart  WHERE id = @<ls_entity>-customer_id INTO TABLE _relatedpart.
    LOOP AT lt_relatedpart ASSIGNING FIELD-SYMBOL(<ls_rel>).
      <ls_rel>-id = lv_new_id.
    ENDLOOP.
    IF lt_relatedpart IS NOT INITIAL.
      INSERT zztmfrelatedpart FROM TABLE _relatedpart.
    ENDIF.

    " 13. Copy TimePeriod
    SELECT * FROM zztmftimeperiod  WHERE id = @<ls_entity>-customer_id INTO TABLE _timeperiod.
    LOOP AT lt_timeperiod ASSIGNING FIELD-SYMBOL(<ls_tim>).
      <ls_tim>-id = lv_new_id.
    ENDLOOP.
    IF lt_timeperiod IS NOT INITIAL.
      INSERT zztmftimeperiod FROM TABLE _timeperiod.
    ENDIF.

    " 14. Return new key
    APPEND VALUE #( %tky = VALUE #( customer_id = lv_new_id ) ) TO mapped-customer.

  ENDLOOP.

Draft Functionality

Draft functionality enhances the user experience by allowing users to create or modify business objects without immediately saving the changes to the database. This is particularly useful for complex objects or when multiple steps are involved in creating or editing data.

Draft Lifecycle:

  • Edit: The user starts editing an existing object or creates a new one, and the data is saved to a draft.
  • Activate: The user confirms the changes, and the draft data is saved to the active database table.
  • Discard: The user cancels the changes, and the draft data is deleted.
  • Resume: The user returns to a previously started draft to continue editing.
  • Draft Implementation Examples:

    • Activate:

      • This method activates a draft, saving the changes to the active table.
      • It reads the draft data from the zztmfcustomer_d (draft table).
      • It copies the data to a structure (ls_customer).
      • It updates the zztmfcustomer (active table) with the data.
      • It deletes the draft record from zztmfcustomer_d.
      • It includes error handling for database operations.
      • Discard:

        • This method discards a draft, deleting the draft data.
        • It deletes the draft record from the zztmfcustomer_d table.
        • It includes error handling.
        • Draft functions is handled automatically in the RAP framework, all you need to is create a table like below and specify it in Behaviour Definition.
@EndUserText.label : 'Table to Store Customer details'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zztmfcustomer_d {

  key customer_id    : char10 not null;
  link               : char100;
  name               : char20 not null;
  status             : char20;
  statusreason       : char30;
  validfor           : datab;
  last_changed_at    : timestampl;
  locallastchangedat : timestampl;
  "%admin"           : include sych_bdl_draft_admin_inc;

}
​

ATTACHMENT HANDLING in RAP

@EndUserText.label : 'Customer Attachment'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zztmcustatt {

  key attach_id   : char10 not null;
  key customer_id : char10 not null;
  file_name       : char100 not null;
  file_type       : char20 not null;
  file_content    : abap.rawstring(999999);
  created_on      : timestampl;
  last_changed_at : timestampl;

}


METHOD create_Attachment.
    DATA: lt_attach TYPE TABLE OF zztmcustatt,
          lv_max_id TYPE zztmcustatt-attach_id.

*    " Determine next attachment id

*
    LOOP AT entities ASSIGNING FIELD-SYMBOL(<ls_entity>).
      DATA(lt_target) = <ls_entity>-%target.
        SELECT MAX( attach_id ) FROM zztmcustatt  where customer_id = @<ls_entity>-customer_id INTO _max_id.
    IF sy-subrc = 0.
      " Convert lv_max_id to a number, increment
      lv_max_id = lv_max_id + 1.
    ELSE.
      lv_max_id = '0000000001'. " initial value, formatted as needed
    ENDIF.
      LOOP AT lt_target ASSIGNING FIELD-SYMBOL(<ls_target>).
        APPEND VALUE #(
          attach_id    = lv_max_id
          customer_id  = <ls_entity>-customer_id   " Parent key from the Customer
          file_name    = <ls_target>-FileName
          file_type    = <ls_target>-FileType
          file_content = <ls_target>-Attachment
          created_on   = sy-datum && sy-uzeit   " or use GET TIME STAMP
        ) TO lt_attach.
        " Increment attachment key (format as needed)
        lv_max_id = lv_max_id + 1.
      ENDLOOP.
    ENDLOOP.

    IF lt_attach IS NOT INITIAL.
      INSERT zztmcustatt FROM TABLE _attach.
      " Map created attachments back
      LOOP AT lt_attach ASSIGNING FIELD-SYMBOL(<ls_att>).
        APPEND VALUE #( %tky = VALUE #( AttachId = <ls_att>-attach_id ) )
          TO mapped-Attachment.
      ENDLOOP.
    ENDIF.
  ENDMETHOD.

 Create a Service Definition and Service Binding to test the application using FIORI ELEMENTS.

  • Srivatsa_5-1745836461754.png
  • Srivatsa_8-1745837073298.png

    Creation of New Record with Draft Functionality & Attachment


     

    • The Records is not Created but its in Draft StatusSrivatsa_2-1746443022000.png

       

      Srivatsa_3-1746443021976.png
    • A new Attachment is uploaded and Created

       

      Srivatsa_4-1746443022086.png

       

       

Conclusion

In Part 2, we covered the implementation details of our Customer Management application. We explored the role of the local handler class in processing business logic, implemented draft functionality to enhance the user experience, and enabled attachment handling to manage files.

This two-part series provided a comprehensive guide to building a Customer Management application with unmanaged RAP. By understanding the concepts and examples presented here, you can create your own robust and user-friendly RAP applications. Remember to adapt the code and techniques to the specific requirements of your projects.

 

With this you can integrate your RAP application with Process Build Automation for Approval. A workflow handler class should be called in the determination of RAP to call the created Workflow. 

As of now, SAP BTP Trial has not provided integration part for free, it can be done only in Licensed mode.