Abap error message

How To Display Error Messages In SAP ABAP? An overview of error message types, error and pop-up messages, and how to show messages to the end user. Published Jun 16, 2021 Message Types In ABAP In total, ABAP has 6 types of messages. Type Description A Abend (abnormal end of task) Displays a message […]

Содержание

  1. How To Display Error Messages In SAP ABAP?
  2. Message Types In ABAP
  3. DISPLAY LIKE Addition
  4. Displaying Messages
  5. Saving Messages In A Variable
  6. See Also
  7. ABAP Blog
  8. Все о разработке в решениях от SAP
  9. ABAP Blog
  10. Все о разработке в решениях от SAP
  11. Ссылки
  12. Цитаты
  13. Новое
  14. Последние комментарии
  15. Обработка особых ситуаций в ABAP
  16. Классический способ обработки исключений
  17. Обработка исключений, основанная на классах
  18. Категории исключений
  19. SAP Messages
  20. SAP Message Classes
  21. MESSAGE E001(MCLASS).
  22. Pass message Parameters
  23. Further information about message types

How To Display Error Messages In SAP ABAP?

An overview of error message types, error and pop-up messages, and how to show messages to the end user.

Published Jun 16, 2021

Message Types In ABAP

In total, ABAP has 6 types of messages.

Type Description
A Abend (abnormal end of task) Displays a message in a dialog pop-up window. The entire transaction is canceled after confirming the message.
E Error Displays an error message in the status line. After confirming the message, the current event block is aborted.
I Information Displays a message in a dialog pop-up window. After confirming the message, the report processing is resumed.
S Success / Status Displays a success message in the status line of the current report.
W Warning Displays a warning message in the status line. After confirming the message, the report processing is resumed.
X Exit Triggers a runtime error and creates a short dump.

DISPLAY LIKE Addition

As you can see from the previous table the message type can also influence the report execution after the message was confirmed. In case you want to take care of the error handling yourself or simply change the appearance of a message you can use the addition DISPLAY LIKE :

This example prints the message Message text to display in the status line with the red error icon. Since the type itself is S report execution continues normally.

Remember: The addition DISPLAY LIKE only changes the appearance, not the behavior of the message type.

Displaying Messages

Following some examples of how to output a message in ABAP.

Saving Messages In A Variable

The below examples show how to create and store a message in a variable. This can be useful when working with system variables or a message class.

See Also

I’m Dan, a software engineer and consultant passionate about SAP, web and mobile app development.

Источник

ABAP Blog

Все о разработке в решениях от SAP

ABAP Blog

Все о разработке в решениях от SAP

Ссылки

Цитаты

Мы пытаемся решить проблему, максимально ускоряя процесс проектирования, чтобы в конце работы над системой у нас осталось достаточно времени для нахождения ошибок, допущенных из-за слишком быстрого проектирования.

Гленфорд Майерс

Новое

  • Получение инстанции cl_gui_alv_grid для SALV 11.09.2021
  • Introduction to ABAP in the Cloud 18.08.2021
  • Getting Started with FPM BOPF Integration 01.06.2021
  • 30. How to Use Authority Checks in Business Object Processing Framework 29.05.2021
  • 29. BOPF Extensibility 29.05.2021
  • 28. BOPF Enterprise Procurement Model (EPM) 29.05.2021
  • 27. BOPF Integration 29.05.2021
  • 26. BOPF Business Configuration Objects 29.05.2021
  • 25. BOPF Performance 29.05.2021
  • 24. BOPF Supportability 29.05.2021

Последние комментарии

Обработка особых ситуаций в ABAP

Когда мы создаем какой-либо многократно используемый компонент, например функциональный модуль или метод в классе, мы сталкиваемся с необходимостью обработки непредвиденных ситуаций (какой-либо входной параметр, оказался не заполненным или доступ к файлу не был получен и т.п.), т.е. тех ситуаций, после которых программа не может выполняться далее стандартным образом, либо требуется дополнительная обработка.

В приведенной статье рассматриваются способы вызова и обработки данных ситуаций, называемых исключениями.

В ABAP есть два основных способа работы с исключениями, классический способ заключается в вызове особых ситуаций описанных в ФМ или методе на отдельной закладке:

Классический способ может использоваться и в классах:

Новый способ основывается на ООП, где в качестве исключений используются классы (обратите внимание, что установлена галочка – классы исключений):

Хочется отметить, что новый способ был введен с версии SAP Web AS 6.10 и при создании новых функциональных модулей или методов рекомендуется использовать именно его. В данной статье не рассматриваются системные исключения и их обработка до введения классов исключений.

В RFC модулях в настоящее время используется классический способ обработки исключений. Не допускается одновременно использовать классический и основанный на классах, способы обработки исключений (в интерфейсе методов, процедур, функций).

Классический способ обработки исключений

При вызове исключения, системное поле sy-subrc будет заполнено номером, под которым исключение было обозначено при вызове ФМ, метода или процедуры:

Как правило, исключения вызываются с текстом сообщения, данный текст может быть описан статически – при вызове исключения оператором MESSAGE, либо динамически – путём получения текста из описания ФМ.

Так же исключение может быть вызвано без какого-либо текста (оператором RAISE ИмяИсключения), но данный способ лучше не использовать, т.к. вызов исключения должен как-то себя расшифровывать и говорить о том, что собственно произошло.

Напишем небольшой ФМ, рассчитывающий сумму двух чисел, оба параметра помечены как необязательные, если первый параметр не будет задан при вызове ФМ, система выдаст исключение – no_num_1.

И программа для его вызова:

При запуске программы произойдет вызов исключения, т.к. был использован тип сообщения «Е», программа завершит свое выполнение после показа сообщения:

Замечу, что это вовсе не означает, что при вызове ФМ или метода и обработке исключения необходимо завершать работу программы, вы можете свободно продолжить её выполнение и далее, добавив например, сообщение об ошибке в лог программы, а не на вывод как в примере.

Ключевое слово OTHERS используется для того чтобы поймать исключения не описанные в ФМ или явно неуказанные, при вызове ФМ.

Пример вызова неописанного исключения:

В данном примере вызывается неописанное в интерфейсе ФМ исключение – no_num_2, которое будет благополучно поймано с помощью ключевого слова OTHERS (системное поле sy-subrc примет значение равное 2).

Кроме того, можно не обрабатывать большой список всех возможных исключений описанных в ФМ, тогда в случае если такое исключение будет вызвано поле sy-subrc примет значение, указанное в OTHERS.

В ФМ, могут быть добавлены новые исключения и в случае, когда при вызове ФМ они не обработаны и не указано слово OTHERS программа упадет в дамп с ошибкой времени выполнения — RAISE_EXCEPTION. Отсюда вывод, ключевое слово OTHERS подставляем всегда, при вызове ФМ (метода или процедуры), когда мы точно не уверены в неизменности компонента.

При вызове исключения в процедурах (perform…) из ФМ, система пытается найти и вызвать исключение в первом ФМ из стека вызовов, если исключение не найдено, вызывается так же, как и неопределенное исключение в ФМ.

Как уже было упомянуто выше, есть возможность получать текст непосредственно из описания особой ситуации:

ФМ будет выглядеть следующим образом:

Результат:

Иногда особые ситуации используются не как исключения, а как параметры показывающие обработку ФМ и его результат, возвращаемый в поле sy-subrc, хотя лучше бы пренебречь подобным стилем:

Сообщения, вызываемые в ФМ или методах, оператором MESSAGE, без дополнения RAISING, либо сообщения вызываемые системой (например, при обработке экранов), могут быть обработаны программой с использованием дополнения: error_message = n_error, указываемого так же после ключевого слова EXCEPTIONS.

При обработке сообщений:

  • Сообщения с типом I, W, S не обрабатываются, но записываются в журнал обработки фонового выполнения, если происходит обработка в фоне.
  • Сообщения с типом E или A могут быть обработаны, при этом в поле sy-subrc будет записано значение n_error. При вызове сообщения с типом А, происходит вызов ROLLBACK WORK (см. описание оператора MESSAGE).
  • Сообщение с типом X не обрабатывается, программа завершается с дампом.

Обработка исключения классическим способом может быть выполнена динамически, с помощью ключевого слова EXCEPTION-TABLE. Пример:

Обработка исключений, основанная на классах

Как понятно из названия, под исключениями в данном случае понимаются объекты специальных классов исключений. Вызов такого исключения может быть выполнен либо в программе с помощью оператора RAISE EXCEPTION, либо системой (например, при делении на ноль будет вызвано предопределённое исключение CX_SY_ZERODIVIDE, список таких исключений), либо через дополнение THROW в условных выражениях (с версии ABAP 7.4).

Во всех случаях инициируется создание объекта указанного класса (если указано дополнение INTO в CATCH), в атрибутах которого содержится информация о возникшей исключительной ситуации, доступ к ним, как правило, осуществляется через методы этого класса.

Классы особых ситуаций могут быть определены как локально, так и глобально через построитель классов – транзакция SE24, диалог создания:

В данном случае галочка «с классом сообщений» означает использование в качестве текста сообщения из класса сообщений транзакция SE91 (будет рассмотрено ниже). По умолчанию текст сообщения создается в текстах класса:

Категории исключений

Все классы особых ситуаций являются производными одного из классов: CX_NO_CHECK, CX_DYNAMIC_CHECK или CX_STATIC_CHECK, которые сами являются производными общего суперкласса CX_ROOT.

  • CX_STATIC_CHECK – как правило, исключения которые вызываются в процедуре (ФМ или методе), должны быть либо обработаны в ней, либо процедура должна иметь соответствующий интерфейс, чтобы вызывающий её код мог обработать эту ситуацию. Если исключение определено как потомок этого класса, оно должно быть явно указано в интерфейсе метода (ФМ или формы) в котором происходит его вызов. Данная категория используется тогда, когда в коде явно ожидается передача обработки особой ситуации на уровень выше того места где оно было вызвано. Если при статической проверке, система не увидит обработки в блоке TRY..CATCH..ENDTRY подобного исключения система выдаст предупреждение:
  • CX_DYNAMIC_CHECK – при проверке кода, компилятор не будет делать предупреждений об отсутствии обработки исключений их этой категории, в случае вызова исключения его обработка будет проверена динамически и если обработчик не будет найден программа упадет в дамп. Обычно данная категория используется тогда, когда исключение может быть обработано внутри самого метода, без передачи обработки выше по стеку. Примером такой категории может являться исключение вызываемое при делении на ноль, передавать его выше по стеку и указывать в интерфейсе метода вовсе не обязательно, т.к. мы можем его обработать внутри самого метода. Однако, если мы хотим передать обработку данного исключения, необходимо указать его в интерфейсе метода.
  • CX_NO_CHECK – аналогичны предыдущему типу, но данную категорию нельзя объявлять в интерфейсах, при этом классы исключений наследуемые от этого класса, неявно все же передаются в интерфейс и выше по стеку вызовов. Данную категорию следует использовать для исключительных ситуаций, которые могут произойти в любое время и не могут быть обработаны непосредственно в коде метода. Кроме того, можно использовать в случаях когда одна и та же исключительная ситуация может возникнуть во множествах методов, а объявлять её в интерфейсах каждого из методов не имеет смысла, т.к. это усложнит код. В итоге подобные исключения могут пройти всю цепочку вызовов методов (т.к. неявно передаются в интерфейс) и быть обработаны на уровне программы.

На исключения накладываются следующие ограничения:

  • Исключение не может быть объявлено в интерфейсе статического конструктора:

  • Исключение не может быть объявлено в интерфейсе обработчика событий. При этом если в коде обработчика произошел вызов исключения, и он не был обработан, система вызовет исключение — CX_SY_NO_HANDLER, которое может быть обработано в вызывающем его коде.
  • При вызове программ через SUMBIT или CALL TRANSACTION, исключение, возникающее в вызываемой программе, не может быть передано в вызывающую программу.

Небольшой пример с локальным классом исключения:

Источник

SAP Messages

A SAP message is an essential part of any ABAP program and are used to display information to the user to let them know what’s happening. This could be in a number of ways such as an error message, warning message or information message.

The following ABAP code is the simplest way to implement a message into your report.

MESSAGE ‘Display this message’ TYPE ‘E’.

SAP Message Classes

A better way to implement your messages would be to create and maintain them via a message class using transactions SE91 or SE80. This way you have a central store for all messages, which makes it easier to maintain. This is especially true if your messages need to be translated into multiple languages. Enter your text here.

To do this you first need to create a message class which is a kind of container/wrapper where you store related messages together. Once this is done you can add as many message as you require into it. You also get the option to create additional long text, which offers the user additional information about the particular issue. See the following link for more information and details of how to create a message class.

Once you have created your message you can use them within your ABAP code using the following syntax:

MESSAGE E001(MCLASS).

MESSAGE = ABAP statement
E = Type of message (can also be I,W,S,A,X)
001 = Message number
MCLASS = Message Class

Pass message Parameters

You can also add parameters to your messages using the «&» character. So for example you could create the following message ‘Purchase order & has been deleted’. You can then pass a purchase order number to the message when using it and it will replace the «&» with the purchase order you pass for example

MESSAGE E001(MCLASS) with ekko-ebeln.

The result would display
«Purchase order 1234 has been deleted»

Further information about message types

