Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
kenichi_unnai
Advisor
Advisor

This is a part of the implementation details of How To... Implement End-to-End Push Notifications with HCPms and SAP Gateway.


Tips & Tricks - Implementing Subscribable OData services & Notification API in ABAP

You have a complete e2e landscape for push. Let's talk about how to implement "Subscribable" OData services with SAP Gateway and trigger the notification from ABAP application.

Building Subscribable OData services

If you don't have any OData services nor ever have coding experiences with SAP Gateway, here's a beginner level crash course of how to build your OData CRUD services. From now on let's assume you have done the CRUD implementation with TravelAgency data.

#1 - OData CRUD Crash Course - Getting ready with offline store

Now that you have functional OData services, go to the transaction code SEGW - Open "Data Model" > "Entity Sets", find your collection you want to make subscribable. You'll see the checkbox "Subscribable". Tick it in.

Click on the project and select "Generate Runtime".

Find "Runtime Artifacts" and select "...DPC_EXT" and "Go to ABAP Workbench".

In the ABAP Workbench, you should be able to find "CHECK_SUBSCRIPTION_AUTHORITY" in the "Methods" > "Inherited Methods". Select it and "Redefine". Simply you save it - this is the place for extra authorization check to access "/IWBEP/D_MGW_SUB" table. But for this case you can leave it empty implementation. (= anyone can subscribe)

In the "Runtime Artifacts", select "...MPC_EXT" and "Go to ABAP Workbench".

Find "DEFINE" in the "Methods" > "Inherited Methods". Select it and "Redefine".  And type in a single line of "super->define( )." Save it.

Time to check if you made it subscribable. In the transaction code SEGW, start a Gateway Client via the system in the "Service Maintenance".

Execute it and you should be able to confirm two new collections of "SubscriptionCollection" and "NotificationCollection".

Tip - if you still don't see them, most likely your client is seeing cached metadata. Please try following:


  • Clear the cache in Gateway Hub: tx code /IWFND/CACHE_CLEANUP
  • Clear in Backend: tx code /IWBEP/CACHE_CLEANUP
  • (Recommended during the development) Deactivate caching: tx code SPRO "SAP NetWeaver" > "Gateway" > "OData Channel" > Administration > Cache Settings > Metadata


Now your favorite OData services became subscribable!

Using Notification API to trigger Push event

SAP Gateway provides a notification API that facilitates sending notifications from the back end when a back-end event is triggered. The necessaryset of API calls to send an appropriate notification once a back-end business object event is triggered are listed below. Integrate the appropriate code for these calls into the standard processing of your ABAP logic - such as during OData CUD methods or in the SAP business object via an appropriate user exit or BADI.

  1. Call static method /IWBEP/CL_MGW_SUB_REGISTRY=>GET_SUBSCRIPTION_REGISTRY( ) to get the instance of the subscription registry.
  2. Call method GET_SUBSCRIPTIONS( ) of the subscription registry, and provide the model group name and the collection for the notifications of the current business application.
  3. Call static method /IWBEP/CL_MGW_NOTIF_PUBLISHER=>GET_NOTIFICATION_PUBLISHER() to get the instance of the notification publisher.
  4. Call method CREATE_NOTIFICATION_ENDPOINTS() of the publisher instance, and provide the data structure you want to send and the list of subscriptions returned by the registry. (Note - formal help document: /IWBEP/IF_MGW_NOTIF_PUBLISHER - SAP NetWeaver Gateway - SAP Library)
  5. Call method SEND_NOTIFICATIONS() of the publisher for each notification endpoint.

Tip - Some remarks with CREATE_NOTIFICATION_ENDPOINTS(). This is specific with /Notification/ Push URL of HCPms:


  • IS_DATA - Mandatory, but you could set any data (this data is originally meant for a HTTP body - but HCPms only sends the header data).
  • IV_TYPE - Mandatory, but it doesn't matter if it is "ID" or "DATA". This value is used to send the HTTP Body payload that is ignored by HCPms.
  • IR_POKE_DATA - If you want to send any additional data (such as OData Entity, email address), use this param - it will be alive in the header.
  • IV_ENTRIES_OF_INTEREST - This is a "Badge" value for push client API.

Please have a look at the complete code in the Appendix to go through those steps with push information (the push will send "Created!" text and its OData entity data), it is intended for embedding in the OData's "Create" method, so that when Create occurs, it sends the notification to the subscribers.

As another sample, ABAP report “/IWBEP/R_MGW_PUSH_TEST” demonstrates the notification transmission with FLIGHT sample data.

