Error message handling in segw for oData services

A classic one – we find ourselfs in a situation where we have to maintain an existing oData service with very poor error handling. Of course, if we’re there from the start, that won’t happen. Somehow it’s always the other developers who screw this up. This blog post comes for the rescue. We will show a way to implement robust message handling in an oData service that makes implementing error messages a joy through some custom abap classes.

Requirements

Exception Class

We’ll keep it brief here. For our approach, we need an exception class. Create one – if you have no idea how check out Create an Exception Class.

Message Class

Here it is, our message class that will make message handling easy. Through the singleton design pattern we make sure, that one instance handles all messages throughout a request. Let’s take a closer look and go through the different methods:

📟 get_instance

as already described we use the singleton pattern. So we always go for lo_messages = zcl_xxx_messages=>get_instance( ) instead of NEW zcl_xxx_messages

📟 add_bapiret1_to_messages

add a bapiret1 message and decide if an exception should be triggered based on the severity of the message via IV_TRIGGER_EXCEPTION.

📟 add_bapiret2_to_messages

add a bapiret2 message and decide if an exception should be triggered based on the severity of the message via IV_TRIGGER_EXCEPTION.

📟 add_bapiret2_t_to_messages

add bapiret2 messages and decide if an exception should be triggered based on the severity of the messages via IV_TRIGGER_EXCEPTION.

📟 get_messages

get all stored messages

📟 clear_all_messages

clear all messages

📟 errors_exist

check all messages for an error.

Source Code

class ZCL_XXX_MESSAGES definition

public

final

create public .

  

public section.

  

class-methods GET_INSTANCE

returning

value(RO_INSTANCE) type ref to ZCL_XXX_MESSAGES .

methods ADD_BAPIRET1_TO_MESSAGES

importing

!IS_RETURN type BAPIRETURN1

!IV_TRIGGER_EXCEPTION type BOOLE_D default ABAP_TRUE

raising

zcx_xxx .

methods ADD_BAPIRET2_TO_MESSAGES

importing

!IS_RETURN type BAPIRET2

!IV_TRIGGER_EXCEPTION type BOOLE_D default ABAP_TRUE

raising

zcx_xxx .

methods GET_MESSAGES

returning

value(RT_MESSAGES) type BAPIRET2_T .

methods ERRORS_EXIST

importing

!IV_TRIGGER_EXCEPTION type BOOLE_D

returning

value(RV_ERRORS_EXIST) type BOOLE_D

raising

zcx_xxx .

methods ADD_BAPIRET2_T_TO_MESSAGES

importing

!IT_RETURN type BAPIRET2_T

!IV_TRIGGER_EXCEPTION type BOOLE_D default ABAP_TRUE

raising

zcx_xxx .

methods CLEAR_ALL_MESSAGES .

PROTECTED SECTION.

PRIVATE SECTION.

  

DATA mt_messages TYPE bapiret2_t .

CLASS-DATA mo_instance TYPE REF TO ZCL_XXX_MESSAGES .

ENDCLASS.

  
  
  

CLASS ZCL_XXX_MESSAGES IMPLEMENTATION.

  
  

* <SIGNATURE>---------------------------------------------------------------------------------------+

* | Instance Public Method ZCL_XXX_MESSAGES->ADD_BAPIRET1_TO_MESSAGES

* +-------------------------------------------------------------------------------------------------+

* | [--->] IS_RETURN TYPE BAPIRETURN1

* | [--->] IV_TRIGGER_EXCEPTION TYPE BOOLE_D (default =ABAP_TRUE)

* | [!CX!] zcx_xxx

* +--------------------------------------------------------------------------------------</SIGNATURE>

METHOD add_bapiret1_to_messages.

  

CHECK is_return IS NOT INITIAL.

  

APPEND INITIAL LINE TO mt_messages ASSIGNING FIELD-SYMBOL(<ls_message>).

<ls_message> = CORRESPONDING #( is_return ).

  

IF ( <ls_message>-type EQ 'E' OR <ls_message>-type EQ 'A' ) AND iv_trigger_exception EQ abap_true.

RAISE EXCEPTION TYPE zcx_xxx.

ENDIF.

  

ENDMETHOD.

  
  

* <SIGNATURE>---------------------------------------------------------------------------------------+

* | Instance Public Method ZCL_XXX_MESSAGES->ADD_BAPIRET2_TO_MESSAGES

* +-------------------------------------------------------------------------------------------------+

* | [--->] IS_RETURN TYPE BAPIRET2

* | [--->] IV_TRIGGER_EXCEPTION TYPE BOOLE_D (default =ABAP_TRUE)

* | [!CX!] zcx_xxx

* +--------------------------------------------------------------------------------------</SIGNATURE>

METHOD add_bapiret2_to_messages.

  

CHECK is_return IS NOT INITIAL.

  

APPEND is_return TO mt_messages.

  

IF ( is_return-type EQ 'E' OR is_return-type EQ 'A' ) AND iv_trigger_exception EQ abap_true.

RAISE EXCEPTION TYPE zcx_xxx.

ENDIF.

  

ENDMETHOD.

  
  

* <SIGNATURE>---------------------------------------------------------------------------------------+

