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:

/wp-content/uploads/2014/02/se19_387507.png

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:

  1. Create Domain ZD_METHOD with CHAR 30.
  2. Create Data Element ZE_METHOD (Name of a method in a class) with Domain ZD_METHOD.
  3. Create Structure ZSTR_METHODS with one component CMPNAME type ZE_METHOD.
  4. 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:

/wp-content/uploads/2014/02/attrib_389364.png

Create an Instance Public method CHECK_METHOD_EXISTS with following parameters:

/wp-content/uploads/2014/02/par_389365.png

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:

/wp-content/uploads/2014/02/class_389468.png

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:


/wp-content/uploads/2014/02/ds_389424.png


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.


/wp-content/uploads/2014/02/str_389430.png

Then in transaction RSA6 I unhid the new filed so it is visible to BW:

/wp-content/uploads/2014/02/rsa6_389441.png

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:

/wp-content/uploads/2014/02/rsa3_389442.png

/wp-content/uploads/2014/02/result_389443.png

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

To report this post you need to login first.

5 Comments

You must be Logged on to comment or reply to a post.

  1. Sri Gadde

    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

    (0) 
    1. Pavol Feranec Post author

      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.

      (0) 
      1. Sri Gadde

        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.

        (0) 
        1. Pavol Feranec Post author

          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

          (0) 
    2. Bruno Garcia

      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

      (0) 

Leave a Reply