Skip to Content

Handling general errors via class based exceptions

Fairly standard scenario: I've got this.

  DATA:  l_requester TYPE xubname.

  CALL FUNCTION 'ENQUEUE_EZMYTAB'
    EXPORTING
      username             = i_username
    EXCEPTIONS
      foreign_lock         = 1
      system_failure       = 2
      OTHERS               = 3.

  CASE sy-subrc.
    WHEN 1.
      l_requester = sy-msgv1.
      RAISE EXCEPTION TYPE zcx_my_exception EXPORTING textid   = zcx_my_exception=>lock_error
                                                      user     = i_username
                                                      lockedby = l_requester.
    WHEN 2.
      RAISE EXCEPTION TYPE zcx_my_exception.

  ENDCASE.

But what I really want for WHEN 2 is the class based exception of

MESSAGE sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1...

I.e., in my calling code, I want to catch the exception, and display whatever the original error message was as generated by the ENQUEUE function module.

I suppose I could do this

DATA: ls_error TYPE scx_t100key.
...
WHEN 2.
  ls_error-msgid = sy-msgid.
  ls_error-msgty = sy-msgty.
  ls_error-msgno = sy-msgno.
...
  RAISE EXCEPTION TYPE zcx_my_exception EXPORTING textid = ls_error

but I can't help feel I'm missing something staggeringly obvious...

matt

Add comment
10|10000 characters needed characters exceeded

  • Follow
  • Get RSS Feed

3 Answers

  • Jan 14, 2011 at 04:59 PM

    May not be the best of the solution but one way could be to use a string variable (lv_dummy) and then

    MESSAGE sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1...INTO lv_dummy.

    Now you could pass this string to an attribute in your exception class and use the same syntax

    RAISE EXCEPTION TYPE zcx_my_exception EXPORTING textid = zcx_my_exception=>...

    to raise the exception.

    Thank you,

    Ramneek

    Add comment
    10|10000 characters needed characters exceeded

  • avatar image
    Former Member
    Jan 15, 2011 at 12:09 AM

    Hi Matt,

    this may sound too simple:

    For me the real advantage of class-based-exception is that they can be raised in an inner block and caught in an outer block at any level.

    I never use the exception attributes to communicate any details, but use

    IF SY-SUBRC NE 0.
      MESSAGE sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1... INTO lv_string.
      Raise Exception type zcx_my_exception.
    ENDIF.

    Catching the exception I may (roughly) know where it comes from. As the message variables are present, I can check their values or repeat the MESSAGE without INTO. The main function of MESSAGE INTO is for transparency, the ability to see the whole message in debugger in lv_string and the where-used-list if message is created by programmer..

    If I really need different reaction for different SY-SUBRC ( = different untyped exception), I'd rather create different class-based exceptions. This helps transparency.

    In other oo language you do not have an ABAP message concept with everywhere-present message variables. Why use this crutch of putting the message variable filled by functions exception into exception object attributes only to convert them back to message output?

    I prefer [KISS|http://en.wikipedia.org/wiki/KISS_principle].

    Regards,

    Clemens

    Add comment
    10|10000 characters needed characters exceeded

    • This is what I did in the end:

          WHEN 1.
            l_requester = sy-msgv1.
            RAISE EXCEPTION TYPE zcx_myexception EXPORTING textid   = zcx_myexception=>lock_error
                                                           user     = me->username
                                                           lockedby = l_requester.
          WHEN 2.
            MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                                WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 INTO l_errmsg.
            RAISE EXCEPTION TYPE zcx_myexception EXPORTING msg = l_errmsg.

      In the catch, I do this.

      DATA: lx_error TYPE REF TO zcx_myexception.
      ...
            CATCH zcx_myexception INTO lx_error.
              IF lx_error->msg IS INITIAL.
                MESSAGE lx_error TYPE 'I'.
              ELSE.
                MESSAGE lx_error->msg TYPE 'I'.
              ENDIF.

      I'd forgotten the obvious point that the attributes of an exception object are directly available!

      thanks

      matt

  • Jan 18, 2011 at 04:46 PM

    Hi Matt,

    Purely academic as it's after the fact, but isn't this the type of thing that message class based exception classes are supposed to do? I've never really seen the point of raising old-fashioned messages from an exception class , but it seems what you're trying to do.

    You'd need to create an exception class for this purpose, but then you should be able to just raise the exception in the usual way and just map the exception attributes to the message variables in the exception class text definition rather than in your code.

    Cheers,

    Mike

    Add comment
    10|10000 characters needed characters exceeded

    • Former Member Mike Pokraka

      Hi,

      my cent:

      One if not the main advantage of class-based-exceptions is that they can be caught in any outer block as long as they are in the blocks interface.

      As we can not have more than one exception occur at any given point of time in one LUW, I have no problem with using the SY-MSGxy variables to communicate exception details.

      Between RAISING a class-based exception and catching it nothing is processed except the exception constructor.

      I do not think this is a violation of MVC approach, take it as ABAP-specific specialization, very simple and fully transparent.

      Regards,

      Clemens