Меню

Динамическая ошибка портала sap

We have a RFC which import SQL clause and return result.

FUNCTION EXTRACT_TABLE_DATA.
*"----------------------------------------------------------------------
*"*"import
*"  TABLES
*"      FIELDS STRUCTURE  ZSQL_CLAUSE_ELEMENTS
*"      FROMCLAUSE STRUCTURE  ZSQL_CLAUSE_ELEMENTS
*"      WHERECLAUSE STRUCTURE  ZSQL_CLAUSE_ELEMENTS
*"      DATA STRUCTURE  ZTABLEROWS
*"----------------------------------------------------------------------
  TYPE-POOLS: abap.
  DATA:
        columnName TYPE SO_TEXT,
        fieldDataDescrRef  TYPE REF TO abap_componentdescr,
        numberFields TYPE i,
        fieldDescr TYPE abap_componentdescr,
        fieldname TYPE string,
        fieldDescrTab TYPE abap_component_tab,
        rowStructDescr TYPE REF TO cl_abap_structdescr,
        rowReference TYPE REF TO data,
        returnRowString TYPE string,
        dataFieldString TYPE string,
        dataline LIKE data,
        fromClauseRow TYPE ZSQL_CLAUSE_ELEMENTS,
        fromClauseString TYPE string,
        whereClauseRow TYPE ZSQL_CLAUSE_ELEMENTS,
        whereClauseString TYPE string,
        fieldsRow TYPE ZSQL_CLAUSE_ELEMENTS,
        FNAME(600) VALUE 'myfile'.

  FIELD-SYMBOLS:
          <datarow> TYPE ANY,
          <datafield> TYPE ANY.


* CREATE DataStructure with field names
* Datatypes are read from fieldnames of FIELDS input table
  DESCRIBE TABLE FIELDS LINES numberFields.
  LOOP AT FIELDS INTO fieldsRow.
    fieldname = SY-TABIX.
* names need to be unique and must start with a char
    CONCATENATE 'string' fieldname INTO fieldname.
    CONDENSE fieldname.
    fieldDescr-name = fieldname.
* for dictionary lookup we need to change columnnames from Open SQL
* to dictionary notation
    columnName = fieldsRow-TEXT.
    REPLACE FIRST OCCURRENCE OF SUBSTRING '~' IN columnName WITH '-' RESPECTING CASE.

    fieldDescr-type ?= cl_abap_typedescr=>describe_by_name( columnName ).
    APPEND fieldDescr TO fieldDescrTab.
  ENDLOOP.

  rowStructDescr = cl_abap_structdescr=>create( fieldDescrTab ).

* now we create the actual data structure in memory
  create data rowReference type HANDLE rowStructDescr.
* finally we assign it to the Field-symbol used by the select statement
  ASSIGN rowReference->* TO <datarow>.
* End Create DataStructure

* to simplify calls we concatenate from and whereclause into strings
* this way caller doesn't need to check word wrappings
  fromClauseString = ''.
  LOOP AT FROMCLAUSE INTO fromClauseRow.
    CONCATENATE fromClauseString fromClauseRow-TEXT INTO fromClauseString.
  ENDLOOP.

  whereClauseString = ''.
  LOOP AT WHERECLAUSE INTO whereClauseRow.
    CONCATENATE whereClauseString whereClauseRow-TEXT INTO whereClauseString.
  ENDLOOP.
*IF sy-uname = 'SIENIT01'.
* break-point.
*ENDIF.
* Now start actual select operation
  SELECT (FIELDS) FROM (fromClauseString) INTO @<datarow> WHERE (whereClauseString).
* we read all fields of the current row, cast it to string and
* concatenate it into a dataline with division chars.
    CLEAR: returnRowString.
    DO numberFields TIMES.
      ASSIGN component sy-index of structure <datarow> to <datafield>.
      dataFieldString = <datafield>.
      CONCATENATE returnRowString '^' datafieldstring INTO returnRowString.
    ENDDO.
    dataline = returnRowString.
* finally dataline is added to the return table.
    INSERT dataline INTO TABLE data.
  ENDSELECT.
