Post

Backup BRF+ decision tables to Git

Backup BRF+ decision tables to Git

Here’s an improved version of the article with more explanations and clearer language:


While SAP BRF+ provides versioning for its objects, we decided to create an additional backup mechanism for the decision tables using Git. This backup solution leverages our existing GitLab API along with the BRF+ API to extract decision table data in XML format.

Basic Setup

To implement this solution, we created a Z-table to store relevant BRF+ applications. This table helps to manage which applications should be backed up. We named this table ZBC_BRF_GIT_APPL and defined it with the following fields:

  • MANDT (Type: MANDT)
  • APPLICATION (Type: FDT_APPLICATION)

In addition to this, we created another table to store the timestamp of the last export, helping us avoid unnecessary duplicates during future backups. This table is called ZBC_BRF_GIT_TIME and contains the following fields:

  • MANDT (Type: MANDT)
  • APPLICATION (Type: FDT_APPLICATION)
  • NAME (Type: FDT_NAME)
  • TIMESTAMP (Type: FTD_TIMESTAMP)

Finally, we needed to create a GitLab repository to store the backup files.

Retrieving the Decision Tables for Each Application

The following ABAP method retrieves the decision tables for each BRF+ application that we want to back up.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
METHOD get_decision_tables.
  DATA: ls_sel    TYPE if_fdt_query=>s_selection.

  DATA: lt_sel   TYPE if_fdt_query=>ts_selection,
        lt_names TYPE if_fdt_query=>ts_name.

  DATA: lo_decision_table TYPE REF TO cl_fdt_decision_table.

  " Retrieve all decision tables for the specified application
  ls_sel-queryfield = if_fdt_admin_data_query=>gc_fn_application_id.
  ls_sel-sign   = 'I'.
  ls_sel-option = 'EQ'.
  ls_sel-low    = gv_application_id.
  INSERT ls_sel INTO TABLE lt_sel.

  ls_sel-queryfield = if_fdt_admin_data_query=>gc_fn_object_type.
  ls_sel-sign = 'I'.
  ls_sel-option = 'EQ'.
  ls_sel-low = if_fdt_constants=>gc_object_type_expression.
  INSERT ls_sel INTO TABLE lt_sel.

  go_factory->get_query( )->select_data(
    EXPORTING
        its_selection = lt_sel
    IMPORTING
      eta_data       = lt_names 
  ).

  " Filter out unchanged decision tables
  LOOP AT lt_names ASSIGNING FIELD-SYMBOL(<lt_name>).
    TRY.
        " Check if the item is a decision table
        lo_decision_table ?= go_factory->get_expression( <lt_name>-id ).

        " Get versions of the decision table and check if it has been modified
        lo_decision_table->if_fdt_admin_data~get_versions( 
          IMPORTING 
            ets_version = DATA(lt_version) 
        ).

        " Select the most recent version of the decision table
        LOOP AT lt_version ASSIGNING FIELD-SYMBOL(<version>) WHERE state = 'A'.
        ENDLOOP.

        CHECK sy-subrc EQ 0.

        " Verify the last backup timestamp
        SELECT SINGLE *
          FROM zbc_brf_git_time
          INTO @DATA(ls_zbc_brf_git_time)
          WHERE application EQ @gv_application_name
            AND name EQ @<lt_name>-name.
        IF sy-subrc EQ 0 AND ls_zbc_brf_git_time-timestamp EQ <version>-trtimestamp.
          CONTINUE.

        ENDIF.

        " Append the decision table to the list of tables for export
        APPEND VALUE #( id = <lt_name>-id name = <lt_name>-name timestamp = <version>-trtimestamp )
          TO rt_tables.

      CATCH cx_root.

    ENDTRY.

  ENDLOOP.

ENDMETHOD.

Explanation:

  • Data Retrieval: The method queries the BRF+ system to fetch all decision tables for a given application. It filters based on the application ID and the object type (decision tables).
  • Version Checking: The method checks whether the decision table has been updated by comparing the current version to the last backed-up version.
  • Avoiding Duplicate Exports: Before exporting, it ensures that the decision table has changed since the last backup by comparing the timestamps.

Exporting the Decision Table as XML

Once we have the list of updated decision tables, the next step is to export them as XML. This code snippet handles the conversion of the decision table into XML format.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
DATA(lo_dxch) = go_factory->get_data_exchange( ).

TRY.
    lo_dxch->export_xml(
      EXPORTING 
        its_object_id  = VALUE #( ( <table>-id ) )
        iv_xml_version = if_fdt_data_exchange=>gc_xml_version
        iv_schema      = if_fdt_data_exchange=>gc_xml_schema_type_external
        iv_deep        = abap_false
      IMPORTING 
        ev_string      = DATA(lv_string)
        et_message     = DATA(lt_msg) 
    ).

    " Format the XML output for readability
    DATA(lo_reader) = cl_sxml_string_reader=>create( 
      cl_bcs_convert=>string_to_xstring( lv_string ) 
    ).

    DATA(lo_writer) = CAST if_sxml_writer( 
      cl_sxml_string_writer=>create( 
        type     = if_sxml=>co_xt_xml10
        encoding = 'UTF-8' ) 
    ).

    lo_writer->set_option( if_sxml_writer=>co_opt_linebreaks ).
    lo_writer->set_option( if_sxml_writer=>co_opt_indent ).

    lo_reader->next_node( ).
    lo_reader->skip_node( lo_writer ).

    " Convert the formatted XML back into a xstring
    DATA(lv_xml) = CAST cl_sxml_string_writer( lo_writer )->get_output( ).

    " Send the XML data to GitLab
    ls_file-path_and_name = |{ gv_application_name }/{ <table>-name }.xml|.
    ls_file-content = lv_xml.
    APPEND ls_file TO lt_files.

    " Update the backup timestamp in the database
    ls_zbc_brf_git_time-application = gv_application_name.
    ls_zbc_brf_git_time-name = <table>-name.
    ls_zbc_brf_git_time-timestamp = <table>-timestamp.
    MODIFY zbc_brf_git_time FROM ls_zbc_brf_git_time.

  CATCH cx_root.

ENDTRY.

Explanation:

  • XML Export: The method exports the decision table as XML, using the export_xml function. It then formats the XML output to ensure it’s well-structured.
  • GitLab Integration: The XML is saved to a file and prepared for upload to the GitLab repository.
  • Updating the Timestamp: After the table is exported, the timestamp of the backup is updated in the ZBC_BRF_GIT_TIME table to prevent redundant exports in the future.

Sending the Files via GitLab API

The final step is sending the backed-up decision tables to the GitLab repository. We use the GitLab API to commit and push the files.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
IF lt_files IS NOT INITIAL.
  TRY.
      lo_gitlab->send_files( iv_commit_message = |Backup of decision tables for application { gv_application_name }|
                              it_files          = lt_files 
      ).
      
    CATCH zcx_gitlab INTO DATA(lo_excp).
      FORMAT COLOR COL_NEGATIVE.
      WRITE: / 'Could not export files:', lo_excp->get_text( ).
      FORMAT COLOR OFF.

  ENDTRY.

ENDIF.

Explanation:

  • GitLab Commit: The files are sent to the GitLab repository with a commit message indicating that they are backups of the decision tables.
  • Error Handling: If there is any issue with the GitLab API call, the error message is displayed.

This setup provides a simple and efficient way to back up SAP BRF+ decision tables to GitLab, ensuring version control and avoiding duplication of exported data. By integrating the GitLab API and the BRF+ API, we create a reliable backup solution for critical decision-making data.

This post is licensed under CC BY 4.0 by the author.