While SAP BRF+ offers versioning of its objects, we decided to create an additional backup of the decision tables via Git. For this backup we used our existing GitLab API in combination with the BRF+ API (for extracting the decision table data to XML).
Basic setup
To make this work, we need a Z-table which contains all relevant BRF+ applications. We created the table ZBC_BRF_GIT_APPL with the following fields:
- MANDT TYPE MANDT
- APPLICATION TYPE FDT_APPLICATION
and a table where we store the timestamp of the last export (to avoid unnecessary duplicates) ZBC_BRF_GIT_TIME
- MANDT TYPE MANDT
- APPLICATION TYPE FDT_APPLICATION
- NAME TYPE FDT_NAME
- TIMESTAMP TYPE FTD_TIMESTAMP
Furthermore we needed to create a GitLab repository which will contain all backups.
Get the decision tables for each application
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
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.
" all decision tables for that 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 that expression is a decision table
lo_decision_table ?= go_factory->get_expression( <lt_name>-id ).
" check if it has been changed since the last backup
lo_decision_table->if_fdt_admin_data~get_versions(
IMPORTING
ets_version = DATA(lt_version) ).
" use highest version
LOOP AT lt_version ASSIGNING FIELD-SYMBOL(<version>) WHERE state = 'A'.
ENDLOOP.
CHECK sy-subrc EQ 0.
" check the last backup
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 VALUE #( id = <lt_name>-id name = <lt_name>-name timestamp = <version>-trtimestamp )
TO rt_tables.
CATCH cx_root.
ENDTRY.
ENDLOOP.
ENDMETHOD.
Export the decision table as XML
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
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) ).
" create a well formatted XML
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 ).
" and write it back to a xstring
DATA(lv_xml) = CAST cl_sxml_string_writer( lo_writer )->get_output( ).
" and send it to git
ls_file-path_and_name = |{ gv_application_name }/{ <table>-name }.xml|.
ls_file-content = lv_xml.
APPEND ls_file
TO lt_files.
" and remember last saved version
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.
Send the files via GitLab API
1
2
3
4
5
6
7
8
9
10
11
12
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.