open DATASET FNAME FOR APPENDING IN TEXT MODE ENCODING DEFAULT.
TRANSFER whereClauseString TO FNAME.
IF SY-SUBRC <> 0.
  WRITE: 'SY-SUBRC:', SY-SUBRC,
       / 'System Message:'.
ENDIF.
CLOSE DATASET FNAME.
ENDFUNCTION.

The four table parameters fields,fromclause,whereclause,data are all table of string.

I use the following parameter set and it runs ok.

fields: ekko~ebeln
fromclause: ekko 
whereclause: 
data:

But I add another row in fields table and it has error.

fields: ekko~ebeln 
        ekko~lifnr
fromclause: ekko
whereclause: 
data:

The error is in SQL clause. I checked the fields ebeln and lifnr are in the ekko table. So what’s the correct way to use dynamic fields in select? Thx.

We have a RFC which import SQL clause and return result.

FUNCTION EXTRACT_TABLE_DATA.
*"----------------------------------------------------------------------
*"*"import
*"  TABLES
*"      FIELDS STRUCTURE  ZSQL_CLAUSE_ELEMENTS
*"      FROMCLAUSE STRUCTURE  ZSQL_CLAUSE_ELEMENTS
*"      WHERECLAUSE STRUCTURE  ZSQL_CLAUSE_ELEMENTS
*"      DATA STRUCTURE  ZTABLEROWS
*"----------------------------------------------------------------------
  TYPE-POOLS: abap.
  DATA:
        columnName TYPE SO_TEXT,
        fieldDataDescrRef  TYPE REF TO abap_componentdescr,
        numberFields TYPE i,
        fieldDescr TYPE abap_componentdescr,
        fieldname TYPE string,
        fieldDescrTab TYPE abap_component_tab,
        rowStructDescr TYPE REF TO cl_abap_structdescr,
        rowReference TYPE REF TO data,
        returnRowString TYPE string,
        dataFieldString TYPE string,
        dataline LIKE data,
        fromClauseRow TYPE ZSQL_CLAUSE_ELEMENTS,
        fromClauseString TYPE string,
        whereClauseRow TYPE ZSQL_CLAUSE_ELEMENTS,
        whereClauseString TYPE string,
        fieldsRow TYPE ZSQL_CLAUSE_ELEMENTS,
        FNAME(600) VALUE 'myfile'.

  FIELD-SYMBOLS:
          <datarow> TYPE ANY,
          <datafield> TYPE ANY.


* CREATE DataStructure with field names
* Datatypes are read from fieldnames of FIELDS input table
  DESCRIBE TABLE FIELDS LINES numberFields.
  LOOP AT FIELDS INTO fieldsRow.
    fieldname = SY-TABIX.
* names need to be unique and must start with a char
    CONCATENATE 'string' fieldname INTO fieldname.
    CONDENSE fieldname.
    fieldDescr-name = fieldname.
* for dictionary lookup we need to change columnnames from Open SQL
* to dictionary notation
    columnName = fieldsRow-TEXT.
    REPLACE FIRST OCCURRENCE OF SUBSTRING '~' IN columnName WITH '-' RESPECTING CASE.

    fieldDescr-type ?= cl_abap_typedescr=>describe_by_name( columnName ).
    APPEND fieldDescr TO fieldDescrTab.
  ENDLOOP.

  rowStructDescr = cl_abap_structdescr=>create( fieldDescrTab ).

* now we create the actual data structure in memory
  create data rowReference type HANDLE rowStructDescr.
* finally we assign it to the Field-symbol used by the select statement
  ASSIGN rowReference->* TO <datarow>.
* End Create DataStructure

* to simplify calls we concatenate from and whereclause into strings
* this way caller doesn't need to check word wrappings
  fromClauseString = ''.
  LOOP AT FROMCLAUSE INTO fromClauseRow.
    CONCATENATE fromClauseString fromClauseRow-TEXT INTO fromClauseString.
  ENDLOOP.

  whereClauseString = ''.
  LOOP AT WHERECLAUSE INTO whereClauseRow.
    CONCATENATE whereClauseString whereClauseRow-TEXT INTO whereClauseString.
  ENDLOOP.