I — Information messages
Information message are displayed in a popup window and only pause processing until you have clicked through the message.

E — Error message
An error message will be displayed in red along the footer of the SAP screen and stops processing going any further.

W — Warning message
A warning message behaves similar to and error message and is displayed along the footer of the SAP screen and stops processing going any further.

S — Success/Status message
A Success message is also displayed along the footer of the SAP screen but does not stop processing going any further and is simply displayed at the end in green.

A — Termination/Abend
A termination message stops processing and causes a runtime error and short dump which is also viewable in tcode ST22.

X — Exit
An exit message stops processing and displays and exit button which exits session processing. Similar to typing /n into the SAP command box.

Источник

imagesКогда мы создаем какой-либо многократно используемый компонент, например функциональный модуль или метод в классе, мы сталкиваемся с необходимостью обработки непредвиденных ситуаций (какой-либо входной параметр, оказался не заполненным или доступ к файлу не был получен и т.п.), т.е. тех ситуаций, после которых программа не может выполняться далее стандартным образом, либо требуется дополнительная обработка.

В приведенной статье рассматриваются способы вызова и обработки данных ситуаций, называемых исключениями.

В ABAP есть два основных способа работы с исключениями, классический способ заключается в вызове особых ситуаций описанных в ФМ или методе на отдельной закладке:

1

Классический способ может использоваться и в классах:

2

Новый способ основывается на ООП, где в качестве исключений используются классы (обратите внимание, что установлена галочка – классы исключений):

3

Хочется отметить, что новый способ был введен с версии SAP Web AS 6.10 и при создании новых функциональных модулей или методов рекомендуется использовать именно его. В данной статье не рассматриваются системные исключения и их обработка до введения классов исключений.

В RFC модулях в настоящее время используется классический способ обработки исключений. Не допускается одновременно использовать классический и основанный на классах, способы обработки исключений (в интерфейсе методов, процедур, функций).

Классический способ обработки исключений

При вызове исключения, системное поле sy-subrc будет заполнено номером, под которым исключение было обозначено при вызове ФМ, метода или процедуры:

CALL FUNCTION ...

...

EXCEPTIONS

  Ошибка1 = 1

  Ошибка2 = 2.

Как правило, исключения вызываются с текстом сообщения, данный текст может быть описан статически – при вызове исключения оператором MESSAGE, либо динамически – путём получения текста из описания ФМ.

Так же исключение может быть вызвано без какого-либо текста (оператором RAISE ИмяИсключения), но данный способ лучше не использовать, т.к. вызов исключения должен как-то себя расшифровывать и говорить о том, что собственно произошло.

Напишем небольшой ФМ, рассчитывающий сумму двух чисел, оба параметра помечены как необязательные, если первый параметр не будет задан при вызове ФМ, система выдаст исключение – no_num_1.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

FUNCTION ZTEST_EXC.

*»———————————————————————-

*»*»Локальный интерфейс:

*»  IMPORTING

*»     REFERENCE(I_NUM_1) TYPE  I OPTIONAL

*»     REFERENCE(I_NUM_2) TYPE  I OPTIONAL

*»  EXPORTING

*»     REFERENCE(E_SUMM) TYPE  I

*»  EXCEPTIONS

*»      NO_NUM_1

*»———————————————————————-

  IF i_num_1 IS NOT SUPPLIED.

    MESSAGE e398(00) WITH ‘Число 1 не указано, расчёт невозможен’ RAISING no_num_1.

  ENDIF.

  E_SUMM = i_num_1 + i_num_2.

ENDFUNCTION.

И программа для его вызова:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

DATA:

  gv_num_2 TYPE i VALUE 10,

  gv_summ  TYPE i.

CALL FUNCTION ‘ZTEST_EXC’

  EXPORTING

    i_num_2  = gv_num_2    » Число 2

  IMPORTING

    e_summ   = gv_summ     » Сумма

  EXCEPTIONS

    no_num_1 = 1

    others   = 2.

IF sysubrc <> 0.

MESSAGE ID symsgid TYPE symsgty NUMBER symsgno

            WITH symsgv1 symsgv2 symsgv3 symsgv4.

ENDIF.

WRITE gv_summ.

При запуске программы произойдет вызов исключения, т.к. был использован тип сообщения «Е», программа завершит свое выполнение после показа сообщения:

4

Замечу, что это вовсе не означает, что при вызове ФМ или метода и обработке исключения необходимо завершать работу программы, вы можете свободно продолжить её выполнение и далее, добавив например, сообщение об ошибке в лог программы, а не на вывод как в примере.

Ключевое слово OTHERS используется для того чтобы поймать исключения не описанные в ФМ или явно неуказанные, при вызове ФМ.

Пример вызова неописанного исключения:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

FUNCTION ztest_exc.

*»———————————————————————-

*»*»Локальный интерфейс:

*»  IMPORTING

*»     REFERENCE(I_NUM_1) TYPE  I OPTIONAL

*»     REFERENCE(I_NUM_2) TYPE  I OPTIONAL

*»  EXPORTING

*»     REFERENCE(E_SUMM) TYPE  I

*»  EXCEPTIONS

*»      NO_NUM_1

*»———————————————————————-

  IF i_num_1 IS NOT SUPPLIED.

    MESSAGE e398(00) WITH ‘Число 1 не указано, расчёт невозможен’ RAISING no_num_2.

  ENDIF.

  E_SUMM = i_num_1 + i_num_2.

ENDFUNCTION.

В данном примере вызывается неописанное в интерфейсе ФМ исключение – no_num_2, которое будет благополучно поймано с помощью ключевого слова OTHERS (системное поле sy-subrc примет значение равное 2).

Кроме того, можно не обрабатывать большой список всех возможных исключений описанных в ФМ, тогда в случае если такое исключение будет вызвано поле sy-subrc примет значение, указанное в OTHERS.

В ФМ, могут быть добавлены новые исключения и в случае, когда при вызове ФМ они не обработаны и не указано слово OTHERS программа упадет в дамп с ошибкой времени выполнения — RAISE_EXCEPTION. Отсюда вывод, ключевое слово OTHERS подставляем всегда, при вызове ФМ (метода или процедуры), когда мы точно не уверены в неизменности компонента.

5

При вызове исключения в процедурах (perform…) из ФМ, система пытается найти и вызвать исключение в первом ФМ из стека вызовов, если исключение не найдено, вызывается так же, как и неопределенное исключение в ФМ.

Как уже было упомянуто выше, есть возможность получать текст непосредственно из описания особой ситуации:

6

ФМ будет выглядеть следующим образом:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

FUNCTION ztest_exc.

*»———————————————————————-

*»*»Локальный интерфейс:

*»  IMPORTING

*»     REFERENCE(I_NUM_1) TYPE  I OPTIONAL

*»     REFERENCE(I_NUM_2) TYPE  I OPTIONAL

*»  EXPORTING

*»     REFERENCE(E_SUMM) TYPE  I

*»  EXCEPTIONS

*»      NO_NUM_1

*»———————————————————————-

  DATA:

    lv_fun TYPE functfuncname,

    lv_exc TYPE functparameter,

    lv_txt TYPE swotlqshorttext.

  lv_fun = ‘ZTEST_EXC’.

  lv_exc = ‘NO_NUM_1’.

  CALL FUNCTION ‘SWO_TEXT_FUNCTION_EXCEPTION’

    EXPORTING

      language  = sylangu

      function  = lv_fun

      exception = lv_exc

    IMPORTING

      shorttext = lv_txt.

  IF i_num_1 IS NOT SUPPLIED.

    MESSAGE e398(00) WITH lv_txt RAISING no_num_1.

  ENDIF.

  e_summ = i_num_1 + i_num_2.

ENDFUNCTION.

Результат: 7

Иногда особые ситуации используются не как исключения, а как параметры показывающие обработку ФМ и его результат, возвращаемый в поле sy-subrc, хотя лучше бы пренебречь подобным стилем:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

FUNCTION ZMORE_THEN_10.

*»———————————————————————-

*»*»Локальный интерфейс:

*»  IMPORTING

*»     REFERENCE(I_VAL) TYPE  I

*»  EXCEPTIONS

*»      MORE_10

*»      LESS_10

*»      EQUAL_10

*»———————————————————————-

  IF i_val = 10.

    RAISE equal_10.

  ELSEIF i_val > 10.

    RAISE more_10.

  ELSE.

    RAISE less_10.

  ENDIF.

ENDFUNCTION.

Программа:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

DATA:

  gv_val TYPE i VALUE 10.

CALL FUNCTION ‘ZMORE_THEN_10’

  EXPORTING

    i_val    = gv_val

  EXCEPTIONS

    more_10  = 1

    less_10  = 2

    equal_10 = 3.

CASE sysubrc.

  WHEN 1.

    WRITE ‘More 10’.

  WHEN 2.

    WRITE ‘Less 10’.

  WHEN 3.

    WRITE ‘Equal

Результат:

8

Сообщения, вызываемые в ФМ или методах, оператором MESSAGE, без дополнения RAISING, либо сообщения вызываемые системой (например, при обработке экранов), могут быть обработаны программой с использованием дополнения: error_message = n_error, указываемого так же после ключевого слова EXCEPTIONS.

При обработке сообщений:

  • Сообщения с типом I, W, S не обрабатываются, но записываются в журнал обработки фонового выполнения, если происходит обработка в фоне.
  • Сообщения с типом E или A могут быть обработаны, при этом в поле sy-subrc будет записано значение n_error. При вызове сообщения с типом А, происходит вызов ROLLBACK WORK (см. описание оператора MESSAGE).
  • Сообщение с типом X не обрабатывается, программа завершается с дампом.

Пример ФМ:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

FUNCTION ztest_exc.

*»———————————————————————-

*»*»Локальный интерфейс:

*»  IMPORTING

*»     REFERENCE(I_NUM_1) TYPE  I OPTIONAL

*»     REFERENCE(I_NUM_2) TYPE  I OPTIONAL

*»  EXPORTING

*»     REFERENCE(E_SUMM) TYPE  I

*»  EXCEPTIONS

*»      NO_NUM_1

*»———————————————————————-

  IF i_num_1 IS NOT SUPPLIED.

    MESSAGE e398(00) WITH ‘Число 1 не указано, расчёт невозможен’.

  ENDIF.

  E_SUMM = i_num_1 + i_num_2.

ENDFUNCTION.

Программа:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

PROGRAM test_exceptions.

DATA:

  gv_val TYPE i VALUE 10,

  gv_summ TYPE i.

CALL FUNCTION ‘ZTEST_EXC’

  EXPORTING

    i_num_2  = gv_val    » Число 2

  IMPORTING

    e_summ   = gv_summ    » Сумма

  EXCEPTIONS

    error_message = 1

    others   = 2.

IF sysubrc = 1.

  WRITE ‘ФМ вызвал MESSAGE с типом E,A’.

ENDIF.

Результат:

9

Обработка исключения классическим способом может быть выполнена динамически, с помощью ключевого слова EXCEPTION-TABLE. Пример:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

DATA: line     TYPE c LENGTH 80,

      text_tab LIKE STANDARD TABLE OF line,

      filename TYPE string,

       filetype TYPE c LENGTH 10,

      fleng    TYPE i.

DATA: func TYPE string,

      ptab TYPE abap_func_parmbind_tab,

      ptab_line TYPE abap_func_parmbind,

      etab TYPE abap_func_excpbind_tab,

      etab_line TYPE abap_func_excpbind.

func = ‘GUI_DOWNLOAD’.

filename = ‘c:temptext.txt’.

filetype = ‘ASC’.

ptab_linename = ‘FILENAME’.

ptab_linekind = abap_func_exporting.

GET REFERENCE OF filename INTO ptab_linevalue.

INSERT ptab_line INTO TABLE ptab.

ptab_linename = ‘FILETYPE’.

ptab_linekind = abap_func_exporting.

GET REFERENCE OF filetype INTO ptab_linevalue.

INSERT ptab_line INTO TABLE ptab.

ptab_linename = ‘DATA_TAB’.

ptab_linekind = abap_func_tables.

GET REFERENCE OF text_tab INTO ptab_linevalue.

INSERT ptab_line INTO TABLE ptab.

ptab_linename = ‘FILELENGTH’.

ptab_linekind = abap_func_importing.

GET REFERENCE OF fleng INTO ptab_linevalue.

INSERT ptab_line INTO TABLE ptab.

...

etab_linename = ‘OTHERS’.

etab_linevalue = 10.

INSERT etab_line INTO TABLE etab.

CALL FUNCTION func

  PARAMETERTABLE

  ptab

  EXCEPTIONTABLE

  etab.

CASE sysubrc.

  WHEN 1.

    ...

    ...

ENDCASE.

Обработка исключений, основанная на классах

Как понятно из названия, под исключениями в данном случае понимаются объекты специальных классов исключений. Вызов такого исключения может быть выполнен либо в программе с помощью оператора RAISE EXCEPTION, либо системой (например, при делении на ноль будет вызвано предопределённое исключение CX_SY_ZERODIVIDE, список таких исключений), либо через дополнение THROW в условных выражениях (с версии ABAP 7.4).

Во всех случаях инициируется создание объекта указанного класса (если указано дополнение INTO в CATCH), в атрибутах которого содержится информация о возникшей исключительной ситуации, доступ к ним, как правило, осуществляется через методы этого класса.