The notification format can be ATOM XML or JSON, which you must specify when you send the subscription request. For example, to receive notifications in the JSON format, send the value of the “Accept” HTTP header to “application/json”. By default, ATOM XML-formatted notifications are used. If your OData client creates a subscription via JSON, here's how it looks in the subscription table (NOTIF FORMAT field):


Note - XML format is preferred with /Notification/ Push URL. (JSON would not work)

Official help doc: SAP Gateway Notification Support

Appendix: Sample Code to Trigger Push

* Fixed values for /IWBEP/D_MGW_SUB table
  CONSTANTS: lc_technical_group_name TYPE /iwbep/med_grp_technical_name VALUE 'Z_TRAVELAGENCY_SRV',                  
             lc_group_version        TYPE /iwbep/med_grp_version        VALUE 0001,
             lc_collection           TYPE /iwbep/mgw_sub_collection     VALUE 'TravelAgencySet',
* The push text message
             lc_text                 TYPE string                        VALUE 'Created!'.
* Vars for Subscriptions
  DATA: lo_sub_registry  TYPE REF TO /iwbep/if_mgw_sub_registry,
        lt_subscriptions TYPE        /iwbep/t_mgw_sub_data,
* Vars for Notifications
        lo_notification_publisher TYPE REF TO /iwbep/if_mgw_notif_publisher,
        ls_notification_endpoint  TYPE /iwbep/if_mgw_notif_publisher=>ty_s_notification_endpoint,
        lt_notification_endpoints TYPE /iwbep/if_mgw_notif_publisher=>ty_t_notification_endpoint,
        lr_data                   TYPE REF TO data,
        lv_notification_type      TYPE char1,
        lx_mgw_tech_exception     TYPE REF TO /iwbep/cx_mgw_tech_exception.

  FIELD-SYMBOLS: <ls_subscription> TYPE /iwbep/s_mgw_sub_data.

* Permission for access to /IWBEP/D_MGW_SUB table
  AUTHORITY-CHECK OBJECT 'S_TABU_DIS'
    ID 'ACTVT'     FIELD '02' " Activity: 02: Create, change, or delete
    ID 'DICBERCLS' FIELD 'IWAD'. " Authorization Group: IW Admin
  IF sy-subrc NE 0.
    RAISE EXCEPTION TYPE /iwbep/cx_mgw_tech_exception
      EXPORTING
        textid = /iwbep/cx_mgw_tech_exception=>missing_authorization.
  ENDIF.

* Type is either ID or Data (Full Payload) - for HCPms, it doesn't matter if it is "ID" or "DATA",
* as HTTP body will be ignored by /Notification/ Push URL of HCPms
  lv_notification_type = /iwbep/if_mgw_notif_publisher=>gcs_notification_types-id.
* Obtain /IWBEP/D_MGW_SUB table
  lo_sub_registry = /iwbep/cl_mgw_sub_registry=>get_subscription_registry( ).
* Obtain a list of subscribers
  lt_subscriptions = lo_sub_registry->get_subscriptions(
                      iv_internal_service_name    = lc_technical_group_name
                      iv_internal_service_version = lc_group_version
                      iv_collection               = lc_collection ).
* Object to push
  lo_notification_publisher = /iwbep/cl_mgw_notif_publisher=>get_notification_publisher( ).

  LOOP AT lt_subscriptions ASSIGNING <ls_subscription>.
    IF  <ls_subscription>-language IS INITIAL.
      <ls_subscription>-language = sy-langu.
    ENDIF.
  ENDLOOP.
* For this case ls_entity set is already declared as "ls_entityset TYPE stravelag"
* entity data will be sent to the push client
  GET REFERENCE OF ls_entityset INTO lr_data.
* Set the required params for push
  lo_notification_publisher->create_notification_endpoints(
    EXPORTING
* those two value are mandatory but ignored
      is_data           = lr_data
      iv_type           = lv_notification_type
* type "create"
      iv_operation_type = /iwbep/if_mgw_notif_publisher=>gcs_operation_types-create
* push text
      iv_text           = lc_text
* additional info (this example is entity data)
      ir_poke_data = lr_data
* "Badge" value
*      iv_entries_of_interest =
      it_subscriptions  = lt_subscriptions
    IMPORTING
      et_notification_endpoints = lt_notification_endpoints ).

* Push the text message to relevant subscribers - this will create a bgRFC queue
  LOOP AT lt_notification_endpoints INTO ls_notification_endpoint.
    TRY.
      lo_notification_publisher->send_notifications(
              is_notification_endpoint = ls_notification_endpoint ).
    CATCH
      /iwbep/cx_mgw_tech_exception INTO lx_mgw_tech_exception.
    ENDTRY.
  ENDLOOP.
7 Comments