*IF sy-uname = 'SIENIT01'.
* break-point.
*ENDIF.
* Now start actual select operation
  SELECT (FIELDS) FROM (fromClauseString) INTO @<datarow> WHERE (whereClauseString).
* we read all fields of the current row, cast it to string and
* concatenate it into a dataline with division chars.
    CLEAR: returnRowString.
    DO numberFields TIMES.
      ASSIGN component sy-index of structure <datarow> to <datafield>.
      dataFieldString = <datafield>.
      CONCATENATE returnRowString '^' datafieldstring INTO returnRowString.
    ENDDO.
    dataline = returnRowString.
* finally dataline is added to the return table.
    INSERT dataline INTO TABLE data.
  ENDSELECT.
open DATASET FNAME FOR APPENDING IN TEXT MODE ENCODING DEFAULT.
TRANSFER whereClauseString TO FNAME.
IF SY-SUBRC <> 0.
  WRITE: 'SY-SUBRC:', SY-SUBRC,
       / 'System Message:'.
ENDIF.
CLOSE DATASET FNAME.
ENDFUNCTION.

The four table parameters fields,fromclause,whereclause,data are all table of string.

I use the following parameter set and it runs ok.

fields: ekko~ebeln
fromclause: ekko 
whereclause: 
data:

But I add another row in fields table and it has error.

fields: ekko~ebeln 
        ekko~lifnr
fromclause: ekko
whereclause: 
data:

The error is in SQL clause. I checked the fields ebeln and lifnr are in the ekko table. So what’s the correct way to use dynamic fields in select? Thx.

Hello,

We are using the CRM business package 5.0 with SAP Portal 7.0. When we click on Service Processing >Service Orders >

Follow up > Create activity > Bus.Act.(Request) within the Portal, we are getting the following error:

<i>An exception occurred while processing a request for :

iView : pcd:portal_content/com.sap.pct/specialist/com.sap.pct.crm/com.sap.pct.crm.roles/com.sap.pct.crm.crm_user/

com.sap.pct.crm.ckm.home/

com.sap.pct.crm.ckm.work/com.sap.pct.crm.act.activities/relatedItems_dlren_0/

DynamicNavigation/com.sap.pct.crm.quickcreate

Component Name : com.sap.pct.crm.app.quickcreate.QuickCreate

<b>Form elements must have unique ids: link0011 (class com.sapportals.htmlb.Link).</b>

Exception id: 02:06_27/08/07_0216_3551950

See the details for the exception ID in the log file</i>

Can someone help me with the situation? Any help would be appreciated

Greetings,

Gene

Hello,

We are using the CRM business package 5.0 with SAP Portal 7.0. When we click on Service Processing >Service Orders >

Follow up > Create activity > Bus.Act.(Request) within the Portal, we are getting the following error:

<i>An exception occurred while processing a request for :

iView : pcd:portal_content/com.sap.pct/specialist/com.sap.pct.crm/com.sap.pct.crm.roles/com.sap.pct.crm.crm_user/

com.sap.pct.crm.ckm.home/

com.sap.pct.crm.ckm.work/com.sap.pct.crm.act.activities/relatedItems_dlren_0/

DynamicNavigation/com.sap.pct.crm.quickcreate

Component Name : com.sap.pct.crm.app.quickcreate.QuickCreate

<b>Form elements must have unique ids: link0011 (class com.sapportals.htmlb.Link).</b>

Exception id: 02:06_27/08/07_0216_3551950

See the details for the exception ID in the log file</i>

Can someone help me with the situation? Any help would be appreciated

Greetings,

Gene

В статье вы найдете актуальные рекомендации по решению различных ошибок в рамках поддержки системы SAP CRM. Эти рекомендации – сумма личного опыта автора, опыта его коллег и выводов из анализа многих книг/статей по релевантным темам в системе SAP CRM.

Оглавление

Введение

Список основных SAP веб-ресурсов

Общие рекомендации по решению ошибок в системе SAP

Роли полномочий (PFCG-роли)

Полезные документы