Классы особых ситуаций могут быть определены как локально, так и глобально через построитель классов – транзакция SE24, диалог создания:

10

В данном случае галочка «с классом сообщений» означает использование в качестве текста сообщения из класса сообщений транзакция SE91 (будет рассмотрено ниже). По умолчанию текст сообщения создается в текстах класса:

11

Категории исключений

Все классы особых ситуаций являются производными одного из классов: CX_NO_CHECK, CX_DYNAMIC_CHECK или CX_STATIC_CHECK, которые сами являются производными общего суперкласса CX_ROOT.

  • CX_STATIC_CHECK – как правило, исключения которые вызываются в процедуре (ФМ или методе), должны быть либо обработаны в ней, либо процедура должна иметь соответствующий интерфейс, чтобы вызывающий её код мог обработать эту ситуацию. Если исключение определено как потомок этого класса, оно должно быть явно указано в интерфейсе метода (ФМ или формы) в котором происходит его вызов. Данная категория используется тогда, когда в коде явно ожидается передача обработки особой ситуации на уровень выше того места где оно было вызвано. Если при статической проверке, система не увидит обработки в блоке TRY..CATCH..ENDTRY подобного исключения система выдаст предупреждение: 12
  • CX_DYNAMIC_CHECK – при проверке кода, компилятор не будет делать предупреждений об отсутствии обработки исключений их этой категории, в случае вызова исключения его обработка будет проверена динамически и если обработчик не будет найден программа упадет в дамп. Обычно данная категория используется тогда, когда исключение может быть обработано внутри самого метода, без передачи обработки выше по стеку. Примером такой категории может являться исключение вызываемое при делении на ноль, передавать его выше по стеку и указывать в интерфейсе метода вовсе не обязательно, т.к. мы можем его обработать внутри самого метода. Однако, если мы хотим передать обработку данного исключения, необходимо указать его в интерфейсе метода.
  • CX_NO_CHECK – аналогичны предыдущему типу, но данную категорию нельзя объявлять в интерфейсах, при этом классы исключений наследуемые от этого класса, неявно все же передаются в интерфейс и выше по стеку вызовов. Данную категорию следует использовать для исключительных ситуаций, которые могут произойти в любое время и не могут быть обработаны непосредственно в коде метода. Кроме того, можно использовать в случаях когда одна и та же исключительная ситуация может возникнуть во множествах методов, а объявлять её в интерфейсах каждого из методов не имеет смысла, т.к. это усложнит код. В итоге подобные исключения могут пройти всю цепочку вызовов методов (т.к. неявно передаются в интерфейс) и быть обработаны на уровне программы.

На исключения накладываются следующие ограничения:

  • Исключение не может быть объявлено в интерфейсе статического конструктора:

13

  • Исключение не может быть объявлено в интерфейсе обработчика событий. При этом если в коде обработчика произошел вызов исключения, и он не был обработан, система вызовет исключение — CX_SY_NO_HANDLER, которое может быть обработано в вызывающем его коде.
  • При вызове программ через SUMBIT или CALL TRANSACTION, исключение, возникающее в вызываемой программе, не может быть передано в вызывающую программу.

Небольшой пример с локальным классом исключения:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

PROGRAM test_exceptions.

CLASS lcx_no_num DEFINITION INHERITING FROM cx_static_check.

ENDCLASS.

CLASS lcl_test_exceptions DEFINITION.

  PUBLIC SECTION.

    METHODS:

      do_summ IMPORTING

                i_num_1 TYPE i OPTIONAL

                i_num_2 TYPE i OPTIONAL

              RETURNING value(re_summ) TYPE int1

              RAISING lcx_no_num.

ENDCLASS.

CLASS lcl_test_exceptions IMPLEMENTATION.

  METHOD do_summ.

    IF i_num_1 IS NOT SUPPLIED OR i_num_2 IS NOT SUPPLIED.

      » Данное исключение присутствует в интерфейсе, может быть обработано вне метода

      RAISE EXCEPTION TYPE lcx_no_num.

    ENDIF.

    TRY.

      re_summ = i_num_1 + i_num_2.

      » Ошибка с дин. проверкой, при её обработке обнулим результат

    CATCH CX_SY_CONVERSION_OVERFLOW.

      re_summ = 0.

    ENDTRY.

  ENDMETHOD.

ENDCLASS.

DATA:

  go_test_exceptions TYPE REF TO lcl_test_exceptions,

  gv_summ TYPE int1.

START-OF-SELECTION.

  CREATE OBJECT go_test_exceptions.

  TRY.

    go_test_exceptions>do_summ(

      EXPORTING

        i_num_2 = 1

      RECEIVING

        re_summ = gv_summ

    ).

  CATCH lcx_no_num.

    WRITE ‘Не заполнены все параметры’.

  ENDTRY.

  go_test_exceptions>do_summ(

    EXPORTING

      i_num_1 = 999

      i_num_2 = 1

    RECEIVING

      re_summ = gv_summ

  ).

  WRITE: / ‘Результат cуммы 999 и 1:’, gv_summ.

В стандартной системе SAP имена всех классов особых ситуаций начинаются с CX_ , пользовательские исключения рекомендуется называть, начиная с ZCX или lcx для локальных классов исключений.

Класс CX_ROOT предоставляет некоторые предопределенные методы, которые наследуются всеми классами особых ситуаций:

  • Метод GET_SOURCE_POSITION возвращает имя главной программы и (если связаны) имена включенных программ (инклудов) и номер строки исходного кода, в которой возникла особая ситуация.
  • Метод GET_TEXT возвращает текст особой ситуации в форме строки.
  • Метод GET_LONGTEXT возвращает подробный текст текста особой ситуации в форме строки.

Тексты исключений

Каждому классу можно присвоить несколько текстов. Присвоенные им идентификаторы создаются построителем классов как константы в атрибутах класса. Тексты сохраняются в репозитарии текстов (OTR). Константы идентификаторы, представленные в шестнадцатеричном формате, уникальны на уровне системы:

14

Доступ к хранилищу текстов можно получить через транзакцию SOTR_EDIT.

В текстах можно определить параметры, их необходимо обозначить в амперсандах. В качестве примера, можно рассмотреть текст из класса исключения — CX_SY_FILE_IO:

15

В параметры будут переданы (при вызове метода GET_TEXT) соответствующие им атрибуты класса:

16

Заполняются эти атрибуты в конструкторе при вызове исключения:

DATA: lr_ex  TYPE REF TO cx_sy_file_io,

      lv_msg TYPE string.

TRY.

   ...

   RAISE EXCPETION TYPE cx_sy_file_io

      EXPORTING

         textid = cx_sy_file_io=>read_error

         filename = ‘somefile.txt’.

CATCH cx_sy_file_io INTO lr_ex.

   lv_msg = lr_ex>get_text( ).

   MESSAGE lv_msg TYPE ‘I’.

ENDTRY.

Так же в конструкторе можно указать, какой текст должен использоваться при инициировании особой ситуации, передав одну из определенных констант в параметр импорта TEXTID. Не рекомендуется использовать подобную методику, т.к. это может запутать код, однако как было уже показано выше SAP сам это использует (read_error, write_error в CX_SY_FILE_IO). Инкапсуляция текстов в классах сообщений и их саморасшифровываемость является одним из преимуществ над классическими исключениями.

Конструктор, который генерируется автоматически в SE24, для нового созданного исключения (ZCX_NO_NUM1), выглядит так:

CALL METHOD SUPER>CONSTRUCTOR

EXPORTING

TEXTID = TEXTID

PREVIOUS = PREVIOUS

.

IF textid IS INITIAL.

   me>textid = ZCX_NO_NUM1 .

ENDIF.

Блок обработки исключений

Особая ситуация может быть обработана, только если оператор, который может инициировать ее, заключен в блок TRY-ENDTRY. Затем особая ситуация обрабатывается с помощью оператора CATCH в блоке TRY-ENDTRY.

17

Блок TRY содержит набор операторов, обрабатывающих особые ситуации. Если в блоке TRY появляется особая ситуация, система осуществляет поиск первого оператора CATCH в том же блоке TRY-ENDTRY, а затем последовательно снаружи во всех заключающих блоках TRY-ENDTRY, обрабатывающих особую ситуацию. Если оператор находится, система осуществляет переход к его обработчику. Если обработчик найти не удается, но блок TRY-ENDTRY находится в процедуре, система осуществляет попытку передачи особой ситуации вызывающей программе.

Блок CATCH содержит обработчик особых ситуаций, исполняемый при возникновении указанной особой ситуации в связанном блоке TRY. Для оператора CATCH можно указать любое количество классов особых ситуаций. Таким образом, определяется обработчик особых ситуаций для всех этих классов особых ситуаций и их подклассов.

Блоки TRY-ENDTRY могут иметь вложенность любой глубины. Поэтому блок TRY, блоки CATCH и блок CLEANUP в целом сами могут содержать полные блоки TRY-ENDTRY.

При возникновении особой ситуации система осуществляет поиск по перечисленным обработчикам особых ситуаций в указанном порядке. Затем она исполняет первый обработчик особых ситуаций, оператор CATCH которого содержит подходящий класс особой ситуации или один из ее суперклассов.

Если ошибка не будет обработана и не будет передана вызывающей программе, система выдаст дамп с ошибкой времени выполнения — UNCAUGHT_EXCEPTION, в том случае когда не обрабатывается исключительная ситуация, связанная с ошибкой времени выполнения, система выдает дамп с ошибкой времени выполнения (например, CX_SY_CONVERSION_CODEPAGE — CONVT_CODEPAGE):

18

Просмотр ошибки в транзакции ST22:Безымянный

Распространение особых ситуаций

Если возникает особая ситуация (наследуемая от CX_DYNAMIC_CHECK, CX_STATIC_CHECK), она автоматически распространяется на все уровни стека вызовов, до тех пор, пока она не будет обработана или пока не встретится такой интерфейс, в котором она (либо её предки) будет отсутствовать.

Следующий пример демонстрирует распространение особой ситуации на несколько методов:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

CLASS lcx_calc_error DEFINITION INHERITING FROM cx_static_check.

ENDCLASS.

CLASS lcx_summ_error DEFINITION INHERITING FROM lcx_calc_error.

ENDCLASS.

CLASS lcl_test_exc DEFINITION.

  PUBLIC SECTION.

  METHODS:

    do_calc

      RAISING

        lcx_calc_error,

    do_summ

      RAISING

        lcx_summ_error.

ENDCLASS.

CLASS lcl_test_exc IMPLEMENTATION.

  METHOD do_calc.

    do_summ( ).

  ENDMETHOD.

  METHOD do_summ.

    RAISE EXCEPTION TYPE lcx_summ_error.

  ENDMETHOD.

ENDCLASS.

DATA:

  go_test TYPE REF TO lcl_test_exc.

START-OF-SELECTION.

  CREATE OBJECT go_test.

  TRY.

    go_test>do_calc( ).

  CATCH lcx_calc_error.

    WRITE ‘Catched’.

  ENDTRY.

Обратите внимание на метод do_calc, в нем описана особая ситуация от которой наследуется lcx_summ_error, соответственно прерывание продолжится на следующий уровень и будет обработано в блоке TRY..CATCH..ENDTRY. При правильно выстроенной архитектуре наследования исключительных ситуаций, прозрачность кода заметно повышается.

В случае, когда используется исключение, наследуемое от CX_NO_CHECK, описание его в интерфейсе метода может быть опущено, т.к. оно инициируется неявным способом системой:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

CLASS lcx_calc_error DEFINITION INHERITING FROM cx_no_check.

ENDCLASS.

CLASS lcx_summ_error DEFINITION INHERITING FROM lcx_calc_error.

ENDCLASS.

CLASS lcl_test_exc DEFINITION.

  PUBLIC SECTION.

  METHODS:

    do_calc,

    do_summ.

ENDCLASS.

CLASS lcl_test_exc IMPLEMENTATION.

  METHOD do_calc.

    do_summ( ).

  ENDMETHOD.

  METHOD do_summ.

    RAISE EXCEPTION TYPE lcx_summ_error.

  ENDMETHOD.

ENDCLASS.

DATA:

  go_test TYPE REF TO lcl_test_exc.

START-OF-SELECTION.

  CREATE OBJECT go_test.

  TRY.

    go_test>do_calc( ).

  CATCH lcx_calc_error.

    WRITE ‘Catched’.

  ENDTRY.

Очистка после вызовов исключений

Блок CLEANUP исполняется, когда выполнен выход из блока TRY-ENDTRY, так как система не смогла найти обработчик для исключения в определенном блоке TRY-ENDTRY, но особая ситуация обрабатывается в окружающем блоке TRY-ENDTRY или передается вызывающей программе.

Данный блок обычно применяется для освобождения занятых ресурсов: очистке ссылочных переменных, закрытие локаторов или наборов данных (datasets) и т.п. Допустим, Вы записываете некоторые данные в файл на сервере приложений. Внутри блока TRY Вы открываете набор данных (dataset) и начинаете запись в него. Однако в некоторый момент, случается особая ситуация, которую вы не обработали и блок TRY прерывает свою работу, при этом, не выполнив закрытие набора данных. Для того чтобы избежать подобной ситуации воспользуемся ключевым словом CLEANUP:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

