Skip to Content

Messages are basically short texts stored in database table T100. What makes them special is the ABAP statement MESSAGE. This statement sends a message with a short text from T100 and adds a message type (S, I, W, E, A, X). The system behavior after sending a message is extremely context dependent and I’m not really confident that the documentation covers all the possible situations.

Historically, messages were invented for the PAI-handling of classical dynpros. There they can be used to conduct an error dialog. As a rule, messages should be restricted to that usage. But there is an important exception. Messages are also closely connected to exception handling:

  • In exception classes that implement IF_T100_MESSAGE, messages from T100 can serve as exception texts. Then they are part of the semantical properties of an exception class besides the class name and its super classes.
  • For non-class-based exceptions, messages can play the role of a poor man’s exception text concept.
    • By raising a classical exception with MESSAGE RASING instead of RAISE, you add the message text and type to the exception. After handling such a classical exception with the  EXCEPTIONS addition of the CALL statement, you find the information in the well known system fields sy-msg... .
    • You can catch messages sent with MESSAGE naming the predefined classical exception error_message behind EXCEPTIONS of the CALL statement.

What’s missing?

Nowadays you work with class based exceptions in your application programs. But from time to time you have to call legacy procedures that throw classical exceptions that are bound to messages. If you cannot handle the reason of the exception in place, you want to pass it to your caller in form of a class based exception. The problem is, how to find an appropriate exception class and how to convert the message based exception text of the original exception to an exception text of the exception class?

Since the exception texts of an exception class are part of their semantics, you would need an own exception class or at least exception text for each message that might occurr. Then you can raise the class based exception e.g. as follows:

meth( EXCEPTIONS exception = 4 ).

IF sy-subrc = 4.

  RAISE EXCEPTION TYPE cx_demo_t100

    EXPORTING

      textid = cx_demo_t100=>demo

      text1  = CONV #( sy-msgv1 )

      text2  = CONV #( sy-msgv2 )

      text3  = CONV #( sy-msgv3 )

      text4  = CONV #( sy-msgv4 ).

ENDIF.

Here, meth is a method that raises a classical exception exception with MESSAGE RAISING and cx_demo_t100 implements IF_T100_MESSAGE and denotes a message that fits to the message passed by the classical exception. If there is no approptiate exception class at hand that is able to cover all the messages that might be send by a called procedure, shrewd developers proceed also as follows:

meth( EXCEPTIONS exception = 4 ).

IF sy-subrc = 4.

  RAISE EXCEPTION TYPE cx_demo_t100

    EXPORTING

      textid = VALUE scx_t100key( msgid = sy-msgid

                                  msgno = sy-msgno

                                  attr1 = ‘TEXT1’

                                  attr2 = ‘TEXT2’

                                  attr3 = ‘TEXT3’

                                  attr4 = ‘TEXT4’ )

      text1  = CONV #( sy-msgv1 )

      text2  = CONV #( sy-msgv2 )

      text3  = CONV #( sy-msgv3 )

      text4  = CONV #( sy-msgv4 ).

ENDIF.

This exploits the fact, that you can pass any structure of type scx_t100key to the contructor of an exception class. By doing so, you define a message from T100 not statically as message text but when raising the exception. Only the attributes for the replacement texts have to be there. Knowing that, you can create a kind of generic exception class for messages. But this is not recommended for exception classes implementing IF_T100_MESSAGE. For such an exception class, the exception text should not be dynamic and you should pass constants of that class to the parameter textid only. Furthermore, the above coding is quiet cumbersome. And further-furthermore, there’s no way to pass the message type.

Solution with ABAP 7.50

Since the above scenario is a valid use case, a solution is provided with ABAP 7.50: A new interface IF_T100_DYN_MSG that contains IF_T100_MESSAGE It adds an attribute msgty for the message type and it also adds predefined attributes msgv1 to msgv4 for the replacment texts (placeholders) of a message.

If an exception class cx_demo_dyn_t100 implements IF_T100_DYN_MSG, you can profit from a new MESSAGE addition to the RAISE EXCEPTION statement:

meth( EXCEPTIONS exception = 4 ).

IF sy-subrc = 4.

  RAISE EXCEPTION TYPE cx_demo_dyn_t100

    MESSAGE ID    sy-msgid

            TYPE   sy-msgty

            NUMBER sy-msgno

            WITH   sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

ENDIF.

This does basically the same as the example above, but now in a well-educated way. You can pass the full signature of a message to an exception class including the message type and the runtime environment does the rest for you. Also, you don’t have to care about the names of the attributes for the placeholders any more. When handling the exception you have access to the message, e.g. as follows:

CATCH cx_demo_dyn_t100 INTO DATA(oref).

  cl_demo_output=>display(

    |Caught exception:\n\n| &&

    |”{ oref->get_text( ) }” of type { oref->msgty }| ).

You get back the message text and, that’s new, also the message type. From now on, this is the recommended way of converting classical messages to exceptions.

For more information and more examples see:

The MESSAGE addition is also available for THROW in conditional expressions, of course.

To report this post you need to login first.

