Wednesday, January 17, 2018

Using snapshots in Badi calls

Suppose you have a complex process in which a certain Badi plays an important part and you would like to save the attributes that are passed to this Badi, much like the option to save a dataset for a function in SE37, for further testing or analysis. This blog shows an easy way to do this by using the EXPORT and IMPORT statement.

For me a real life example of such a process involved a Badi for shopping cart approval in SAP Supplier Relationship Management (SRM). What made testing complex were the different technical components: a web interface for the end user and a workflow for the approval process that was, to make matters worse, triggered asynchronously.

I really wanted to isolate the Badi call so I could analyse and test it as a separate unit. So for this I needed a way to save a snapshot of all the attributes during the Badi call and a way to restart the Badi call with the saved snapshot.

Saving a snapshot

The EXPORT  TO DATABASE statement provides an easy way to group several data objects and save them in a single database record. Supported data objects include simple types, structures, internal tables and complex structures. Object references are not directly supported but they might be serializable to a XSTRING value Using Serializable Objects in ABAP. You can create your own database table but it is easier to reuse the existing INDX table. It supports a so-called region (field RELID) and if you stick to a Z-range you're pretty safe not to interfere with other processes.

Provide the Badi with a little piece of additional code:

  if sy-cprog <> 'Z_BADI_TESTER'. "Don't export when called by the test program
    "Fill the header record
     data(ls_indx) = value indx(
       relid = 'Z0'    "region
       srtfd = 'DEMO'  "unique identifier
       aedat = sy-datum
       usera = sy-uname ).

    "Save all the attributes
    export
      p01 from flt_val
      p02 from is_header
      p03 from it_item
      to database indx(z0) from ls_indx id ls_indx-srtfd.
  endif.


In my example I'm just numbering the parameters P01, P02 and P03. It doesn't matter what you call them as long as you assign them to the correct variables on import. The result is a record in table INDX. Not much to see here, just header data, the real data is hidden in field CLUSTD which has a RAW format and cannot be displayed in SE16.



Calling the Badi using the snapshot

Next thing we need is a way to restore the saved snapshot. We have to build a little program to do the job. It just has to do two things: restore the data from the INDX table and then pass it on to the Badi.

  "Restore all the attributes
  import
    p01 to flt_val
    p02 to is_header
    p03 to it_item
    from database indx(z0) id 'DEMO'.

  "Pass them on to the Badi
  new zcl_im_bbp_wfl_approv_badi( )->if_ex_bbp_doc_change_badi~bbp_sc_change(
    exporting
      flt_val   = flt_val
      is_header = is_header
      it_item   = it_item
    importing
      es_header = data(es_header)
      et_item   = data(et_item) ).


The power of the EXPORT/IMPORT statement is its ability to save a whole set of variables in one go where it doesn't matter how complex the variable types are. This complexity is completely handled by the system. One aspect to consider is that the type definitions must be exactly the same during import and export otherwise short dumps occur.

Another use case might be a call to an external interface and you want to temporarily replace the external data by previously saved data.