Question

I have several custom exception classes that were created "With Message Class". Since I can't directly get a message from them, I want to create a utility method that returns a BAPIRET2 from a given exception based on the values in IF_T100_MESSAGE~T100KEY. However, I can't provide that method with a generic CX_ROOT importing parameter as this class is not message-enabled. I also can't create a generic message-enabled exception class as new classes have to inherit from one of CX_STATIC_CHECK, CX_DYNAMIC_CHECK, or CX_NOCHECK.

How can I then retrieve the message details from an unspecified exception? Should I create a method that receives a CX_ROOT and then does up to three calls to methods with an import typed to each of the three possible subclasses? Or are there better alternatives?

Was it helpful?

Solution

You could prepare a type descriptor of the interface (once):

DATA: lr_t100_descr TYPE REF TO cl_abap_intfdescr.

lr_t100_descr ?= cl_abap_typedescr=>describe_by_name( 'IF_T100_MESSAGE' ).

and then examine each exception as it comes your way:

DATA: lr_t100_exception TYPE REF TO if_t100_message.

IF lr_t100_descr->applies_to( ir_any_exception ) = abap_true.
  lr_t100_exception ?= ir_any_exception.
  " ...
ENDIF.

OTHER TIPS

You could use the message collector object, so for example

DATA:
  excp              type ref to CX_ROOT,
  bapi_messages     type BAPIRETTAB,
  message_collector type ref to IF_RECA_MESSAGE_LIST.

FIELD_SYMBOLS:
  <bapi_message>    TYPE BAPIRET2.

message_collector = cf_reca_message_list=>create( ).

TRY.
 " some code which may cause and exception
CATCH cx_root into excp.
  message_collector->add_from_exxeption( io_exception = excp).
ENDTRY.

bapi_messages = message_collector->get_list_as_bapiret( ).

LOOP AT bapi_messages ASSIGNING <bapi_message>.
  " write out message
ENDLOOP.

It is well worth checking out the message collector object.

For example http://wiki.scn.sap.com/wiki/display/profile/2007/07/09/Message+Handling+-+Finding+the+Needle+in+the+Haystack

For a logging class I use something like this:

METHOD add_message_exception.
  DATA:
    lr_type         TYPE REF TO cl_abap_typedescr,
    lr_class        TYPE REF TO cl_abap_classdescr,
    lr_intf         TYPE REF TO cl_abap_intfdescr,
    l_bapiret2      TYPE bapiret2,
    lr_msg          TYPE REF TO if_t100_message.

  CHECK ir_exception IS NOT INITIAL.

  l_bapiret2-type       = i_type.

  "Test for T100KEY interface
  cl_abap_classdescr=>describe_by_object_ref(
    EXPORTING
      p_object_ref         = ir_exception
    RECEIVING
      p_descr_ref          = lr_type
   EXCEPTIONS
      reference_is_initial = 1
      OTHERS               = 2  ).
  TRY.
      lr_class ?= lr_type.
      IF sy-subrc = 0.
        lr_class->get_interface_type(
          EXPORTING
            p_name              = 'IF_T100_MESSAGE'
          RECEIVING
            p_descr_ref         = lr_intf
          EXCEPTIONS
            interface_not_found = 1
            OTHERS              = 2 ).
        IF sy-subrc = 0.
          lr_msg ?= ir_exception.  "Cast to interface
          l_bapiret2-id         = lr_msg->t100key-msgid.
          l_bapiret2-number     = lr_msg->t100key-msgno.

          cl_message_helper=>set_msg_vars_for_if_t100_msg( text = lr_msg ).

          l_bapiret2-message_v1 = sy-msgv1.
          l_bapiret2-message_v2 = sy-msgv2.
          l_bapiret2-message_v3 = sy-msgv3.
          l_bapiret2-message_v4 = sy-msgv4.

          l_bapiret2-message = me->get_msg(
              i_msgid = l_bapiret2-id
              i_msgno = l_bapiret2-number ).
        ENDIF.
      ENDIF.
    CATCH cx_root.
      "Pokémon exception handling
  ENDTRY.

  "No T100KEY Interface available
  IF lr_msg IS INITIAL.
    l_bapiret2-message    = ir_exception->if_message~get_text( ).
    l_bapiret2-message_v1 = sy-msgv1.
    l_bapiret2-message_v2 = sy-msgv2.
    l_bapiret2-message_v3 = sy-msgv3.
    l_bapiret2-message_v4 = sy-msgv4.
  ENDIF.
ENDMETHOD.

Hope this helps as I struggled with the same problem. Maybe there is some adjustment needed, but I think you get the basic idea. This method can handle

I might be missing something, but can't you just use IF_MESSAGE~GET_TEXT which is present on CX_ROOT ?

Otherwise, I would make it the responsibility of the custom exception class to have a method that can return a proper message ( it might rely on the utility method you are planning on ).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top