16 Comments

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

  1. Ralf Duckstein

    Hello Horst,

    just a question: The above statement handles now very well the conversion of classic exceptions to class based exceptions. What about the opposite direction?

    There is already the syntax

    MESSAGE class_based_exception_object TYPE ‘E’ RAISING class_exception.

    to throw a classic exception using a class based exception because it implements the IF_MESSAGE interface. In fact the MESSAGE statement accepts any object that implement IF_MESSAGE.

    So when we now have IF_T100_DYN_MSG that also knows the message type, the message statement should support the following:

    MESSAGE class_based_exception_object RAISING class_exception.

    The TYPE should be optional when the provided class implements IF_T100_DYN_MSG.

    Regards,

    Ralf

    PS: Yes we also need the opposite direction as old FMs sometime are changed to use internal new OO API, but they are kept, because not 100% clear that they can be removed. Even the old code can’t stay as this requires double maintenance and sometimes solving issues is much more simple using the new OO API.

    (0) 
      1. Ralf Duckstein

        You are right, it is simply to get out some redundant overhead. And when we talk about overhead … why not having a form like this:

        RAISE EXCEPTION TYPE cx_demo_dyn_t100
            SYSTEM-MESSAGE.

        (0) 
  2. Ralf Duckstein

    Hi Horst,

    just another “always pain” thing when raising exceptions.

    Today I have to code (in 7.40 before even more lines required):

    DATA(ex) = cx_my_exception=>create_for_object( obj ).

    RAISE EXCEPTION ex.

    simply due to the fact that the RAISE EXCEPTION statement doesn’t allow an expression that returns an exception object.

    I like to use this way to fill the text attributes of the exception from the given object, or maybe even create objects of different sub classes.

    This would not be necessary when I can use object attributes in the text constants of exceptions. In fact I can do this by hand, but in the dialog for assigning an objects attribute to the message attribute 1 to 4 I can only use the attributes of this object, not the attributes of objects that are attributes in this class. And as we have no default “toString” behavior for objects it makes no sense to pass an object to a message attribute. Maybe we simply could extend the CL_MESSAGE_HELPER->SET_SINGLE_MSG_VAR so that it is able to work with objects as well. Maybe simply by defining that in case an object attribute is used it must implement the IF_MESSAGE interface and thus will provide a “string representation” via IF_MESSAGE~GET_TEXT.

    Regards,

    Ralf

    (0) 
  3. Suhas Saha

    Hi Horst,

    I am currently working on an ABAP 740 SP12 system where i can find the interface IF_T100_DYN_MSG. But unfortunately the the MESSAGE addition for RAISE EXCEPTION is not available. 😐

    In the ABAP740 documentation i don’t see any mention of SP12, although in ABAP750 docu i can see 740-SP10 mentioned. So what exactly is 740-SP12? 😕

    BR,

    Suhas

    (0) 
    1. Horst Keller Post author

      Let’s have a look at the figure in ABAP News for Release 7.50 – What is ABAP 7.50?

      7.40, SP12 is an SPnn after 7.40, SP08. No development from SP08 on any more (one exception: release of the CDS access control for SADL with SP10, but in fact the real release for that is 7.50 too).

      Now, why is IF_T100_DYN_MSG available? It is undocumented and incomplete. Comparing the 7.40 version with 7.50 shows that the MSGV attributes are missing. Let’s assume its simply a placeholder for things to come (reservation of the name). -> Forget it in 7.40!


      😛


      (0) 
  4. Edo von Glan

    Just looked into the post now (we do not have 7.50 yet), but I also think Ralf Duckstein’s suggestion of a short form

    RAISE EXCEPTION TYPE cx_demo_dyn_t100

        SYSTEM-MESSAGE.

    should be implemented, at least as an optional short form, to get rid of 3 lines of overhead.

    Mind you, in the case that the system fields (sy-msg…) were not filled by a called function (or method), but by your current piece of coding, like this:

      MESSAGE E074(xx) INTO dummy.

      RAISE EXCEPTION TYPE …

         MESSAGE ID sy-msgid

                            TYPE sy-msgty

                            …

    then of course you can simply shorten to

      RAISE EXCEPTION TYPE …

        MESSAGE E074(xx).

    I assume this statement would also be found by the used-by function (German: Verwendungsnachweis)? (We don’t have 7.50 yet, so I can not try it out.)

    (0) 
  5. Mainak Aich

    Hello Horst,

    Thanks for sharing this new feature. It will be really helpful for easily passing T100 message to exception class. I have couple of points here-

    1. E.g. I have created a method where I have return table of type bapiret2_t which is a BAPI return table type. When I catch an exception inside the method for some code which raises a class based exception, I get the message text back but I find it difficult to fill the bapi return structure which I am returning from the method. Now with this new feature, I can find message type with 4 message place holders. But do I get the message class and number also? Or to be clear do you have any suggestion how to populate BAPI return structure parameters after catching a class based exception.

    2. I checked your more information reference and probably found a typo there in the help documentation with the following link.

    ABAP Keyword Documentation

    Click on the link “System Interface IF_T100_DYN_MSG in a Global Exception Class” under example section,and a new page will open. In the description section 2nd line, it should be from sy-msgv1 to sy-msgv4 instead of sy-msgv1 to sy-msgv2.

    Thanks,

    Mainak

    (0) 
  6. Ioan Radulescu

    hi, I will just echo Edo’s discreet question: will the search where-used for the message number (from tcode SE91) find it in the exception throwing statement you mentioned? :

      RAISE EXCEPTION TYPE cx_demo_dyn_t100

        MESSAGE ID    sy-msgid

                TYPE   sy-msgty

                NUMBER sy-msgno

                WITH   sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

     

    at the moment for this only reason I’m forced to use the statement message … into lv_dummy_message and then use the syst fields to retrieve the text and variables.

    (0) 
  7. Enno Wulff

    Great news!

    But I still don’t know why MESSAGE exception TYPE ‘I’ works but MESSAGE exception INTO DATA(message) is not allowed… ;(

    It’s a mess integrating exceptions into Application Log structure… :/

    (0) 
    1. Horst Keller Post author

      Why would you want to do that?

      You can access the exception text directly with

      exception->get_text( )

      No need for involving the MESSAGE statement for that.

       

      (0) 
      1. Enno Wulff

        Oh yes of course! to have SY-message fields filled properly. For further logging (application log). Only having the text in the log is often not helpful.

        (0) 

Leave a Reply