TRY.

*  Открываем файл на запись:

   OPEN DATASET lv_file FOR OUTPUT IN TEXT MODE

                        ENCODING DEFAULT.

*  Переносим данные в файл:

   LOOP AT lt_extract INTO ls_record.

      PERFORM sub_format_record CHANGING ls_record.

      TRANSFER ls_record TO lv_file.

   ENDLOOP.

*  Закрываем файл:

   CLOSE DATASET lv_file.

CATCH cx_sy_file_access_error INTO lr_file_ex.

*  Ошибки ввода, вывода (датасет в таком случае не открыт)…

CATCH lcx_format_error INTO lr_format_ex.

*  Обрабатываем свою внутренюю ошибку при форматировании…

*  при этом необходимо закрыть набор данных

   CLOSE DATASET lv_file.

CLEANUP.

*  В случае если возникнет не обработанное исключение закроем набор данных:

   CLOSE DATASET lv_file.

ENDTRY.

В случае возобновляемых оператором RESUME исключений, блок CLEANUP не выполняется. Блок CLEANUP, как и блок CATCH позволяет получить ссылочную переменную на вызванное исключение, с помощью дополнения [INTO oref].

Передача исключений по цепочке

Необходимо понимать, что особая ситуация может передаваться через любое количество иерархий вызова перед финальной обработкой. Одна особая ситуация может инициировать вторую и т. д. Каждая инстанция должна оставаться действительной, независимо то того, был ли связанный блок CATCH уже обработан или нет. Поэтому необходимо убедиться, что предыдущая инстанция особой ситуации доступна с помощью, по крайней мере, одной ссылки. Атрибут общей инстанции PREVIOUS, наследуемый всеми классами особых состояний из CX_ROOT, обеспечивает удобный для этого способ.

Пример:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

CLASS lcx_very_big DEFINITION INHERITING FROM cx_static_check.

ENDCLASS.

CLASS lcx_calc_error DEFINITION INHERITING FROM cx_static_check.

ENDCLASS.

CLASS lcl_test_exceptions DEFINITION.

  PUBLIC SECTION.

    METHODS:

      do_calc IMPORTING

                i_num_1 TYPE i OPTIONAL

                i_num_2 TYPE i OPTIONAL

              RETURNING VALUE(re_result) TYPE i

              RAISING lcx_calc_error.

  PRIVATE SECTION.

    METHODS:

      do_summ IMPORTING

                i_num_1 TYPE i OPTIONAL

                i_num_2 TYPE i OPTIONAL

              RETURNING value(re_summ) TYPE i

              RAISING lcx_very_big.

ENDCLASS.

CLASS lcl_test_exceptions IMPLEMENTATION.

  METHOD do_summ.

    re_summ = i_num_1 + i_num_2.

    IF re_summ > 100.

      RAISE EXCEPTION TYPE lcx_very_big.

    ENDIF.

  ENDMETHOD.

  METHOD do_calc.

    DATA:

      lo_very_big TYPE REF TO lcx_very_big.

    TRY.

      me>do_summ(

        EXPORTING

          i_num_1 = i_num_1

          i_num_2 = i_num_2

        RECEIVING

          re_summ = re_result

      ).

    CATCH lcx_very_big INTO lo_very_big.

      RAISE EXCEPTION TYPE lcx_calc_error EXPORTING previous = lo_very_big.

    ENDTRY.

  ENDMETHOD.

ENDCLASS.

DATA:

  go_test_exceptions TYPE REF TO lcl_test_exceptions,

  gv_result TYPE i,

  go_calc_error TYPE REF TO lcx_calc_error,

  go_big_error  TYPE REF TO lcx_very_big.

START-OF-SELECTION.

  CREATE OBJECT go_test_exceptions.

  TRY.

    go_test_exceptions>do_calc(

      EXPORTING

        i_num_1   = 1000

        i_num_2   = 500

      RECEIVING

        re_result = gv_result

    ).

  CATCH lcx_calc_error INTO go_calc_error.

    go_big_error ?= go_calc_error>previous.

  ENDTRY.

Таким образом, пройдя по цепочке, мы всегда можем определить, в каком конкретном месте было инициировано исключение и что из-за этого произошло. Иногда при построении какой-либо ООП модели, удобно собрать всю цепочку из ошибок в каком-нибудь одном виде и выдать в качестве универсального исключения, в качестве примера рекомендую посмотреть этот пример.

Возобновляемые исключения и повтор блока TRY

При срабатывании исключения, выполнение программы в текущем контексте завершается. Иногда необходимо не завершать выполнение текущего контекста, для этого были созданы так называемые возобновляемые исключения. Для того чтобы вызвать такое исключение, необходимо в операторе RAISE (или в THROW) указать что вызывается именно возобновляемое исключение, при этом для того чтобы воспользоваться оператором RESUME (который возвращает код обратно в то место где было вызвано исключение), необходимо у оператора CATCH указать дополнение BEFORE UNWIND (обозначает обработку возобновляемого исключения), иначе система вызовет исключение CX_SY_ILLEGAL_HANDLER. При возврате в контекст, из которого было вызвано исключение блок CLEANUP не вызывается. Если в указанном в CATCH блоке не будет вызван оператор RESUME, контекст будет удален при выходе из блока CATCH.

Пример обработки возобновляемого исключения:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

CLASS lcx_no_num DEFINITION INHERITING FROM cx_static_check.

ENDCLASS.

CLASS lcx_less_zero DEFINITION INHERITING FROM cx_no_check.

ENDCLASS.

CLASS lcl_test_exceptions DEFINITION.

  PUBLIC SECTION.

    METHODS:

      do_summ IMPORTING

                i_num_1 TYPE i OPTIONAL

                i_num_2 TYPE i OPTIONAL

              RETURNING value(re_summ) TYPE int1

              RAISING RESUMABLE(lcx_no_num).

ENDCLASS.

CLASS lcl_test_exceptions IMPLEMENTATION.

  METHOD do_summ.

    IF i_num_1 IS NOT SUPPLIED OR i_num_2 IS NOT SUPPLIED.

      » Данное исключение присутствует в интерфейсе, может быть обработано вне метода

      RAISE RESUMABLE EXCEPTION TYPE lcx_no_num.

    ENDIF.

    TRY.

      re_summ = i_num_1 + i_num_2.

      » Динамическая ошибка, при её обработке обнулим результат

    CATCH CX_SY_CONVERSION_OVERFLOW.

      re_summ = 0.

    ENDTRY.

  ENDMETHOD.

ENDCLASS.

DATA:

  go_test_exceptions TYPE REF TO lcl_test_exceptions,

  gv_summ TYPE int1.

START-OF-SELECTION.

  CREATE OBJECT go_test_exceptions.

  TRY.

    go_test_exceptions>do_summ(

      EXPORTING

        i_num_2 = 1

      RECEIVING

        re_summ = gv_summ

    ).

  CATCH BEFORE UNWIND lcx_no_num.

    RESUME.

  ENDTRY.

  WRITE: / ‘Cумма без указания 1-го числа’, gv_summ.

  go_test_exceptions>do_summ(

    EXPORTING

      i_num_1 = 999

      i_num_2 = 1

    RECEIVING

      re_summ = gv_summ

  ).

  WRITE: / ‘Результат cуммы 999 и 1:’, gv_summ.

При обработке исключений так же есть возможность повтора блока TRY..CATCH, делается это с использованием оператора RETRY. Пример:

PARAMETERS: number1 TYPE i,

            number2 TYPE i.

DATA result  TYPE p DECIMALS 2.

TRY.

    result = number1 / number2.

  CATCH cx_sy_zerodivide.

    number1 = 0.

    RETRY.

ENDTRY.

В данном случае если номер 2 будет равен нулю, система вызовет исключение, с помощью RETRY мы заново запустим блок TRY..CACTH, при этом уже исключение не возникнет, т.к. при делении нуля на ноль результатом будет ноль.

Отображение сообщений из классов сообщений в тексты исключений

Начиная с версии 6.40, появилась возможность связывать тексты исключительных сообщений с классами сообщений (транзакция SE91). Как уже упоминалось выше для этого необходимо в конструкторе класса, указать галочку класс сообщений. При этом вместо интерфейса IF_MESSAGE будет внедрен интерфейс IF_T100_MESSAGE (таблица T100 хранит в себе эти сообщения):

19

При редактировании текста, необходимо будет привязать его к классу и номеру сообщения, при этом заполнить параметры, если это необходимо:

20

Начиная с NW 2004, оператор MESSAGE позволяет напрямую обработку исключений, внедряющих интерфейс IF_T100_MESSAGE:

TRY.

   ...

CATCH cx_some_exception INTO lr_ex.

   MESSAGE lr_ex TYPE ‘E’.

ENDTRY.

Локальный класс исключения в приватном методе глобального класса

Бывают ситуации, когда для какого-либо приватного метода необходимо реализовать исключение, которое может быть вызвано исключительно данным методом (классом).  Реализовать подобное можно, если создать локальный класс исключений:

  • Перейти в локальные определения/внедрения:

21

  • Создать класс исключения:

22

  •  Указать в методе имя локального класса исключения (обязательно в режиме редактирования исходного кода):

23

Результат:

24

Если попробовать сделать тоже самое в режиме редактирования на основе формуляров, выскочит предупреждение о том, что такого класса не существует:

25

Более подробно об исключениях можно почитать в официальной документации:

http://help.sap.com/abapdocu_740/en/abenabap_exceptions.htm

Оператор MESSAGE служит для диалогового взаимодействия с пользователем. Существует шесть типов сообщения.

Тип Описание
S Status (Success). Сообщение отображается в статусной строке и не влияет на работу программы. Данный вид сообщения применяется для информирования об успешной выполнении операции.
status-message
W Warning. Предупредительные сообщения отображаются в статусной строке. При возникновении сообщения работа программы прерывается, а пользователю предоставляется возможность вносить исправления в полях для ввода. При нажатии на Enter в диалоговом режиме, работа программы будет восстановлена.
warning-message
E Error. Сообщение отображается в статусной строке. При возникновении данного вида сообщения обработка программы останавливается.
error-message
I Information. Информационное сообщение отображается в отдельном модальном окне. При возникновении сообщения работа программы прерывается. После закрытия диалога работа программы восстанавливается.
imformation-message
A Abend (Abort). Сообщение отображается в модальном окне. При возникновении сообщения программа завершается, а система возвращается в меню более высокого уровня. Сообщения стоит применять только в крайних ситуациях.
abend-message
X Exception. Сообщение инициирует дамп MESSAGE_TYPE_X. Данный вид сообщения стоит применять в ситуациях, когда нужно проанализировать что именно привело к ошибке во время выполнения.
x-message

Синтаксис

MESSAGE { msg | text | exception }
{ { [DISPLAY LIKE dtype] [WITH dobj1 … dobj4] }
| { [DISPLAY LIKE dtype] [WITH dobj1 … dobj4] RAISING exception }
| { [WITH dobj1 … dobj4] INTO text } }.

После вызова оператора MESSAGE заполняются системные поля

Поле Значение
sy-msgid Содержит класс сообщения
sy-msgno Содержит номер сообщения
sy-msgty Содержит тип сообщения (S,I,W,E,A,X)
sy-msgv1 .. sy-msgv4 Содержит данные сообщения, указанные после добавления WITH

Для вывода сообщений используются классы сообщений, которые создаются в тр. SE91
se91

MESSAGE — msg

При выводе сообщений нужно указать: класс, номер и тип сообщения

MESSAGE tn(id)
MESSAGE tn
MESSAGE ID mid TYPE mtype NUMBER num.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

*&———————————————————————*

*& Report  Z_MESSAGE

*& Возможности оператора MESSAGE

*&———————————————————————*

*& Примеры использования оператора MESSAGE

*& http://abap4.ru/?p=360

*&———————————————————————*

REPORT z_message MESSAGE-ID 00.

START-OF-SELECTION.

  PERFORM main.

FORM main.

  » Краткая запись

  MESSAGE s002(00).

  » Краткая запись. Класс сообщения указывается в MESSAGE-ID программы

  MESSAGE s002.

  » Полная запись с указанием класса, типа и номера в отдельных полях

  MESSAGE ID ’00’ TYPE ‘S’ NUMBER ‘002’.

ENDFORM.

Результат работы программы
Класс сообщения 00, номер сообщения 002

MESSAGE — text

MESSAGE text TYPE mtype.

В также MESSAGE можно передать свободный текст. В этом случае класс сообщения будет 00, номер сообщения 001. Данный вариант обычно используют когда нет возможности определить сообщения в SAP, например когда текст сообщения формируется во внешних системах.

*&———————————————————————*

*& Пример вывода текста

*& http://abap4.ru/?p=360

*&———————————————————————*

REPORT z_message.

START-OF-SELECTION.

  PERFORM main.

FORM main.

  MESSAGE ‘Текст сообщения’ TYPE ‘I’.

ENDFORM.

Результат работы программы
free-text
В системных полях будет сообщение базисного класса 001(00)
free-text-sy

MESSAGE — exception

MESSAGE oref TYPE mtype.

В также MESSAGE можно передать исключение. Результат будет аналогичен выводу исключения.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

*&———————————————————————*