Как выполнить транзакцию в SAP GUI при отсутствии полномочий

Как узнать какой авторизационный объект проверяется системой

Бизнес-роли (интерфейс WebUI)

Полезные документы

Алгоритм определения бизнес-роли

Как определяется язык входа по умолчанию при запуске WebUI интерфейса

Как сделать Т-образную конфигурацию ракурса

Ракурс поиска – как добавить новый оператор для критерия поиска

Интерфейс SAP GUI

Как определяется язык входа по умолчанию при запуске SAP GUI интерфейса

SAP Basis

Как открыть/закрыть продуктивную систему для изменений

Как задать правила для введения паролей в SAP системе

Как выгрузить файл с сервера (транзакция AL11)

Пользовательские параметры – транзакция SU3 вкладка «Параметры»

АВАР

Полезные документы

Бесконечный цикл

Как дебажить POP-UP окно в SAP GUI интерфейсе

Как программировать без ключа разработчика

Основные и транзакционные данные

Удаление основных и транзакционных данных

Middleware – механизм обмена данных

Сроки на операции. XML правила

Введение

В статье Вы найдете актуальные рекомендации по решению различных ошибок в рамках поддержки системы SAP CRM. Эти рекомендации – сумма личного опыта автора, опыта его коллег и выводов из анализа многих книг/статей по релевантным темам в системе SAP CRM.

Дополнительно в статье рассказывается о некоторых полезных инструментах «фишках», которые часто помогают в продуктивной системе воспроизвести ошибку и найти пути её решения при наличии очень малого количества прав.

Список основных SAP веб-ресурсов

Ниже приведены ссылки на основные веб-ресурсы, где можно найти информацию по SAP CRM.

Общие ресурсы.

  • https://help.sap.com – «справка» достаточно подробная, часто гораздо лучше курсов, если требуется разобраться в конкретном вопросе.
  • https://blogs.sap.com – здесь можно найти множество статей по самым различным темам.
  • https://wiki.scn.sap.com/wiki/display/CRM/Customer+Relationship+Management – это своего рода Wikipedia для SAP CRM.
  • https://influence.sap.com/sap/ino/#/campaign – ресурс, на котором можно отслеживать новые доработки в области SAP CRM. Идея в том, что SAP запустил программу, где пользователи публикуют пожелания к функциональности системы SAP CRM. Затем идут голосование и реализация тех доработок, которые набрали максимальное число голосов в данном календарном году.
  • http://blog.acorel.nl – блог голландской компании со множеством коротких и полезных статей по SAP CRM.
  • http://www.sapfans.com – довольно популярный форум на английском языке.
  • http://sapuniversity.eu

Ресурсы на русском языке.

  • http://sapboard.ru
  • https://sapland.ru

Специализированные ресурсы – SAP Security.

  • http://www.mariewagener.de/Notes.PDF.Download
  • http://www.sapsecurityexpert.com
  • http://www.sapsecuritypages.com

Общие рекомендации по решению ошибок в системе SAP

ВАЖНО – в первую очередь надо обязательно убедиться, что имеет место именно «ошибка». Тяжелей всего чинить то, что не сломалось. Часто обращения пользователей по поводу «ошибки системы» лечатся чтением инструкции.

Алгоритм работы при обнаружении ошибки в системе SAP:

  • Читаем внимательно сообщение об ошибке – проверяем настройки в системе.
  • Ищем, не обсуждалась ли подобная ошибка на форумах.
  • Ищем ноту по коду ошибки и ключевым словам, описывающим проблему.
  • Если нота не найдена, то заводим сообщение в поддержку SAP, детально описываем ошибку и ждем ответа.
  • Если ждать нет возможности, то можно обратиться в чате к эксперту SAP.
  • Если нет результата или хочется самостоятельно разобраться в причине – запускаем транзакцию под отладчиком и «дебажим», то есть проверяем логику работы программы до наступления ошибки.

Несколько лирических отступлений.

Поиск подобной ошибки на форумах:

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