* | Instance Public Method ZCL_XXX_MESSAGES->ADD_BAPIRET2_T_TO_MESSAGES

* +-------------------------------------------------------------------------------------------------+

* | [--->] IT_RETURN TYPE BAPIRET2_T

* | [--->] IV_TRIGGER_EXCEPTION TYPE BOOLE_D (default =ABAP_TRUE)

* | [!CX!] zcx_xxx

* +--------------------------------------------------------------------------------------</SIGNATURE>

METHOD add_bapiret2_t_to_messages.

DATA: ls_return TYPE bapiret2.

  

CHECK it_return IS NOT INITIAL.

  

mt_messages = CORRESPONDING #( BASE ( mt_messages ) it_return ).

  

LOOP AT it_return INTO ls_return.

IF ( ls_return-type EQ 'E' OR ls_return-type EQ 'A' ) AND iv_trigger_exception EQ abap_true.

RAISE EXCEPTION TYPE zcx_xxx.

ENDIF.

ENDLOOP.

  

ENDMETHOD.

  
  

* <SIGNATURE>---------------------------------------------------------------------------------------+

* | Instance Public Method ZCL_XXX_MESSAGES->CLEAR_ALL_MESSAGES

* +-------------------------------------------------------------------------------------------------+

* +--------------------------------------------------------------------------------------</SIGNATURE>

METHOD clear_all_messages.

  

CLEAR mt_messages.

  

ENDMETHOD.

  
  

* <SIGNATURE>---------------------------------------------------------------------------------------+

* | Instance Public Method ZCL_XXX_MESSAGES->ERRORS_EXIST

* +-------------------------------------------------------------------------------------------------+

* | [--->] IV_TRIGGER_EXCEPTION TYPE BOOLE_D

* | [<-()] RV_ERRORS_EXIST TYPE BOOLE_D

* | [!CX!] zcx_xxx

* +--------------------------------------------------------------------------------------</SIGNATURE>

METHOD errors_exist.

  

LOOP AT mt_messages ASSIGNING FIELD-SYMBOL(<ls_message>) WHERE type EQ 'E' OR type EQ 'A'.

rv_errors_exist = abap_true.

IF iv_trigger_exception EQ abap_true.

RAISE EXCEPTION TYPE zcx_xxx.

ENDIF.

ENDLOOP.

  

ENDMETHOD.

  
  

* <SIGNATURE>---------------------------------------------------------------------------------------+

* | Static Public Method ZCL_XXX_MESSAGES=>GET_INSTANCE

* +-------------------------------------------------------------------------------------------------+

* | [<-()] RO_INSTANCE TYPE REF TO ZCL_XXX_MESSAGES

* +--------------------------------------------------------------------------------------</SIGNATURE>

METHOD get_instance.

  

IF mo_instance IS INITIAL.

  

CREATE OBJECT mo_instance.

  

ENDIF.

  

ro_instance = mo_instance.

  

ENDMETHOD.

  
  

* <SIGNATURE>---------------------------------------------------------------------------------------+

* | Instance Public Method ZCL_XXX_MESSAGES->GET_MESSAGES

* +-------------------------------------------------------------------------------------------------+

* | [<-()] RT_MESSAGES TYPE BAPIRET2_T

* +--------------------------------------------------------------------------------------</SIGNATURE>

METHOD get_messages.

  

rt_messages = mt_messages.

  

ENDMETHOD.

ENDCLASS.

How to use the message handling class in your abap code

In the following code snippet there is an example of how to use the approach.

CLASS lcl_test DEFINITION FINAL.
  

PUBLIC SECTION.

CLASS-METHODS get_expanded_entity

IMPORTING

is_entity TYPE zhr_gw_entity_s

EXPORTING

et_return TYPE bapiret2_t

es_entity TYPE zhr_gw_entity_s.

  

CLASS-METHODS execute_business_logic

IMPORTING iv_param TYPE string

RETURNING

VALUE(rs_entity) TYPE zhr_gw_entity_s

RAISING

zcx_xxx.

ENDCLASS.

  

CLASS lcl_test IMPLEMENTATION.

  

METHOD get_expanded_entity.

DATA: lt_messages TYPE REF TO zcl_xxx_messages.

  

lo_messages = zcl_xxx_messages=>get_instance( ).

TRY.

es_entity = execute_business_logic( iv_param = is_entity-param ).

CATCH zcx_xxx.

et_return = lo_messages->get_messages( ).

ENDTRY.

ENDMETHOD.

  

METHOD execute_business_logic.

DATA: lo_messages TYPE REF TO zcl_xxx_messages,

lv_msg TYPE bapi_msg,

ls_return TYPE bapiret2.

  

lo_messages = zcl_xxx_messages=>get_instance( ).

  

"execute business logic here

  

*--- sample for throwing an exception/error message

MESSAGE e001(zxxx) INTO lv_msg.

ls_return = VALUE #( type = sy-msgty id = sy-msgid number = sy-msgno message = lv_msg ).

lo_messages->add_bapiret2_to_messages( is_return = ls_return ).

ENDMETHOD.

  

ENDCLASS.

Leave a Reply

Your email address will not be published. Required fields are marked *