*& Пример вывода исключения

*& http://abap4.ru/?p=360

*&———————————————————————*

REPORT z_message.

START-OF-SELECTION.

  PERFORM main.

FORM main.

  DATA lr_root TYPE REF TO cx_root.

  DATA lv_value TYPE i.

  TRY .

    lv_value = 1 / 0.

  CATCH cx_root INTO lr_root.

    MESSAGE lr_root TYPE ‘I’.

  ENDTRY.

ENDFORM.

Результат работы программы
devide-by-zero
Значения системных полей
devide-by-zero-sy

MESSAGE — WITH

MESSAGEWITH dobj1 … dobj4.

Сообщения могут содержать параметры, которые передаются через дополнение WITH. Пример вывода сообщения 076(va) с двумя параметрами.
076(va)

*&———————————————————————*

*& Вывод сообщения с параметрами

*& http://abap4.ru/?p=360

*&———————————————————————*

REPORT z_message.

START-OF-SELECTION.

  PERFORM main.

FORM main.

  MESSAGE i076(va) WITH ‘TESTVAR’ syrepid.

ENDFORM.

Результат работы программы
message-with

MESSAGE — DISPLAY LIKE

MESSAGEDISPLAY LIKE dtype.

При использовании дополнения DISPLAY LIKE, происходит замена иконки на специфичную для типа, указанного в dtype. В dtype можно передать одно из следующих значений: A, E, I, S или W. Данное дополнение нельзя использовать для сообщения типа X, оно всегда вызывает дамп. DISPLAY LIKE обычно используется в ситуациях, когда нужно отобразить ошибку, но не прерывать выполнение программы.

*&———————————————————————*

*& Пример использования DISPLAY LIKE

*& http://abap4.ru/?p=360

*&———————————————————————*

REPORT z_message.

START-OF-SELECTION.

  PERFORM main.

FORM main.

  MESSAGE ‘Ошибка в модальном окне’ TYPE ‘I’ DISPLAY LIKE ‘E’.

ENDFORM.

Результат работы программы
i-as-e

MESSAGE — INTO

MESSAGEINTO text.

При использовании дополнения INTO, в переменную text записывается короткий текст сообщения. Само сообщение при этом, не отображается. Данное дополнение обычно применяют в двух случаях: когда нужно получить текст сообщения; когда нужно заполнить системные переменные для дальнейшего использования, например, для журнала приложений.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

*&———————————————————————*

*& Пример использования MESSAGE INTO

*& http://abap4.ru/?p=360

*&———————————————————————*

REPORT z_message.

START-OF-SELECTION.

  PERFORM main.

FORM main.

  DATA lv_text TYPE text120.

  MESSAGE e036(60) WITH ‘2100’ INTO lv_text. » Балансовая единица «&» неизвестна (ввести существующую БЕ).

  WRITE: / ‘TEXT: ‘, lv_text.

  WRITE: / ‘SY-MSGID: ‘, symsgid.

  WRITE: / ‘SY-MSGTY: ‘, symsgty.

  WRITE: / ‘SY-MSGNO: ‘, symsgno.

  WRITE: / ‘SY-MSGV1: ‘, symsgv1.

  WRITE: / ‘SY-MSGV2: ‘, symsgv2.

  WRITE: / ‘SY-MSGV3: ‘, symsgv3.

  WRITE: / ‘SY-MSGV4: ‘, symsgv4.

ENDFORM.

message-into

MESSAGE — RAISING

MESSAGERAISING exception.

Оператор MESSAGE вместе с дополнением RAISING представляет собой комбинацию операторов MESSAGE и RAISE. Данное дополнение имеет смысл только во время обработки методов и функциональных модулей, в которых определено исключение старого типа (основанного не на классах). Если вызывающий метод или функциональный модуль обрабатывает данное исключение в EXCEPTIONS, то MESSAGE .. RAISING работает аналогично оператору RAISE. Если же вызывающей стороне исключение не обрабатывается, то RAISING игнорируется.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

*&———————————————————————*

*& Пример использования MESSAGE RAISING

*& http://abap4.ru/?p=360

*&———————————————————————*

REPORT z_message.

CLASS c1 DEFINITION.

  PUBLIC SECTION.

    CLASS-METHODS m1 EXCEPTIONS exc1.

ENDCLASS.

CLASS c1 IMPLEMENTATION.

  METHOD m1.

    MESSAGE ‘Сообщение с RAISING’ TYPE ‘I’ RAISING exc1.

  ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.

  PERFORM main.

FORM main.

  c1=>m1( ).                      » Отработает MESSAGE

  c1=>m1( EXCEPTIONS exc1 = 4 ).  » Отработает RAISING

  IF sysubrc = 4.

  ENDIF.

ENDFORM.

Preface – This post is part of the ABAP Beginner series.

Introduction

A programmer always tries to code in such a way that his code is bug free and full proof. But there are certain scenarios, where his codes can fail. In such case, if the coder already knows the scenarios, then he handle them in form of Error handling. But, in case of situations, where an error can be generated due to unknown situations and left un-handled can cause serious dumps. For these scenarios, we have exception handling in SAP. In this article we will explore all scenarios of Exception and Error Handling in ABAP Reports

Exception and Error Handling in SAP ABAP Reports

As discussed above, a coder is required to handle known issues as well as intended error messages. These messages are shown to user in the output via MESSAGE statement.

Different ways to catch Errors/Exception

ABAP provides various ways to catch errors in an ABAP program.

  1. Using System Variable

The simplest way is to use their system variables.

 SY-SUBRC EQ  0. "This statement indicates that an operation completed successfully.
 SY-SUBRC NE  0. "This statement indicates that an operation has failed.

This way works directly if the entire code of report was process within the same program. It means, it cannot catch an error directly in case you have processed a Function Module or ABAP Class statements. For those entity, we need to raise exception from their end, and then exception can be handled in the report and processed accordingly.

  1. Catching Errors based on Exception

In case, we implement a function module or method of a class, then it is important to raise exception from these classes and then we can catch these exceptions in report and show respective error.

For Example:

CALL FUNCTION 'Test_Function'
     EXPORTING
          DELIMITER =   ':'
          STRING        =   lv_string
     IMPORTING
          HEAD           =   lv_head
          TAIL             =   lv_tail
     EXCEPTIONS
          NOT_FOUND   =  1
          OTHERS       =   2.


CASE SY-SUBRC.
     WHEN 1. ...
// Show Error Message
     WHEN 2. ...
// Show Error Message
     WHEN OTHER.
// Show Error Message
ENDCASE.
  1. Using TRY CATCH ENDTRY

In case an exception is raised via a method of class, or an unexpected exception is raised, in these cases, we use TRY CATCH functionality of SAP ABAP. This is one of the best full proof way to handle all types of exceptions.

Example:

TRY.
     //Call your class or function module here
CATCH CX_SY_ZERODIVIDE INTO O_REF. // The exception you have raised there
     MESSAGE “Your Error Message”.
ENDTRY.

Different ways to show Messages

  1. Using ABAP Statement

Syntax:

MESSAGE ‘<Enter Your Text here>’ TYPE ‘Enter the type of Message here’.

Types of Message

ABAP provides the following 6 types of messages:

Message Type Meaning Explanation
A Termination This message is shown during program termination.
E Error This message is shown during Error.
I Information This message is used to show any information.
S Success This shown in the status of the Output screen.
W Warning It behaves like an error message.
X Exit It causes a short dump with error message.
  1. Using Predefined Function Modules

ABAP provides following function modules that can be used to store, format and show messages altogether:

Function Module Usage
MESSAGES_INITIALIZE To Initialize the messages.
MESSAGE_STORE To Store the messages to be displayed.
MESSAGES_SHOW To Display all the messages together on a pop up
FORMAT_MESSAGE To Format the messages
HR_DISPLAY_ERROR_LIST To display all the error messages

Example:

  1. Using Message Statement
MESSAGE 'This is an error message' TYPE 'E'.
  1. Using Multiple functions to store and show messages:
" It is Initialized only initially...
* Initialize your messages
  CALL FUNCTION 'MESSAGES_INITIALIZE'
    EXCEPTIONS
      log_not_active       = 1
      wrong_identification = 2
      OTHERS               = 3.
"One by one append all your messages here
      PERFORM store_messages USING 'E'
                                   w_pn
                                   w_batch2
                                   w_werks
                                   ' '
                                   w_msgno.
FORM store_messages USING p_msgty
                          p_msgv1
                          p_msgv2
                          p_msgv3
                          p_msgv4
                          p_txtnr.
  IF p_msgty EQ 'E'.
    w_err_fg = 'X'.
  ENDIF.
* Store all your messages meant to be displayed
  CALL FUNCTION 'MESSAGE_STORE'
    EXPORTING
      arbgb                  = 'ZCCH001'
      msgty                  = p_msgty
      msgv1                  = p_msgv1
      msgv2                  = p_msgv2
      msgv3                  = p_msgv3
      msgv4                  = p_msgv4
      txtnr                  = p_txtnr
    EXCEPTIONS
      message_type_not_valid = 1
      not_active             = 2
      OTHERS                 = 3.
ENDFORM.                    " STORE_MESSAGES
"In the end fetch all your message and show them altogether
* This displays all the messages in a popup
  CALL FUNCTION 'MESSAGES_SHOW'
    EXPORTING
      show_linno         = ' '
    IMPORTING
      e_exit_command     = wa_exit_command
    EXCEPTIONS
      inconsistent_range = 1
      no_messages        = 2
      OTHERS             = 3.
  1. Using HR_DISPLAY_ERROR_LIST
DATA:
it_error        TYPE STANDARD TABLE OF HRERROR,"TABLES PARAM
wa_error     LIKE LINE OF it_error .
DATA(ld_no_popup) = 'some text here'.
DATA(ld_no_print) = 'some text here'.
DATA(ld_no_img) = 'some text here'.
DATA(ld_no_msgno) = 'some text here'.
DATA(ld_linesize) = '123 '.
DATA(ld_listheader) = 'Check type of data required'.
DATA(ld_colheader) = 'Check type of data required'.
DATA(ld_hidemsg) = 'some text here'.
 
 
"populate fields of struture and append to itab
append wa_error to it_error.
.
CALL FUNCTION 'HR_DISPLAY_ERROR_LIST'
* EXPORTING
*   no_popup =                   ld_no_popup
*   no_print =                   ld_no_print
*   no_img =                     ld_no_img
*   no_msgno =                   ld_no_msgno
*   linesize =                   ld_linesize
*   listheader =                 ld_listheader
*   colheader =                  ld_colheader
*   hidemsg =                    ld_hidemsg
* TABLES
*   error =                      it_error
  EXCEPTIONS
    INVALID_LINESIZE =           1
    .  "  HR_DISPLAY_ERROR_LIST
IF SY-SUBRC EQ 0.
  "All OK
ELSEIF SY-SUBRC EQ 1. "Exception
  "Add code for exception here
ENDIF.

How to create SAP ABAP Error Message Class

SAP ABAP Error Messages are very important for each ABAP program to know what is happening in that Program. Creating an error message class is very easy and we can create message classes using SE91 and SE38 Transaction codes.

Every Message has the message class and its ID and its Type.

Message Class in SAP ABAP

MESSAGE E001(MCLASS).

MESSAGE-Keyword

E-Message Type

001-Message Id

Mclass-Message class Name

Message Class TCode

SE91 and SE38 are message classTransaction codes.

Creating Message Class in SAP ABAP

First of all, Go to SE91 Tcode and Give the Message Class Name ZDEMO_MESSAGE and click on create

How to create SAP ABAP Error Message Class

In the Messages Tab, choose id and enter Message Description.

How to create SAP ABAP Error Message Class

Message Class has been created successfully. Now how to use created message class in the ABAP program.

MESSAGE I000(ZDEMO_MESSAGE).


Types of Messages in SAP ABAP

I — Information messages 

Information messages are displayed in a popup window and only pause processing until you have clicked through the message. 

E — Error message 

An error message will be displayed in red along the footer of the SAP screen and stops processing going any further. 

W — Warning message 

A warning message behaves similar to an error message and is displayed along the footer of the SAP screen.

S — Success/Status message 

A Success message is also displayed along the footer of the SAP screen but does not stop processing going any further and is simply displayed at the end in green. 

A — Termination/Abend 

A termination message stops processing and causes a run time error and short dump.

X — Exit 

An exit message stops processing and displays an exit button which exits session processing. 

How many ways can we display the messages in the SAP ABAP Program

a). MESSAGE ‘abs’ type ‘I’.

b). MESSAGE I003 (<Message Class>)

c). REPORT <Program Name> MESSAGE-ID <Message Class>.

        MESSAGE I006.

d). MESSAGE text-001 type ‘I’.

e). MESSAGE i009 WITH ‘create the correct sales order number'(003).

f). MESSAGE ID ‘<Message Class>’ type ‘I’ NUMBER 002.

g). MESSAGE i007 (<Message Class>) WITH ‘<Some text message> ‘.

h). MESSAGE i004 WITH text-003.

i). MESSAGE i002 (<Message Class>) WITH text-003.

j). MESSAGE i002 (<Message Class>) with p_user.