Нота – SAP Note:

  • Нота – это «заметка», выпускаемая SAP, описывающая проблему и способы ее решения.
  • Помимо текстовой части нота может содержать исправления (корректуры) для программ.
  • Ноты следует искать на веб-ресурсе https://launchpad.support.sap.com
  • Установка ноты осуществляется через транзакцию SNOTE.

Сообщение – SAP Message:

  • Это сообщение в команду поддержки SAP об ошибке в вашей системе.
  • Сообщение следует заводить на том же веб-ресурсе https://launchpad.support.sap.com через пункт меню «Report an Incident» (рис. 1).

Чат – SAP Chat:

  • Это чат с экспертом SAP (плановая сессия или режим реального времени).
  • Важно помнить, что чат в реальном времени может состоятся только, если доступен эксперт SAP по теме вашего обращения на текущий момент.
  • Чат следует инициировать на том же веб-ресурсе https://launchpad.support.sap.com через пункт меню «Expert Chat» (рис. 1).

Рис. 1 – Пункты меню для инициации SAP Message и SAP Chat.

Это было описание общих правил и рекомендаций, которые сокращают время решения типичных ошибок в системе SAP CRM. Теперь давайте перейдём непосредственно к рассмотрению самих ошибок и полезных инструментов.

Роли полномочий (PFCG-роли)

Полезные документы

Роль полномочий – сущность в системе SAP CRM, которая описывает, какие именно действия может осуществлять пользователь в системе.

Книга «SAP CRM AUTHORIZATIONS. Concepts and examples».

  • Автор: Davy Pelssers
  • Год публикации: 2007
  • Источник: http://sapuniversity.eu/wp-content/uploads/2012/11/SAP-AUTHORIZATIONS-V3.pdf

Данная книга доступна по ссылке выше и по личному запросу на электронный адрес автора – davy.pelssers@contactoffice.net. Книга представляет собой полное и детальное описание механизма работы полномочий именно в системе SAP CRM.

Статья «PFCG Roles and Authorization Concept. SAP CRM 7.0».

  • Автор: SAP AG
  • Год публикации: 2009
  • Источник: http://www.sdn.sap.com/irj/scn/index?rid=/library/uuid/00515e75-f1d0-2c10-bebb-e5675f470ee6

В данной статье описывается алгоритм определения бизнес-роли, в частности значение настройки привязки роли-полномочий к бизнес-роли (рис. 2). Идея в том, что данная связь участвует в системе SAP CRM для определения Бизнес-Роли, а не наоборот (см. ниже раздел – Алгоритм определения Бизнес-роли).

Рис. 2 – Настройка привязки роли-полномочий к бизнес-роли.

Далее давайте рассмотрим несколько полезных инструментов «фишек» при работе с полномочиями в системе SAP CRM.

Как выполнить транзакцию в SAP GUI при отсутствии полномочий

Пример сообщения о нехватке полномочий выглядит следующим образом (рис. 3).

Рис. 3 – сообщение о нехватке полномочий.

Метод обхода проверки полномочий.

  • Ставим точку прерываний в функциональном модуле SMTR_KERNEL_CHECK_AUTHORITY – строка 35 (рис. 4).

Рис. 4 – Проверка полномочий на выполнение транзакции.

  • В новом окне включаем системную отладку – транзакция /HS.
  • Затем запускаем нашу транзакцию и проваливаемся в отладчик.
  • Доходим до нашей точки прерывания и перепрыгиваем проверку полномочий.
  • Как результат нужная транзакция будет выполнена.

ВАЖНО – для данного способа необходимо иметь полномочия на отладку с подменой значения.

Альтернативный способ.

В транзакции ST01 включить трассировку – возобновить ошибку – узнать недостающий объект полномочий – запросить себе недостающие полномочия (рис. 5).

Рис. 5 – Меню управления в транзакции ST01.

Как узнать какой авторизационный объект проверяется системой

Эту задачу можно решить с помощью отладчика. При выполнении нашего действия вызываем отладчик и ставим точку прерывания на команде AUTHORITY-CHECK (рис. 6). Затем анализируем все срабатывания точки прерывания пока не будет найдено место, где выполняется проверка нашего объекта авторизации.

