software, software.sap

ABAP Tip: Converting Function Module Exceptions to Exception Classes

1464-ppt

Although function modules belong to the era of procedural programming, we all need to use them from time to time. While most BAPI’s usually return error messages in a clean internal table format, many other function modules return classical exceptions.

If you are calling a function within a class method, you might have a hard time converting those classical exceptions to class based exceptions – meaning exception classes.

I have written an exception class which automatically converts any function module exception to a class based exception. Here is the source code:

CLASS zcx_bc_function_subrc DEFINITION
 PUBLIC
 INHERITING FROM cx_static_check
 FINAL
 CREATE PUBLIC .

 PUBLIC SECTION.

 INTERFACES if_t100_message .

 CONSTANTS:
   BEGIN OF subrc_error," Function &1 error &2 : &3 - &4
     msgid TYPE symsgid VALUE 'ZBC',
     msgno TYPE symsgno VALUE '130',
     attr1 TYPE scx_attrname VALUE 'FUNCNAME',
     attr2 TYPE scx_attrname VALUE 'SUBRC',
     attr3 TYPE scx_attrname VALUE 'PARAM',
     attr4 TYPE scx_attrname VALUE 'STEXT',
   END OF subrc_error.

 DATA: 
   funcname TYPE funct-funcname,
   subrc TYPE sysubrc,
   param TYPE funct-parameter,
   stext TYPE funct-stext.

 METHODS constructor
   IMPORTING
     !textid LIKE if_t100_message=>t100key OPTIONAL
     !previous LIKE previous OPTIONAL
     !funcname TYPE funct-funcname OPTIONAL
     !subrc TYPE sysubrc DEFAULT sy-subrc
     !param TYPE funct-parameter
     !stext TYPE funct-stext.

 CLASS-METHODS raise_if_sysubrc_not_initial
   IMPORTING
     !iv_funcname TYPE funct-funcname
   RAISING
     zcx_bc_function_subrc.

 PROTECTED SECTION.
 PRIVATE SECTION.
ENDCLASS.



CLASS zcx_bc_function_subrc IMPLEMENTATION.

 METHOD constructor.
   CALL METHOD super->constructor
     EXPORTING
       previous = previous.
   CLEAR me->textid.
   IF textid IS INITIAL.
     if_t100_message~t100key = if_t100_message=>default_textid.
   ELSE.
     if_t100_message~t100key = textid.
   ENDIF.

   me->funcname = funcname.
   me->subrc = subrc.
   me->param = param.
   me->stext = stext.
 ENDMETHOD.

 METHOD raise_if_sysubrc_not_initial.

   CHECK sy-subrc IS NOT INITIAL.

   DATA(lv_subrc_bak) = sy-subrc.

   SELECT SINGLE parameter INTO @DATA(lv_parameter)
     FROM fupararef
     WHERE funcname EQ @iv_funcname
       AND paramtype EQ @abap_true
       AND pposition EQ @lv_subrc_bak.

   SELECT SINGLE stext INTO @DATA(lv_stext)
     FROM funct
     WHERE spras EQ @sy-langu
       AND funcname EQ @iv_funcname
       AND parameter EQ @lv_parameter
       AND kind EQ @abap_true.

   IF sy-subrc NE 0.
     SELECT SINGLE stext INTO @lv_stext
       FROM funct
       WHERE funcname EQ @iv_funcname
         AND parameter EQ @lv_parameter
         AND kind EQ @abap_true.
   ENDIF.

   RAISE EXCEPTION TYPE zcx_bc_function_subrc
     EXPORTING
       funcname = iv_funcname
       param = lv_parameter
       stext = lv_stext
       subrc = lv_subrc_bak
       textid = zcx_bc_function_subrc=>subrc_error. 

 ENDMETHOD.

ENDCLASS.

Here is an example of making this exception class useful.

CLASS zcl_sample DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    METHODS sample_method RAISING zcx_bc_function_subrc.
  PRIVATE SECTION.
  PROTECTED SECTION.
ENDLCASS.

CLASS zcl_sample IMPLEMENTATION.

  METHOD sample_method.

    CALL FUNCTION 'ZFUNCTION'
      EXPORTING
        IV_PARAM1     = 'DUMMY'
      EXCEPTIONS
        some_error    = 1
        another_error = 2
        OTHERS        = 3
      ##FM_SUBRC_OK .

    zcx_bc_function_subrc=>raise_if_sysubrc_not_initial( 'ZFUNCTION' ).

  ENDMETHOD.

ENDCLASS.

The static method RAISE_IF_SYSUBRC_NOT_INITIAL will do nothing if SY-SUBRC is initial. Otherwise, it will determine the details of the function exception and raise a class based exception using that information.

Since the static method is based on SY-SUBRC, it must be placed immediately after the function call – before anything else changes SY-SUBRC.

The pragma ##FM_SUBRC_OK tells the ABAP checker that we intentionally didn’t check SY-SUBRC after the function call. We check it within the static method, but the checker wouldn’t know that.

The advantage of this method is; you don’t need to develop a custom class based exception for each function module. It would simply work with any function. The disadvantage is; it consolidates all exceptions into a single class (ZCX_BC_FUNCTION_SUBRC) so the details of the error are not easy to determine programatically. The details of the functional exception is stored as a text within the exception class and you can’t include any other variables.

Nevertheless; this is a practical approach if you don’t need all the bells & whistles and simply need to return a casual exception object in case the function returns an error.

Standard

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s