message class in sap abap
how to create message class in sap abap
message class tcode
message class
how to use message class in sap abap
create message class in sap abap
sap message class
message class in sap
sap message class tcode
tcode for message class
message class tcode in sap
tcode for message class in sap
message class tcode in sap abap
sap tcode message class
abap message class tcode
abap message class
sap create message class
message class in abap
tcode message class
how to create a message class in sap abap
message class in sap abap tcode
tcode for message class in sap abap
sap transaction message class
message class abap
abap create message class
abap message
sap tcode for message class
standard message class in sap abap
transaction for message class in sap
message class sap
sap abap message class
message class transaction sap
message class tcode sap
message class sap tcode
sap message class table
message abap
abap error message
abap message example
sap message class transaction
message class table in sap
how to write error message in sap abap
abap message id
se91 in sap
error message in sap abap
error message abap
sap abap message
message to class
sap message id tcode
se91 tcode in sap
sap abap error message
display error message in sap abap
sap change error message to warning
abap message types
sap abap message types
how to check message class in sap
how to display error message in sap abap
types of messages in sap abap
se91 sap
message types in sap abap
sap display message class
sap standard message class with
error message syntax in sap abap
sap abap message example
how to display multiple error messages in sap abap
message in sap abap
warning message in sap abap
abap text-001
messages in abap
abap class tcode
message with abap
se91
how to find message class in sap
sap se91

Popular posts from this blog

BADI Interview Questions in SAP ABAP

BADI Interview Questions in SAP ABAP A BAdI is an object-oriented enhancement option, which makes it the most sophisticated enhancement type. The main characteristic of a BAdI is that it provides a mechanism to change the functionality of a well-defined business function without making changes to the delivered source code. Future upgrades of the original business function can be applied without losing the customer-specific enhancements or the need to merge the changes.  If you want to become a professional and technical blogger practically, read these real-world practical SAP ABAP books . These books will help you to become a more flexible coding developer in future SAP technology. What is a BADI in SAP? BADI (Business Add-In) is a new SAP Object Oriented enhancement technique that is used to add our own business functionality to the existing SAP standard functionality.  BADI follows the Object-Oriented approach to make them reusable. A BADI can be used any number of times

Sample SAP ABAP Programming Examples for Practice

Sample SAP ABAP Programming Examples for Practice Are you a beginner at ABAP Language, you’re looking for example programs for practice. Here I collected some sample programs from various objects in ABAP that are useful for beginners to improve their Technical skills. To familiar with coding and ABAP applications, you must be practice all applications. As per my experience, practice makes you perfect, as a technical consultant, should be ready to develop any object based on the need of the client, then only, we will get appreciation from the client and from our team side and it helps us to develop complex objects in SAP. ABAP Syntax ABAP Statements ABAP Program Types SAP ABAP Workbench Tools SAP Modules SAP Transaction Codes SAP Tables SAP ABAP Hello world Program Example ABAP- Simple ALV report Example ABAP- Interactive ALV Report Example ABAP- BDC Call Transaction Method Programming ABAP- BDC Session Method Programming Example ABAP- Smartforms

Module Pool Programming Interview Questions and Answers in SAP ABAP

Module Pool Programming(Dialog Programming)  Interview Questions and Answers in SAP ABAP As an ABAP Consultant, you should be strong in Module pool programming techniques as well as when you face the real-time or fresher interview, Questions, and answers to test your talent to select for the interview. For that purpose, I am sharing my interview experiences in which I faced the most of the times on these topics that are at exit command, events difference between set screen and call screen difference between call screen and set screen in module pool,chain-end chain in module pool. What is the transaction code for the screen painter? SE51. What is the transaction code for Menu painter? SE41. What is the transaction code for the screen painter? SE93. What are the main components of dialog programs? Screens Module pools Subroutines Menus Transactions What is Screen flow Logic? The screen flow logic is like an ABAP program in that it serves as a

Step by Step tutorial on BDC Session Method Program in SAP ABAP

Image

Step by Step tutorial on BDC Session Method Program in SAP ABAP BDC Session Method is used to upload data from Non-SAP to SAP System. Using Session method, we can transfer data through more than one Transaction, Unlike BDC Call Transaction Method Program . We are Processing Batch input Session From SM35 Transaction Code. Session method. 1) synchronous processing. 2) can transfer a large amount of data. 3) processing is slower. 4) error log is created 5) data is not updated until the session is processed. Call transaction Method. 1) asynchronous processing 2) can transfer a small amount of data 3) processing is faster. 4) errors need to be handled explicitly 5) data is updated automatically Go to SHDB and Press Enter Click on New Recording Button and Give the zrecord1 name and enter transaction code MM01 and click on the Start recording button. The system goes to the Create material screen, there give the industry sector and material type and selects ba

SAP ABAP Interview Questions and Answers for 10 Years Experienced

SAP ABAP Interview Questions and Answers for 10 Years Experienced This post will helpful for SAP ABAP experienced candidates who may have 3,4 5, 6,7, and 10 years of experience, all of them can be follow this interview pattern for their successful interview.  SAP Data Dictionary Realtime Interview Questions SAP BDC Realtime Interview Questions SAP ALV Reports  Real-time Interview Questions Module Pool Interview Questions SAP Smartforms Realtime Interview Questions SAP BADI Realtime Interview Questions SAP BAPI Realtime Interview Questions SAP  IDOC Realtime Interview Questions ABAP Check and Value Table Questions SAP SD MM FICO Flow Interview Questions SAP OOPs Realtime Interview Questions SAP OOPs Part One  Real-time Interview Questions SAP OOPs Part two Real time Interview Questions SAP OOPs Part three Realtime Interview Questions SAP OOPs Part four Realtime Interview Questions ABAP  Realtime Interview Questio

What is Message?

Messages are used to describe what is happening in the program execution to the programmer or user. Messages represents with a three-digit number. Messages range starts from 000 to 999.

Message Types —

Messages are basically six types. Those are —

A Abend The message appears in a separate dialog box and the program execution get terminated.
When the user has confirmed the message, control returns to the next-highest area menu.
E Error An error dialog appears or the program terminates depending on the program condition.
I Information The message appears in a separate dialog box.
Once the user has confirmed the message, the program execution continues from the next statement coded immediately after the MESSAGE statement.
S Success The total program execution continues normally and the message is displayed in the status bar of the screen.
W Warning An error message is displayed in the status bar of the screen and the program execution terminates.
X Exit or Abort No message is displayed.
The program terminates with a short dump.
Program terminations with a short dump normally only occur when a runtime error occurs.

Message Usage —

Messages can be added to the program mostly in two ways. Those are —

  • Coding directly in the program
  • By using the message class.

Coding directly in the program —

Coding the message directly in the program is a very simple process. No definition was required before coding the message in the program.

Syntax —

MESSAGE {message-name} TYPE {message-type}.

  • Message — 80 characters user defined message.
  • Message-type — Specifies the message type.

Now, let us see how different message types coded one by one with seperate examples.

Example —

Display abend message.

Code —

*&---------------------------------------------------------------------*
*& Report  Z_MESSAGE
*&---------------------------------------------------------------------*
*& Written by TutorialsCampus
*&---------------------------------------------------------------------*

REPORT  Z_MESSAGE.

* Displaying Abend Message of type A
MESSAGE 'This is a Abend message' TYPE 'A'.

Output —

Abend message example display

Explaining Example —

In the above example, each and every statement is preceeded with a comment to explain about the statement. Go through them to get clear understanding of example code.

MESSAGE ‘This is a Abend message’ TYPE ‘A’. — Opens a popup and displays ‘This is a Abend message’ on the popup.

Example —

Display error message.

Code —

*&---------------------------------------------------------------------*
*& Report  Z_MESSAGE
*&---------------------------------------------------------------------*
*& Written by TutorialsCampus
*&---------------------------------------------------------------------*

REPORT  Z_MESSAGE.

* Displaying error Message of type E
MESSAGE 'This is a Error message' TYPE 'E'.

Output —

Error message example display

Explaining Example —

In the above example, each and every statement is preceeded with a comment to explain about the statement. Go through them to get clear understanding of example code.

MESSAGE ‘This is a Error message’ TYPE ‘E’. — Displays ‘This is a Error message’ on the output page status bar.

Example —

Display Informational message.

Code —

*&---------------------------------------------------------------------*
*& Report  Z_MESSAGE
*&---------------------------------------------------------------------*
*& Written by TutorialsCampus
*&---------------------------------------------------------------------*

REPORT  Z_MESSAGE.

* Displaying Informational Message of type I
MESSAGE 'This is a Informational message' TYPE 'I'.

Output —

informational message example display

Explaining Example —

In the above example, each and every statement is preceeded with a comment to explain about the statement. Go through them to get clear understanding of example code.

MESSAGE ‘This is a Informational message’ TYPE ‘I’. — Opens a popup and displays ‘This is a Informatonal message’ on the popup.

Example —

Display success message.

Code —

*&---------------------------------------------------------------------*
*& Report  Z_MESSAGE
*&---------------------------------------------------------------------*
*& Written by TutorialsCampus
*&---------------------------------------------------------------------*

REPORT  Z_MESSAGE.

* Displaying Success Message of type S
MESSAGE 'This is a Success message' TYPE 'S'.

Output —

Success message example display

Explaining Example —

In the above example, each and every statement is preceeded with a comment to explain about the statement. Go through them to get clear understanding of example code.

MESSAGE ‘This is a Success message’ TYPE ‘S’. — Displays ‘This is a Success message’ on the output page status bar.

Example —

Display warning message.

Code —

*&---------------------------------------------------------------------*
*& Report  Z_MESSAGE
*&---------------------------------------------------------------------*
*& Written by TutorialsCampus
*&---------------------------------------------------------------------*

REPORT  Z_MESSAGE.

* Displaying Warning Message of type W
MESSAGE 'This is a Warning message' TYPE 'W'.

Output —

Warning message example display

Explaining Example —

In the above example, each and every statement is preceeded with a comment to explain about the statement. Go through them to get clear understanding of example code.

MESSAGE ‘This is a Warning message’ TYPE ‘W’. — Displays ‘This is a Warning message’ on the output page status bar.

Example —

Display exit message.

Code —

*&---------------------------------------------------------------------*
*& Report  Z_MESSAGE
*&---------------------------------------------------------------------*
*& Written by TutorialsCampus
*&---------------------------------------------------------------------*

REPORT  Z_MESSAGE.

* Displaying Exit Message of type X
MESSAGE 'This is a Exit message' TYPE 'X'.

Output —

Exit message example display

Explaining Example —

In the above example, each and every statement is preceeded with a comment to explain about the statement. Go through them to get clear understanding of example code.

MESSAGE ‘This is a Exit message’ TYPE ‘X’. — Displays ‘This is a Exit message’ on the output exit page.

Using the message class —

In this scenario, messages gets displayed from the message class that is defined by using MESSAGE-ID along with the REPORT command. Message number is a three-character code that can define a set of 1000 messages and those are accessed when MESSAGE command executed in the program.

Messages number ranges from 000 to 999 (i.e. 1000 messages). Each message associated with message number and the message length can be upto 80 characters.
When a message number used in the program, the corresponding message retrived from the message class and gets displayed.

Syntax —

MESSAGE {message-name} WITH field1 ... field4.

This addition replaces the placeholders «&1» to «&4» and «&» of the short text or «&V1&» to «&V4&» of the long text of of the operands field1, …, field4. Up to four operands field1 through field4 can be specified.

Messages are not always static and some part of the message can be filled with a dynamic or runtime text.
While creating a custom message, Amber sign (&) symbol used in the place of dynamic or runtime text.
The MESSAGE…WITH statement used to pass the dynamic or runtime text during the program execution.

Example —

Create a message class with a template message and pass the runtime text to complete the message.

First we need to create the message class with MESSAGE-ID by coding in the program.

Step-1: Code MESSAGE-ID along with REPORT shown like below. ZMG_CUSTMESG is the new message class.

create custom message1

Step-2: Double click on the message class name (ZMG_CUSTMESG) to create it. The Create Object diaglog gets opened.

create custom message2

Step-3: Click on «YES» to create new. It directs to Message Maintenance screen.

create custom message3

Step-4: Once the required information updated, move to «Messages» tab or Save button. Below screen gets appear.

create custom message4

Step-5: Select the desired package and click on «Local Object» button or «Save«. The Messages tab gets opened like below.

create custom message5

Step-6: Create the messages that required and click on «Save» button to save. Now newly created message class gets saved and it routes to ABAP Editor to continue the program coding.

Note! The message added with &. ‘&‘ used to pass custom information from the MESSAGE…WITH statement to the message text.
The text in the MESSAGE statement replaces ‘&‘ and displays the message.

Step-7: Open ABAP editor and complete the coding in the program.

create custom message6

The message defined for the message number 000 is ‘This is a & Message’. We are passing custom text(‘Informational’) in MESSAGE….WITH statement. So the ‘&’ replaces with ‘Informational’ and displays the message as ‘This is a Informational message’. As it is an message type ‘I’, it displays in separate dialog box.

Step-8: Execute the program to display the output.

Finally, the custom message displayed with dynamic or runtime text ‘Informational’. The output ‘This is Informational Message’ gets displayed on the seperate informational dialog box.