Рис. 6 – Установка точки прерывания.

Детально данный метод описан в статье по ссылке https://blogs.sap.com/2014/03/19/how-to-analyze-authorization-issues-in-debug.

Пример использования данного метода.

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

Рис. 7 – Объект полномочий для меню в интерфейсе WebUI.

С помощью вышеописанного метода в момент загрузки бизнес-роли можно определить какой объект полномочий система проверяет для каждого пункта меню в интерфейсе WebUI:

  • Класс – CL_CRM_UI_NAVBAR_SRV
  • Метод – COMP_AUTHORITY_CHECK
  • Объект полномочий – UIU_COMP.

Более детальную информацию можно найти в SAP Note – 2550558 «Work center not visible in Web UI Navigation menu».

На этом мы завершаем рассмотрение раздела «Роли полномочий (PFCG-роли)» и переходим к следующему разделу «Бизнес-роли (интерфейс WebUI)».

Бизнес-роли (интерфейс WebUI)

Полезные документы

Бизнес-роль – сущность, которая определяет веб-интерфейс пользователя, то есть то, что он видит в браузере, когда открывает систему SAP CRM.

Web-интерфейс – это интерфейс системы SAP CRM в браузере.

Обязательные PFCG-роли для запуска WebUI:

  • SAP_CRM_UIU_FRAMEWORK
  • SAP_CRM_UIU_SLS_PROFESSIONAL

Статьи – более детальную информацию по данной теме можно найти по ссылкам ниже:

  • http://sapuniversity.eu/logon-is-not-possible-because-you-have-not-been-assigned-to-a-business-role-please-contact-your-system-administrator/
  • http://sapuniversity.eu/necessary-authorization-in-order-to-use-the-sap-crm-user-parameter-crm_ui_profile/

Далее давайте рассмотрим несколько полезных инструментов «фишек» при работе и настройке бизнес-ролей и интерфейса WebUI.

Алгоритм определения бизнес-роли

Алгоритм состоит из 3-х последовательных шагов:

  • Система проверяет параметр CRM_UI_PROFILE в настройках пользователя (рис. 8).

Рис. 8 – Параметры пользователя.

  • Если ничего не найдено на шаге выше, то система проверяет присвоение бизнес-роли в орг. структуре (рис. 9).

Рис. 9 – Присвоение бизнес-роли на орг. структуре.

  • Если ничего не найдено на шаге выше, то система получает все PFCG-роли, присвоенные пользователю, и определяет присвоены ли они к бизнес-ролям. Найденная бизнес-роль присваивается пользователю (рис. 10).

Рис. 10 – Присвоение роли полномочий на бизнес-роль.

Более детальную информацию о работе данного алгоритма, можно получить в статье ниже http://www.sdn.sap.com/irj/scn/index?rid=/library/uuid/00515e75-f1d0-2c10-bebb-e5675f470ee6

Как определяется язык входа по умолчанию при запуске WebUI интерфейса.

При запуске WebUI интерфейса в диалоговом окне регистрации входа в систему заполнено поле «Язык». Хочется узнать, как система определяет язык входа по умолчанию, и можно ли его изменить (рис. 11).

Рис. 11 – Диалоговое окно регистрации входа в систему.

Алгоритм определения языка состоит из 5-ти последовательных шагов:

  • SICF Service – система проверяет значение в поле «Язык» для вашего сервиса «Запуск интерфейса WebUI» в транзакции SICF (рис. 12).

Рис. 12 – сервис для запуска интерфейса WebUI.

  • WebUI link – если ничего не найдено на шаге выше, то система проверяет содержит ли HTTP запрос параметр SAP-LANGUAGE.

    • http://…/sap/bc/bsp/sap/crm_ui_frame/default.htm?s&sap-language=EN
  • Browser language settings – если ничего не найдено на шаге выше, то система проверяет настройки языка в браузере.

    • Система берет язык, который установлен как основной в настройках браузера.
    • ВАЖНО – язык браузера должен быть установлен/инсталлирован в системе SAP CRM.
    • Для IE браузера путь настройки языка: Tools – Internet Options – Languages.
  • User Settings – если ничего не найдено на шаге выше, то система проверяет настройки пользователя (транзакция SU01 – поле «Язык входа» на карточке пользователя).
  • SAP system default language – если ничего не найдено на шаге выше, то система использует язык, который установлен как язык по умолчанию для системы SAP CRM.

