ABAP Blog Posts
cancel
Showing results for 
Search instead for 
Did you mean: 

The problem

When using AIF mapping, each field is processed stateless. This means that if a value is fetched for the mapping of one field and is required again for another field, it has to be determined repeatedsly. As a result, message processing time increases unnecessarily, even though the result of the underlying function module call could be reused.

In this post, we show how to provide an AIF interface with temporary memory by applying the singleton pattern in ABAP OO.

 

The solution

Since each message is processed within its own LUW, the singleton pattern is a suitable approach. By defining a class that stores its own instance as an attribute, each request for the instance first checks whether it already exists. A new instance is created only if no instance is available yet.

The get_instance( ) method

  METHOD _get_instance.
    IF _o_instance IS NOT BOUND.
      _o_instance = NEW #( ).
    ENDIF.
    ro_instance = _o_instance.
  ENDMETHOD.

The method returns the instance, which can then store values in its own attributes. Whenever a value needs to be determined, the corresponding attribute is checked first. The value is only fetched or calculated if the attribute is still empty. This ensures that each value is determined only once during the current processing context.

Using attributes to store values

In our specific scenario, a mapping value has to be retrieved from an external system outside SAP, which is a very expensive operation in terms of runtime. To avoid unnecessary repeated calls, we retrieve the data only once and store it in an attribute. For example, to determine the new values for sales organization, division, and distribution channel, we created an attribute that stores this data in an internal table: MT_SAP_ORG_ELEMENTS.

Whenever one of these values is required for mapping, we first check whether it is already available in the attribute. If so, we reuse the stored value instead of executing the expensive call repeatedly:

  METHOD get_sales_org.
    "1. Check if S/4-Value already available
    IF line_exists( me->mt_sap_org_elements[ sales_org_r3 = iv_sales_org_r3 ] ).
      "Value already exists in Attribute
       ...
      RETURN.
    ENDIF.

    "2. Get S/4-Value from Mapping
    APPEND LINES OF zcl_xxx=>get_sap_org_elements( ) TO me->mt_sap_org_elements.
    ...
  ENDMETHOD.
METHOD get_division.
    "1. Check if S/4-Value already available
    IF line_exists( mt_sap_org_elements[
                                sales_org_r3  = iv_sales_org_r3
                                div_r3        = iv_div_r3
                          ] ).
       "Value already exists in Attribute
       ...
       RETURN.
    ENDIF.

    "2. Get S/4-Value from Mapping
    APPEND LINES OF zcl_xxx=>get_sap_org_elements( ) TO me->mt_sap_org_elements.
    ...
  ENDMETHOD.
  METHOD get_distr_channel.
    "1. Check if S/4-Value already available
    IF line_exists( me->mt_sap_org_elements[
                                sales_org_r3      = iv_sales_org_r3
                                distr_channel_r3  = iv_distr_chan_r3
                              ] ).
       "Value already exists in Attribute
       ...
       RETURN.
    ENDIF.

    "2. Get S/4-Value from Mapping
    APPEND LINES OF zcl_xxx=>get_sap_org_elements( ) TO me->mt_sap_org_elements.
    ...
  ENDMETHOD.

 

The calling of these methods can be implemented in the required mapping-function-modules provided by AIF (/AIF/FILE_TEMPL_VALMAPPING):

" get the Instance (Singleton Pattern)
DATA(lo_instance) = zcl_interface_class=>_get_instance( ).

" value_in is in this example the R/3-sales order
value_out = lo_instance->get_sales_org( iv_sales_org_r3 = value_in )

This function module can now be customized in the field mapping of the interface in the source mapping:

Julia16_2-1786977652664.png

Now, whichever mapping of those three fields will be called first, is the only mapping, where a call to the external middleware will be executed. All the following field mappings will have the data from the middleware already available.

 

The destroy_instance( ) method

Finally, we added a destroy method to clear the instance. This is especially relevant when using the AIF test tool, where the analysis function can be executed multiple times within the same LUW. To ensure a clean start for each run, we created an initial mapping function that clears the instance attribute before processing begins.

  METHOD _destroy_instance.
    IF _o_instance IS BOUND.
      CLEAR _o_instance.
    ENDIF.
  ENDMETHOD.

The destroy-method gets called in an Init-Functionmodule (/AIF/FILE_TEMPL_INIT_MAPPING), which needs to be customized in the Interface-Definition:

Julia16_3-1786978144577.png

zcl_interface_class=>_destroy_instance( ).

 

Conclusion

The singleton pattern is a well-known concept in ABAP OO. Applied in the context of AIF, it can significantly improve the performance of the mapping process. By destroying the instance before the first call, it is ensured that the instance created afterwards is used only within the current message processing context.

In general, the singleton pattern can be useful whenever a process runs within the same LUW, for example in FI-CA. If you have experience with this approach or know other scenarios where this pattern can be beneficial, we would be happy if you shared them with us 😊

 

We hope this post provided a useful insight into how the performance of AIF mapping can be improved and offered some inspiration for applying the singleton pattern in similar scenarios.

Labels in this area