В ABAP реализован достаточно мощный механизм использования сообщений, в который интегрированы и локализация, и включение переменных в текст сообщений, передача этих сообщений в RFC, использование в классических и объектных исключениях, логирование, а также широкие возможности по выводу сообщений на различных вариантах GUI. При этом часто возникает необходимость передавать сообщения не поодиночке, а списком, например по завершении какого-то комплексного процесса, состоящего из шагов, либо при вызове программного модуля (RFC, BAPI и т.п.), возвращающего список сообщений.

Достаточно распространенной является практика использования таблицы со структурой BAPIRET в той или иной модификации. Как правило, таблица содержит не только сообщения, но и дополнительную информацию, как статусы, информация для логирования и другое.

Несмотря на простоту и распространенность этого решения, часто возникают похожие задачи по работе с данными из таких списков. Например получение наихудшего статуса, выбор сообщений с определенным статусом, добавление/удаление сообщений, логирование списка и прочее. Так или иначе на крупных проектах это приводит к необходимости создания некой обертки над списком сообщений, которая будет реализовывать весь функционал по работе с ним. Написание подобных классов — довольно увлекательный процесс, однако следует знать, что в стандарте уже существуют решения, способные покрыть почти все эти требования. О наиболее распространенных из них я расскажу в этой заметке.

##RECA

В стандартной поставке ABAP есть пакет RECA, включающий в себя множество утилитарных классов, решающих широкий спектр технических задач. Пакет входит в модуль RE-FX, который поставляется в составе SAP ERP, однако может быть найден и в других системах, например в EHS. Многие этих классов достойны отдельных статей, но сегодня мы поговорим об одном из них — CL_RECA_MESSAGE_LIST, а точнее его интерфейсе IF_RECA_MESSAGE_LIST, через который он и будет использоваться в программе.

Интерфейс имеет множество методов для работы со списком сообщений, для добавления сообщений из разных источников, для анализа сообщений и работы с логированием. Ниже я рассмотрю некоторые из них.

Инстанция создается через factory класс:

DATA:
  lo_message_list TYPE REF TO if_reca_message_list.

lo_message_list = cf_reca_message_list=>create( ).

В метод можно передать параметры BAL объекта, если вы хотите сохранять в него сообщения. Также класс cf_reca_message_list предоставляет инструментарий для поиска существующих BAL объектов.

IF_RECA_MESSAGE_LIST позволяет добавлять сообщения из различных источников: через указание номера сообщения, из объекта исключения, из таблицы BAPIRET, из sy, а также из другого объекта сообщений.

lo_message_list->add(
  id_msgty = 'S'
  id_msgid = 'RDA'
  id_msgno = 24
  id_msgv1 = 'test'
).

*CALL BAPI
lo_message_list->add_from_bapi(
  it_bapiret = lt_bapi_result
).

*CATCH cx_root INTO lo_exception.
lo_message_list->add_from_exception(
  io_exception = lo_exception
).

lo_message_list->add_from_instance(
  io_msglist = lo_message_list2
).

lo_message_list->add_symsg( ).

Стоит обратить внимание, что в интерфейсе нет метода, позволяющего добавлять сообщение из символьной переменной. Вероятно это связано с тем, что тексты в литералах являются плохим тоном в ABAP, так как не позволяют осуществлять перевод и затрудняют поддержку. Если вы один из тех, кто хардкодит тексты в строковые переменные, то при работе с этим объектом от такого подхода придется отказаться.

Этот контейнер удобно использовать как возвращаемый параметр метода, который выполняет цепочку действий, статус которых вы хотите в дальнейшем как-то использовать. Также удобно записывать сообщения, которые возвращают BAPI и другие ФМ, в частности те, что вызываются по RFC — зачастую они возвращают список сообщений именно в формате BAPIRET или близком к нему, который несложно сконвертировать в нужный.

DATA:
  lt_message_1 TYPE bapiret1_tab,
  lt_message_2 TYPE mmpur_message_list.

lo_message_list->add_from_bapi(
  it_bapiret = CORRESPONDING #( lt_bapi_result )
).

lo_message_list->add_from_bapi(
  it_bapiret = CORRESPONDING #( lt_message_2 MAPPING
    type        = msgty
    id          = msgid
    number      = msgno
    message_v1  = msgv1
    message_v2  = msgv2
    message_v3  = msgv3
    message_v4  = msgv4
  )
).

Класс также позволяет получить сообщения обратно в удобном виде — получить все сообщения в виде таблицы BAPIRET, получить первое или последнее сообщение, отфильтровать сообщения по типу.

Помимо этого, класс позволяет получать различные аналитические данные по сообщениям, на основе которых удобно строить различные логигческие конструкции и проверки, не обращаясь раз за разом к самому списку напрямую. Например, можно получить статистику по всему списку сообщений, либо проверить, есть ли сообщения с определенным типом и есть ли сообщения вообще.

IF lo_message_list->has_messages_of_msgty( 'E' ).
*  error processing of types E and X
ENDIF.

DATA(ls_msg_statistics) = lo_message_list->get_statistics( ).

IF ls_msg_statistics-msg_cnt_e > 0 OR ls_msg_statistics-msg_cnt_a > 0.
*  error processing
ELSEIF ls_msg_statistics-msg_cnt_w > 0.
*  warning processing
ELSE.
*  success processing
ENDIF.

Ну и помимо прочего в контейнер встроен функционал по работе с BAL, например изменение заголовка, изменение уровня детализации сообщений и, конечно, сохранение. Пример использования:

lo_message_list = cf_reca_message_list=>create(
    id_object       = 'ZTEST'
    id_subobject    = 'SUBTEST'
    id_extnumber    = CONV #( sy-repid )
).

MESSAGE s000(00) INTO lv_dummy.
lo_message_list->add_symsg( ).
lo_message_list->store( ).

Для вывода сообщений класса на экран в классическом Dynpro можно воспользоваться ФМ RECA_GUI_MSGLIST_POPUP, который выводит сообщения на стандартном экране лога.

Контейнер сообщений с подобным функционалом находит множество вариантов применения. Помимо очевидных вариантов вроде возвращаемого параметра, контейнер можно использовать, например, как атрибут класса исключения, куда можно записать несколько сообщений, описывающих возникшую ошибочную ситуацию, либо включить подробное описание шагов процесса, предшествующего ошибке. При обработке исключения эти сообщения можно включить в контейнер другого класса исключения, если обработка ошибки будет продолжена на более высоком уровне по стеку вызова, или при окончательной обработке ошибки вывести эти сообщения на экран или добавить в лог.

CLASS zcx_random_error DEFINITION
  PUBLIC
  INHERITING FROM cx_static_check
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.

    INTERFACES if_t100_dyn_msg .
    INTERFACES if_t100_message .

    METHODS constructor
      IMPORTING
        textid        LIKE if_t100_message=>t100key OPTIONAL
        previous      LIKE previous OPTIONAL
        msg_container TYPE REF TO if_reca_message_list OPTIONAL.
    METHODS get_msg_container
      RETURNING
        VALUE(ro_msg_container) TYPE REF TO if_reca_message_list .

  PRIVATE SECTION.

    DATA go_msg_container TYPE REF TO if_reca_message_list .
ENDCLASS.

CLASS zcx_random_error 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.

    IF msg_container IS BOUND.
      go_msg_container = msg_container.
    ELSE.
      go_msg_container = cf_reca_message_list=>create( ).
    ENDIF.
  ENDMETHOD.

  METHOD get_msg_container.
    ro_msg_container = go_msg_container.
  ENDMETHOD.
ENDCLASS.

****************************************

TRY.
*    some code

    lo_message_list = cf_reca_message_list=>create( ).

*    fill message container in between

    RAISE EXCEPTION TYPE zcx_random_error
      EXPORTING
        msg_container = lo_message_list.

*    some other code

  CATCH zcx_random_error INTO DATA(lo_error).
*    add error messages to log
    lo_main_log->add_from_instance( lo_error->get_msg_container( ) ).
    lo_main_log->store( abap_false ).

*    show messages as popup
    CALL FUNCTION 'RECA_GUI_MSGLIST_POPUP'
      EXPORTING
        io_msglist = lo_error->get_msg_container( ).
ENDTRY.

Также работая в рамках программы или функционального модуля можно создать глобальный класс логгера, используя этот контейнер, для упрощения частого обращения к объекту для записи логов. Также можно построить вокруг контейнера класс-обертку, который будет инициализироваться с контейнером в статическом атрибуте где-то в начале программы и служить той же цели — упростить логирование, минимизировав количество boilerplate кода.

Стоит учесть, что в классе не реализованы некоторые тонкости работы с BAL, так что он не будет 100% заменой. Однако он с легкостью покрывает 99% повседневных задач по работе с сообщениями. Несмотря на то, что этот контейнер имеет довольно топорный интерфейс взаимодействия и то, что в нем смешаны несколько ответственностей — хранение сообщений, их обработка и логирование, он покрывает большинство задач, связанных с передачей сообщений внутри системы и всевозможном взаимодействии с ними.

##OData

Широкое применение концепция контейнера сообщений получила в рамках OData Gateway. SAP в рамках OData API предоставляет контейнер /IWBEP/IF_MESSAGE_CONTAINER, который используется для передачи сообщений через OData-канал клиенту OData-сервиса. Подробную информацию можно почитать в справке по компоненту SAP_GWFND, а я приведу краткий обзору функциональности интерфейса и варианты работы с ним.
Интерфейс имплементирует класс /iwbep/cl_mgw_msg_container, в котором также есть статический factory-метод get_mgw_msg_container, через который возможно создать новый контейнер.

DATA:
  lo_msg_container  TYPE REF TO /iwbep/if_message_container.

lo_msg_container = /iwbep/cl_mgw_msg_container=>get_mgw_msg_container( ).

Этот контейнер используется в различных классах OData Gateway, в частности в качестве атрибута в базовых классах исключений /iwbep/cx_mgw_busi_exception и /iwbep/cx_mgw_tech_exception. Эти классы используются для возврата информации об ошибках для их последующего отображения на клиентской стороне. Я не буду подробно останавливаться на этих классах, скажу лишь, что от них удобно наследовать свои классы исключений при работе в OData сервисе и передавать с ними все сообщения об ошибках.

Теперь немного подробнее про сам контейнер.

Как и предыдущий, этот интерфейс имеет несколько методов для добавления сообщений.

lo_msg_container->add_message(
  iv_msg_type   = 'S'
  iv_msg_id     = 'RDA'
  iv_msg_number = 024
  iv_msg_v1     = 'test'
).

*message list from bapi
lo_msg_container->add_messages_from_bapi(
  it_bapi_messages = lt_bapi_result
).

*message list from BAL
lo_msg_container->add_messages_from_log(
  it_log_messages = lt_bal_messages
).

*message from another container
lo_msg_container->add_messages_from_container( lo_msg_container2 ).

* exception in CATCH-block 
lo_msg_container->add_message_from_exception( lo_error ).

Так как класс заточен на работу с OData, его методы содержат параметры, позволяющие задавать различные атрибуты ответа на запрос. Например, указывать, будет ли сообщение показываться в заголовке списка сообщений, или указывать название поля/компонента, спровоцировавшего ошибку.

Обратите внимание, что метод работает только для исключений, унаследованных от /iwbep/cx_mgw_base_exception. Остальные исключения можно обработать следующим образом — после поимки исключения выбросить новое исключение, унаследованное от /iwbep/cx_mgw_base_exception, передав текущее ему в качестве параметра, чтобы выше по стеку вызова уже работать с исключениями этого фреймворка. Сообщение из исходного исключения добавится в список ошибок при обработке исключения в самом фреймворке.

TRY.

    RAISE EXCEPTION TYPE zcx_random_error.
    
  CATCH cx_root INTO DATA(lo_some_error).
    RAISE EXCEPTION TYPE /iwbep/cx_mgw_tech_exception
      EXPORTING
        previous = lo_some_error.
ENDTRY.

Также в данном контейнере есть возможность добавлять сообщение из свободной текстовой переменной.

lo_msg_container->add_message_text_only(
  iv_msg_type = 'E'
  iv_msg_text = 'Some unexpected error!'
).

Возможно данный подход вполне оправдывает себя при отправке сообщений о технических ошибках через OData канал, но для логических (бизнес) ошибок всегда лучше использовать стандартные тексты, которые могут быть переведены на разные языки и легко найдены в коде при необходимости.

Как и предыдущий, этот контейнер обладает аналитическим функционалом.

IF lo_msg_container->get_worst_message_type( ) = 'E'.
*  error processing
ELSEIF lo_msg_container->get_worst_message_type( ) = 'W'.
*  not so bad
ELSE.
*  perfect!
ENDIF.

Также есть возможность получать сообщения в виде таблицы типа /iwbep/t_message_container.

Добавление сообщений при выбрасывании исключения может выглядеть следующим образом

lo_msg_container->add_message(
  iv_msg_type   = 'S'
  iv_msg_id     = 'RDA'
  iv_msg_number = 123
).

RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception
  EXPORTING
    message_container = lo_msg_container
    http_status_code  = /iwbep/cx_mgw_busi_exception=>gcs_http_status_codes-not_found.

Контейнер не содержит функционала по работе с логом, но в данном случае это и не предполагается, для этого есть специализированные решения, вроде предыдущего контейнера.

#BOPF