Соответственно, чтобы изменить значение по умолчанию в поле «Язык», достаточно выполнить настройку в одном из пяти пунктов, описанных выше.

Более детальную информацию по данной теме можно найти по ссылкам ниже:

  • http://sapuniversity.eu/how-to-set-a-default-logon-language-in-my-sap-crm-web-ui/
  • https://help.sap.com/viewer/f7dd32926c1c4fcf889a4303d833a22b/7.5.7/en-US/48cae5c9356c3254e10000000a42189b.html

Как сделать Т-образную конфигурацию ракурса

Рассмотрим интересную задачу, где требуется изменить макет (формат) расположения ракурсов в интерфейсе WebUI (рис. 13).

Рис. 13 – Макет (формат) расположения ракурсов.

Для решения данной задачи необходимо выполнить следующие настройки в системе SAP CRM:

  • Настройка в SPRO для ракурса, где регистрируется возможность изменения формата расположения ракурсов.
    • Путь меню настройки: SPROCRM — Фреймворк UI — Определение архитектуры пользовательского интерфейса — Регистрация обзорных страниц для формата подэкрана.
  • Настройка в SPRO для ракурса, где создается новый формат расположения ракурсов.
    • Путь меню настройки: SPROCRM — Фреймворк UI — Определение архитектуры пользовательского интерфейса — Информационный бюллетень — Обработать информационный бюллетень.
  • Настройка конфигурации ракурса, где происходит выбор нового формата (рис. 14).

Рис. 14 – Настройка конфигурации ракурса.

Более детально с данной темой можно ознакомиться в статьях ниже:

  • https://www.acorel.nl/2013/08/overview-pages-in-tile-layout/
  • https://help.sap.com/doc/saphelp_crm70/7.0.0.18/en-US/12/31441d9a204c29baa10ffe8ff4c3c1/content.htm?no_cache=true

Ракурс поиска – как добавить новый оператор для критерия поиска

Другая интересная задача, где показано как без АВАР-разработки можно добавить новый оператор для критерия поиска в интерфейсе WebUI (рис. 15).

Рис. 15 – Доступные операторы в критериях поиска.

Для решения данной задачи необходимо выполнить следующие настройки в системе SAP CRM:

  • В браузере определяем техническое имя для ракурса и атрибута поиска (рис. 16).

Рис. 16 – Техническое имя для ракурса и атрибута поиска.

  • Затем определяем имя объекта динамического запроса (рис. 17).
    • Путь определения: Транзакция BSP_WD_CMPWB – компонент – ракурс – контекст – узел контекста – напр. BuilHeaderAdvancedSearch.

Рис. 17 – Имя объекта динамического запроса.

  • Затем выполняем настройку в SPRO, где задаём доступные операторы для критерия поиска (рис. 18).
    • Путь меню настройки: SPROCRM — CRM: компоненты, общие для всех приложений — Родовой уровень взаимодействия / уровень объекта — Настройки для компонентов — Определить операторов для динамических запросов.

Рис. 18 – Настройка операторов для критерия поиска.

На этом мы завершаем рассмотрение раздела «Бизнес-роли (интерфейс WebUI)» и переходим к разделу «Интерфейс SAP GUI», где мы рассмотрим одну небольшую задачу.

Интерфейс SAP GUI

Как определяется язык входа по умолчанию при запуске SAP GUI интерфейса

При запуске диалогового окна регистрации входа в SAP GUI (рис. 19) мы хотим, чтобы язык входа уже был заполнен значением, которое нам необходимо, чтобы избегать ручного

Если хотите прочитать статью полностью и оставить свои комментарии присоединяйтесь к sapland

Зарегистрироваться

У вас уже есть учетная запись?

Войти

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

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Дискорд ошибка при запуске приложения 0xc000003e
  • Динамическая ошибка переходного процесса