Enhancement of BW DataSources using BAdI
In BW there are scenarios where you have to enhance an existing Datasource with one or more fields and program a logic to fill those fields in or change the extraction in any other way. Traditionally a developer can use a SAP Enhancement RSAP0001 in a custom project Include in transaction CMOD and put all coding inside:
Function Module | Include | Description |
---|---|---|
EXIT_SAPLRSAP_001 |
ZXRSAU01 | Transaction data |
EXIT_SAPLRSAP_002 | ZXRSAU02 | Attributes, texts |
EXIT_SAPLRSAP_003 | ZXRSAU03 | Texts |
EXIT_SAPLRSAP_004 | ZXRSAU04 | Hierarchies |
This approach can create a lot of mess when you have multiple datasource enhancements like that inside one Include.
I was searching for a better solution which would be flexible and separate datasource enhancements in a better way. I stumbled upon a white paper from Flávio Peres which gave me an idea how to do that:
http://scn.sap.com/docs/DOC-11246
There were some blank spots where I was not sure how to approach it so I decided to enhance it and document the whole solution again here. I hope it can be quickly used by any developer without having to think about the framework itself.
Everything starts from an SAP classical BaDI RSU5_SAPI_BADI. You can see it in transaction SE19. There we start defining a new implementation:
When you specify your own implementation and its description you will see the system added an interface IF_EX_RSU5_SAPI_BADI into the implementation. This Interface adds 2 methods into the implementation class:
Method Name | Description |
---|---|
DATA_TRANSFORM | Method for General Data Transfer |
HIER_TRANSFORM | Method for Hierarchy Data Transfer |
The method DATA_TRANSFORM is responsible for handling all classical datasources. The method HIER_TRANSFORM handles Hierarchy extractions which will be covered in detail in some of my future blogs.
First we copy the method DATA_TRANSFORM with all its parameters into a new method called _TEMPLATE_DATASOURCE and make it a “Static method”. That will be used as a pattern for all datasource enhancements.
Now double-click on the original DATA_TRANSFORM method and insert following code:
METHOD if_ex_rsu5_sapi_badi~data_transform.
**********************************************************
* To implement an exit for a
* datasource create your own method by copying the
* method _TEMPLATE_DATASOURCE and rename it to the name
* of your datasource. In case you enhance a Business
* Content datasource skip the 0 at the beginning (e.g.
* Datasource 0FI_AR_3 -> Method FI_AR_3
* The method is then called by the Exit Framework
*********************************************************
DATA: ls_oltpsource TYPE rsaot_s_osource,
lo_data TYPE REF TO data,
lv_method TYPE seocmpname.
FIELD-SYMBOLS: <lt_data> TYPE STANDARD TABLE.
* check if any data is extracted
CHECK c_t_data IS NOT INITIAL.
*retrieve information about the Datasource
CALL FUNCTION 'RSA1_SINGLE_OLTPSOURCE_GET'
EXPORTING
i_oltpsource = i_datasource
i_objvers = 'A'
IMPORTING
e_s_oltpsource = ls_oltpsource
EXCEPTIONS
no_authority = 1
not_exist = 2
inconsistent = 3
OTHERS = 4.
IF sy-subrc <> 0.
EXIT.
ENDIF.
* create data for Extract Structure
CREATE DATA lo_data TYPE TABLE OF (ls_oltpsource-exstruct).
ASSIGN lo_data->* TO <lt_data>.
ASSIGN c_t_data TO <lt_data>.
* get method name for datasource
lv_method = i_datasource.
CASE lv_method(1).
WHEN '0' OR '2'.
* shift by one character as methods can't start with a number
SHIFT lv_method.
WHEN OTHERS.
"Do nothing
ENDCASE.
* check method is implemented
CHECK check_method_exists( lv_method ) = 'X'.
*execute the Datasource enhancement
CALL METHOD (lv_method)
EXPORTING
i_datasource = i_datasource
i_updmode = i_updmode
i_t_select = i_t_select
i_t_fields = i_t_fields
CHANGING
c_t_data = <lt_data>
c_t_messages = c_t_messages.
ENDMETHOD.
This method will always be called when an extraction starts but if there is no enhancement for the extraction it will end doing nothing.
If you check the syntax of the code you will end up with an error of unknown method CHECK_METHOD_EXISTS. We will create it in the next moment.
First I created some dictionary objects to have my own table in the class:
- Create Domain ZD_METHOD with CHAR 30.
- Create Data Element ZE_METHOD (Name of a method in a class) with Domain ZD_METHOD.
- Create Structure ZSTR_METHODS with one component CMPNAME type ZE_METHOD.
- Create a Table Type ZTT_METHODS with Liny Type ZSTR_METHODS which will be a Sorted Table with a key field CMPNAME.
Now with this we can create an attribute GT_METHODS inside our class ZBW_EXTRACTOR_BADI to store the names of methods there:
Create an Instance Public method CHECK_METHOD_EXISTS with following parameters:
With all this we can place a simple code inside the method:
METHOD check_method_exists.
*reads global attribute table with all methods and retrieves a flag if a match is found
READ TABLE gt_methods WITH KEY cmpname = iv_method TRANSPORTING NO FIELDS.
IF sy-subrc = 0.
rv_exist = 'X'. "method found
ELSE.
CLEAR rv_exist.
ENDIF.
ENDMETHOD.
The global table with method names will be filled in a class constructor which you need to create with following code.
METHOD constructor.
DATA: lo_class TYPE REF TO cl_oo_object,
lt_methods TYPE seo_methods,
ls_methods_global LIKE LINE OF gt_methods,
lo_descr_ref TYPE REF TO cl_abap_typedescr,
lv_class TYPE seoclsname.
FIELD-SYMBOLS: <fs_methods> LIKE LINE OF lt_methods.
*retrieve description of the class
lo_descr_ref = cl_abap_classdescr=>describe_by_object_ref( me ).
lv_class = lo_descr_ref->get_relative_name( ).
TRY.
CALL METHOD cl_oo_object=>get_instance
EXPORTING
clsname = lv_class
RECEIVING
result = lo_class.
CATCH cx_class_not_existent.
ENDTRY.
IF sy-subrc = 0.
*Read all methods
CALL METHOD lo_class->get_methods
EXPORTING
public_methods_only = seox_false
instance_methods_only = seox_false
RECEIVING
result = lt_methods.
LOOP AT lt_methods ASSIGNING <fs_methods>.
ls_methods_global-cmpname = <fs_methods>-cmpname.
INSERT ls_methods_global INTO TABLE gt_methods.
ENDLOOP.
ENDIF.
ENDMETHOD.
The last thing is to insert a sample code into the _TEMPLATE_DATASOURCE method:
METHOD _template_datasource.
**********************************************************
* To implement an exit for a
* datasource create your own method by copying the
* method _TEMPLATE_DATASOURCE and rename it to the name
* of your datasource. In case you enhance a Business
* Content datasource skip the 0 at the beginning (e.g.
* Datasource 0FI_AR_3 -> Method FI_AR_3
* The method is then called by the Exit Framework
*********************************************************
** Data Definition
* DATA: lt_sourcepackage TYPE TABLE OF zoxnsp0107. "change the structure according to DS
*
* FIELD-SYMBOLS: <fs_sourcepackage> TYPE zoxnsp0107.
*
* lt_sourcepackage[] = c_t_data[].
*
**Custom coding starts from here.
* CLEAR c_t_data.
*
* DELETE lt_sourcepackage WHERE carrid(1) NE 'A'.
*
* SELECT a~carrid
* a~carrname
* a~currcode
* a~url
* b~connid
* INTO CORRESPONDING FIELDS OF TABLE c_t_data
* FROM scarr AS a LEFT OUTER JOIN spfli AS b ON
* a~carrid = b~carrid
* FOR ALL ENTRIES IN lt_sourcepackage WHERE
* a~carrid = lt_sourcepackage-carrid.
* IF sy-subrc = 0.
*
* ELSE.
* "Error handling
* ENDIF.
ENDMETHOD.
Now you should have everything needed for a successful activation of the class and the framework. The class should look like this:
The framework is now complete and we can test it by using any existing Datasource or with a simple one shown below.
As a test I created a simple datasource ZSCARR to extract data from the SAP FLIGHT demo database:
It is a simple datasource over table SCARR (which you can fill using SAP report SAPBC_DATA_GENERATOR). As a sample enhancement I added a field CONNID from table SPFLI as an append Structure.
Then in transaction RSA6 I unhid the new filed so it is visible to BW:
You need to copy the ExtractStruct. from here to the method. The method is simply a copy of the _TEMPLATE_DATASOURCE method to a method ZSCARR. Once you adjust the local table inside and activate you can see the result in transaction RSA3:
I hope this can help you create clean and flexible enhancements for all your extractions. Feel free to suggest any improvements to this approach.
Best regards,
Pavol
Hi,
Have you tried using HIER_TRANSFORM in BW 7.3 yet.
We have been using these methods for both data and hier. transformations. After the upgrade to 7.3, HIER_TRANSFORM no longer gets invoked.
-Sri
Hi,
you can check if the hierarchy is flexible. In RSA1 in Datasource extraction tab there is a flag Hierarchy is flexible. In that case it is using the new structure and you cannot use HIER_TRANSFORM as SAP note 691154 says.
Hi Pavol,
Could you please elaborate? I can't find this flag anywhere in BW 7.3 on the datasource.
There is an Extraction tab for the ECC hierarchy datasource however, there is no flag as such.
Am I missing something? The 691154 seems to be pretty old and doesn't seem to be for BW 7.3.
Appreciate your response.
Hi Sri,
sorry it took so long but I have a solution for you. All you need to do is to create a project in transaction CMOD and add Enhancement RSAP0001 into it. Then you go into its Function Module EXIT_SAPLRSAP_004 and doubleclick on Include ZXRSAU04. Inside it you can call the method and it will go there:
DATA: lo_class TYPE REF TO <YOUR CLASS NAME>.
DATA: li_t_langu TYPE sbiwa_t_langu,
lc_t_hietext TYPE rsap_t_hietext,
lc_t_hienode TYPE rsap_t_hienode,
lc_t_foldert TYPE rsap_t_foldert,
lc_t_hieintv TYPE rsap_t_hieintv,
lc_t_messages TYPE rsu5_t_messages.
CREATE OBJECT lo_class.
li_t_langu[] = i_t_langu[].
lc_t_hietext[] = c_t_hietext[].
lc_t_hienode[] = c_t_hienode[].
lc_t_foldert[] = c_t_foldert[].
lc_t_hieintv[] = c_t_hieintv[].
lc_t_messages[] = c_t_messages[].
CALL METHOD lo_class->if_ex_rsu5_sapi_badi~hier_transform
EXPORTING
i_datasource = i_datasource
i_s_hieflag = i_s_hieflag
i_s_hier_sel = i_s_hier_sel
i_t_langu = li_t_langu
CHANGING
c_t_hietext = lc_t_hietext
c_t_hienode = lc_t_hienode
c_t_foldert = lc_t_foldert
c_t_hieintv = lc_t_hieintv
c_t_messages = lc_t_messages
EXCEPTIONS
rsap_badi_exit_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
Please let me know if this helped you.
Thanks.
Cheers,
Pavol
Hi Sri,
Maybe you don't need it anymore, but for others, please check note 1997720. It solves a problem regarding hierarchy extraction with this BADI.
Kind regards,
Garcia