Фреймворк бизнес-объектов имеет свой контейнер сообщений, адаптированный под работу с древовидной структурой модели бизнес-объектов и особенностей их функционала.
Основным контейнером сообщений является /BOBF/IF_FRW_MESSAGE. Как и предыдущие рассмотренные примеры, контейнер создается через factory-метод соответствующего класса.

DATA:
  lo_msg_container TYPE REF TO /bobf/if_frw_message.

lo_msg_container = /bobf/cl_frw_message_factory=>create_container( ).

Метод может возвращать объекты разных классов в зависимости от контекста Transaction Manager’а, но для пользователя контейнера эта разница скрыта за интерфейсом.

Контейнер имеет возможность добавлять стандартные сообщения и сообщения из других контейнеров или из классов исключений.

lo_msg_container->add( lo_msg_container2 ).

lo_msg_container->add_message(
  is_msg = VALUE #(
    msgty = 'S'
    msgid = 'RDA'
    msgno = 024
    msgv1 = 'test'
  )
).

lo_msg_container->add_exception( lo_error ).

При добавлении сообщения можно указать специфичные для BOPF параметры — место возникновения сообщения: ключ ноды БО, ключ конкретной инстанции этой ноды, атрибут этой ноды, который содержит ошибочные данные.

Однако основной функционал этого контейнера реализован в рамках другого подхода. В BOPF используются объектно-ориентированные сообщения. В самом контейнере есть два метода по добавлению объектно-ориентированных сообщений — простое добавление сообщения и добавления сообщения с явным указанием места возникновения сообщения (location). Намного интереснее поговорить про сами классы сообщений, но об этом чуть позже.

Как и остальные контейнеры, /BOBF/IF_FRW_MESSAGE имеет методы для получения списка сообщений — возможно либо получить все сообщения таблицей, либо задать определенный фильтр.

DATA:
  lt_message_list      TYPE /bobf/cm_frw=>tt_frw,
  lt_detailed_msg_list TYPE   /bobf/t_frw_message_k.

*get all messages as object list
lo_msg_container->get(
  IMPORTING
    et_message = lt_message_list
).

*get error messages as detailed list
lo_msg_container->get_messages(
  EXPORTING
    iv_severity = /bobf/cm_frw=>co_severity_success
  IMPORTING
    et_message  = lt_detailed_msg_list
).

Также есть возможность проверить наличие сообщений с ошибками. Дополнительно можно указать, включать ли в проверку сообщения из actions или determinations бизнес-объектов. По-умолчанию проверяются все.

IF lo_msg_container->check( ).
*  error processing
ENDIF.

На этом основной функционал контейнера заканчивается. Куда интереснее подробнее рассмотреть концепцию сообщений, реализованную в BOPF.

###Объектно-ориентированные сообщения, используемые в BOPF.

Как уже было сказано выше, бизнес-объекты используют для обработки сообщений объекты, наследующиеся от абстрактного класса /BOBF/CM_FRW. Технически он наследует класс CX_DYNAMIC_CHECK, то есть представляет собой класс исключений. Технически. (Подробнее)

Смысл объектной обертки заключается в переходе от мета-сущности сообщений к объектам, которые удобно использовать в рамках программы (если, конечно, вы не из староверов, сидящих на процедурной парадигме). Такие сообщения довольно удобно создавать и использовать. Например, класс /BOBF/CM_FRW_SYMSG, который имеет интерфейс для добавления сообщения в привычном виде.

DATA(lo_message) = NEW /bobf/cm_frw_symsg(
  textid = VALUE #(
    msgid = 'RDA'
    msgno = 024
    attr1 = 'test'
  )
  severity = 'E'
  )
).

Их удобно добавлять в соответствующий контейнер.

lo_msg_container->add_cm( lo_message ).

lo_msg_container->add_cm(
  NEW /bobf/cm_frw_symsg(
    textid = VALUE #(
      msgid = 'RDA'
      msgno = 015
      attr1 = 'one'
      attr2 = 'two'
    )
    severity = 'S'
  )
).

MESSAGE e024(rda) WITH 'example' INTO DATA(lv_dummy).
lo_msg_container->add_cm(
  NEW /bobf/cm_frw_symsg(
    textid = VALUE #(
      msgid = sy-msgid
      msgno = sy-msgno
      attr1 = sy-msgv1
    )
    severity = sy-msgty
  )
).

Можно добавлять текст сообщений из строковой переменной (хоть я и считаю это и не очень хорошей практикой).

lo_msg_container->add_cm(
  NEW /bobf/cm_frw_symsg(
    message_text = 'some custom text'
  )
).

Также сообщения можно использовать как и обычные классы исключений, а при обработке на более высоком уровне добавить в контейнер. Особенно это удобно для того, чтобы обернуть сообщения от вызовов ФМ, используя соответствующий синтаксис 7.5 (не забудьте про интерфейс IF_T100_DYN_MSG).

TRY.

*    some coding

    RAISE EXCEPTION TYPE zcm_hello
      MESSAGE
      ID sy-msgid
      TYPE sy-msgty
      NUMBER sy-msgno
      WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

*    more coding

    RAISE EXCEPTION TYPE zcm_hello
      EXPORTING
        textid   = zcm_hello=>some_error
        severity = zcm_hello=>co_severity_error.

*    some coding after all

  CATCH /bobf/cm_frw INTO DATA(lo_message).
    lo_msg_container->add_cm( lo_message ).

  CATCH cx_root INTO DATA(lo_error).
    MESSAGE lo_error TYPE 'X'.

ENDTRY.

Так как эти сообщения имплементируют интерфейс IF_MESSAGE, их можно использовать для отображения на экране при помощи оператора MESSAGE (хотя, если вы работаете в рамках BOPF, скорее всего интерфейс реализован на WebDynpro или Fiori, нежели на SAPGUI).

При создании объекта сообщения можно указать дополнительные параметры — как уже известное нам место возникновения сообщения в BOPF, так и другие — SEVERITY — тип сообщения, SYMPTOM — описывает причину возникновения ошибки, LIFETIME — описывает категорию сообщения (временные или постоянные: первые просто возвращаются пользователю и забываются, вторые сохраняются вместе с моделью (релевангны только для временных (draft) БО и будут появляться на последующих шагах обработки, пока проблема не будет устранена).

lo_msg_container->add_cm(
  NEW /bobf/cm_frw_symsg(
    textid   = ls_textid
    severity = /bobf/cm_frw=>co_severity_warning
    symptom  = /bobf/if_frw_message_symptoms=>co_bo_inconsistency
    lifetime = /bobf/cm_frw=>co_lifetime_transition
  )
).

Несмотря на простоту и явность интерфейса объектных сообщений, он достаточно громоздок. Поэтому для упрощения рутинного кода в модулях, активно использующих BOPF, реализованы утилитарные классы для выполнения повторяющихся действий с контейнерами и сообщениями. Например в TM это /SCMTMS/CL_MSG_HELPER, а в EHS это CL_EHFND_FW_APPL_LOG_HELPER. Наверняка подобные есть и в других модулях, реализованных на бизнес-объектах — SLC, QIM, MOC и т.д. — найдите их самостоятельно. А если вы пришли на проект, где на бизнес-объектах реализована кастомерская логика с нуля (как на ISM-PrIMa в Deutsche Bahn), вы наверняка найдете с любовью написанный до вас Z-хелпер.

Для классов сообщений действует особый нейминг — *cm*, т.е. вы можете называть свои классы z*cm* или y*cm* (или /*/cm*, если вы работаете в вендорском пространстве имен). Семантически они ничем не отличаются от других классов исключений, и так же, как обычные классы исключений, могут иметь список сообщений, который можно редактировать через конструктор в se24 или вручную. Можно, например, добавить все сообщения какого-то модуля в один такой класс, а при создании сообщения передавать уже константу в textid — это сделает код более чистым, а сами сообщения можно будет найти через where-used list (работает только для глобальных классов).

CLASS zcm_hello DEFINITION
  PUBLIC
  INHERITING FROM /bobf/cm_frw
  CREATE PUBLIC .

  PUBLIC SECTION.

    INTERFACES if_t100_dyn_msg .

    CONSTANTS:
      BEGIN OF some_error,
        msgid TYPE symsgid VALUE 'RDA',
        msgno TYPE symsgno VALUE '024',
        attr1 TYPE scx_attrname VALUE '',
        attr2 TYPE scx_attrname VALUE '',
        attr3 TYPE scx_attrname VALUE '',
        attr4 TYPE scx_attrname VALUE '',
      END OF some_error .

    METHODS constructor
      IMPORTING
        !textid                  LIKE if_t100_message=>t100key OPTIONAL
        !previous                LIKE previous OPTIONAL
        !severity                TYPE ty_message_severity OPTIONAL
        !symptom                 TYPE ty_message_symptom OPTIONAL
        !lifetime                TYPE ty_message_lifetime DEFAULT co_lifetime_transition
        !ms_origin_location      TYPE /bobf/s_frw_location OPTIONAL
        !mt_environment_location TYPE /bobf/t_frw_location OPTIONAL
        !mv_act_key              TYPE /bobf/act_key OPTIONAL
        !mv_assoc_key            TYPE /bobf/obm_assoc_key OPTIONAL
        !mv_bopf_location        TYPE /bobf/conf_key OPTIONAL
        !mv_det_key              TYPE /bobf/det_key OPTIONAL
        !mv_query_key            TYPE /bobf/obm_query_key OPTIONAL
        !mv_val_key              TYPE /bobf/val_key OPTIONAL .
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcm_hello IMPLEMENTATION.
  METHOD constructor.
    CALL METHOD super->constructor
      EXPORTING
        previous                = previous
        severity                = severity
        symptom                 = symptom
        lifetime                = lifetime
        ms_origin_location      = ms_origin_location
        mt_environment_location = mt_environment_location
        mv_act_key              = mv_act_key
        mv_assoc_key            = mv_assoc_key
        mv_bopf_location        = mv_bopf_location
        mv_det_key              = mv_det_key
        mv_query_key            = mv_query_key
        mv_val_key              = mv_val_key.
    CLEAR me->textid.
    IF textid IS INITIAL.
      if_t100_message~t100key = if_t100_message=>default_textid.
    ELSE.
      if_t100_message~t100key = textid.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

Сгенерированный класс

Однако, несмотря на красоту описанного подхода, пока что он находит применение только внутри BOPF, в котором в принципе существует “своя атмосфера”. Поэтому для интеграции с другими частями SAP необходимо как-то преобразовать объектные сообщения в сообщения старой школы. Обычно такой функционал уже реализован в классах-хелперах модуля.

Несмотря на некоторые накладные расходы, сама концепция очень элегантна и позволяет работать с сообщениями в удобном формате, сочетающимся с современным стремлением ABAP стать нормальным языком программирования.

##Реализация в разных компонентах

Как мы все знаем, работники SAP никогда не общаются друг с другом, ходят в бар в разное время, а за обмен информацией между проектами можно положить учетку на стол и до конца жизни писать только в Z*. По крайней мере этим можно было бы объяснить такое огромное количество разнообразных реализаций одного и того же, как в различных продуктах этой компании. Каждый модуль, каждый фреймворк и технология зачастую имеют собственные реализации одних и тех же базовых либо более специфических вещей, которые не совместимы друг с другом.

Не обошла стороной эта тенденция и контейнеры сообщений. Свои контейнеры есть у различных модулей и фреймворков. Вот несколько тех, которые я встречал в работе:

  • CL_LOG_PPF — контейнер PPF
  • CL_EHFND_FW_LOGGER — контейнер ENA (объектная обертка над BOPF) в EHS

Есть и другие, вы можете встретить их при работе с разными частями SAP. Но суть будет везде примерно одинакова, разве что адаптирована под контекст выполняемых задач.

##Что же выбрать?

В итоге мы имеем дюжину контейнеров сообщений с различным функционалом. Какой же лучше? Какой использовать в повседневной разработке?

Скорее всего, на этот вопрос нельзя дать однозначного ответа. Каждый хорош по-своему, поэтому используйте тот, который близок к контексту вашей разработки. Если вы разрабатываете OData-сервис, логично будет построить обмен сообщениями в рамках контейнера /IWBEP/IF_MESSAGE_CONTAINER и классов исключений, используемых в фреймворке. Аналогично и для других фреймворков или модулей — BOPF, PPF и т.д. В других случаях я советую использовать IF_RECA_MESSAGE_LIST, как наиболее универсальный. Если же в вашем модуле его нет (например в EWM — нет), поищите какую-то местную реализацию, скорее всего она там есть, если модуль моложе пятнадцати лет. Если и такого нет, воспользуйтесь каким-нибудь готовым Z-решением, благо их есть несколько довольно хороших. В любом случае такая обертка будет гораздо удобнее в работе, чем таскание туда-сюда таблиц вроде BAPIRET.

Стремитесь к чистому объектно-ориентированному коду с минимумом неявных операций, коими являются многие операции с сообщениями, вроде классических исключений. Контейнеры сообщений помогут решить эту задачу элегантным и удобным способом, а также помогут использовать информацию из списка сообщений легким для разработчика путем.

Понравилась статья? Поделить с друзьями:
  • A0b2 ошибка bmw e90
  • A0b1 ошибка bmw e60
  • A0ad ошибка бмв
  • A0aa ошибка bmw e90
  • Aapt error resource drawable