Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
former_member716571
Participant

  • Introduction

  • Scenario

  • Step by step procedure

  • Coding


 Introduction



  • For raising error messages first we have to prepare a message container. Message Container is used to add corresponding success or error messages to the response of the OData service. We use a standard interface /IWBEP/IF_MESSAGE_CONTAINER to add the messages to the OData response.



  • To add a message to the message container, we can use any of these methods in the message container interface apart from these 5 methods other methods also available. In this blog I will be showing these methods only.



  1. ADD_MESSAGE - Adds an error message

  2. ADD_ERROR_DETAIL – Add error detail to the OData Inner Error section.

  3. ADD_MESSAGE_TEXT_ONLY – Adds an Error text without Message Details

  4. ADD_MESSAGE_FROM_BAPI – Adds one message of type BAPIRET2 to the message container

  5. ADD_MESSAGES_FROM_BAPI – Adds messages of type BAPIRET2 to the message container



  • Raising an error message from SAP Odata method is a 3 step process:



  1. Define a message container object

  2. Add message text to message container object

  3. Export message container object in raised exception



  • Let’s start by creating an example to display the messages in the OData service. I will show create_entity as an example for all the methods of message container.


Scenario


We have Employee information Custom table as YEMP_DETAILS containing below fields. By taking these fields we are performing post operation.



Step-by-Step Procedure


#1 Creating Odata service:


Create a OData service with an entity set called “EmpdetailsSet” which retrieves the Employee details available in the table. Here I took this simple example to demonstrate the concept, you may choose a different example as per your need. Code may look like below for create_entity.

 METHOD EMPDETAILSSET_CREATE_ENTITY.

" Read Request Data
CALL METHOD IO_DATA_PROVIDER->READ_ENTRY_DATA
IMPORTING
ES_DATA                 ER_ENTITY.

" Insert Data in table YEMP_DETAILS             
INSERT yemp_details FROM ER_ENTITY.

ENDMETHOD.

#2 Testing Odata service:


Test the OData service in the gateway client, if we don’t validate fields, you will see response like below with HTTP response code as 201.


Fig 1


As you can see in above fig.1 even though all field values are initial it will be saving into database. To avoid this, we have to validate fields.

#3 Adding a messages to OData response using methods


Now our next step is to add the error message to this response. So modify the implementation of ‘EMPDETAILSSET_CREATE_ENTITY’ for adding messages to  the response.

Coding


ADD_MESSAGE:  Using this method we can handle both single and multiple messages to response.

ADD_MESSAGE required message class, id and type of the message. For this we have to create message class in SE91 T-code and have to add messages with message numbers.

The important parameter which should be noted here is IV_ADD_TO_RESPONSE_HEADER, if we set this parameter as ‘ABAP_TRUE’ then the message will be added to the response header parameter “sap-message”, In case of displaying success message we must set that parameter to true because success message will not display in response body. I’m not displaying message in response header rather I was displaying in response body.

Handling Single Message in response:

METHOD EMPDETAILSSET_CREATE_ENTITY.

" Read Request Data
CALL METHOD IO_DATA_PROVIDER->READ_ENTRY_DATA
IMPORTING
ES_DATA = ER_ENTITY.                                                                                                      .
" Instantiate Message Container
DATA : LO_MSG TYPE REF TO /IWBEP/IF_MESSAGE_CONTAINER.                                        CALL METHOD Me->/IWBEP/IF_MGW_CONV_SRV_RUNTIME~GET_MESSAGE_CONTAINER
RECEIVING
RO_MESSAGE_CONTAINER = LO_MSG.

" Validations
IF ER_ENTITY-EMPID IS INITIAL.
CALL METHOD LO_MSG->ADD_MESSAGE
EXPORTING
IV_MSG_TYPE   = /IWBEP/CL_COS_LOGGER=>ERROR " Message Type
IV_MSG_ID     = 'YB_MSG'   " Message Class
IV_MSG_NUMBER = '001'.  " Message Number – Enter EmpId
.
RAISE EXCEPTION TYPE /IWBEP/CX_MGW_BUSI_EXCEPTION
EXPORTING
MESSAGE_CONTAINER = LO_MSG.
ENDIF.

IF ER_ENTITY-NAME IS INITIAL.
CALL METHOD LO_MSG->ADD_MESSAGE
EXPORTING
IV_MSG_TYPE   = /IWBEP/CL_COS_LOGGER=>ERROR
IV_MSG_ID     = 'YB_MSG'
IV_MSG_NUMBER = '002'  " Enter name
.
RAISE EXCEPTION TYPE /IWBEP/CX_MGW_BUSI_EXCEPTION
EXPORTING
MESSAGE_CONTAINER = LO_MSG.
ENDIF.

IF ER_ENTITY-CITY IS INITIAL.
CALL METHOD LO_MSG->ADD_MESSAGE
EXPORTING
IV_MSG_TYPE    = /IWBEP/CL_COS_LOGGER=>ERROR
IV_MSG_ID      = 'YB_MSG'
IV_MSG_NUMBER  = '003'   " Enter City
.
RAISE EXCEPTION TYPE /IWBEP/CX_MGW_BUSI_EXCEPTION
EXPORTING
MESSAGE_CONTAINER = LO_MSG.
ENDIF.

" Insert Data in table YEMP_DETAILS
IF ER_ENTITY IS NOT INITIAL.
INSERT YEMP_DETAILS FROM ER_ENTITY.
ENDIF.

ENDMETHOD.


fig.2


As you can see in fig.2 by using the above code for add message method we are raising exception individually for every if conditions, so if in HTTP request all the three fields are initial but in HTTP response only Empid Message was displaying. So change code as below for displaying multiple messages in response.

Handling Multiple messages in response:

METHOD EMPDETAILSSET_CREATE_ENTITY.

" Read Request Data
CALL METHOD IO_DATA_PROVIDER->READ_ENTRY_DATA
IMPORTING
ES_DATA = ER_ENTITY.

" Instantiate Message Container
DATA : LO_MSG TYPE REF TO /IWBEP/IF_MESSAGE_CONTAINER.

CALL METHOD ME->/IWBEP/IF_MGW_CONV_SRV_RUNTIME~GET_MESSAGE_CONTAINER
RECEIVING
RO_MESSAGE_CONTAINER = LO_MSG.

" Checking Validations
IF ER_ENTITY-EMPID IS INITIAL.
CALL METHOD LO_MSG->ADD_MESSAGE
EXPORTING
IV_MSG_TYPE   = /IWBEP/CL_COS_LOGGER=>ERROR
IV_MSG_ID     = 'YB_MSG'
IV_MSG_NUMBER = '001'   " Enter Id
.
ENDIF.

IF ER_ENTITY-NAME IS INITIAL.
CALL METHOD LO_MSG->ADD_MESSAGE
EXPORTING
IV_MSG_TYPE   = /IWBEP/CL_COS_LOGGER=>ERROR
IV_MSG_ID     = 'YB_MSG'
IV_MSG_NUMBER = '002'.   " Enter name
ENDIF.

IF ER_ENTITY-CITY IS INITIAL.
CALL METHOD LO_MSG->ADD_MESSAGE
EXPORTING
IV_MSG_TYPE    = /IWBEP/CL_COS_LOGGER=>ERROR
IV_MSG_ID      = 'YB_MSG'
IV_MSG_NUMBER  = '003'.   " Enter city                                                                                     ENDIF.

" Raising Exception
RAISE EXCEPTION TYPE /IWBEP/CX_MGW_BUSI_EXCEPTION
EXPORTING
MESSAGE_CONTAINER = LO_MSG.

" Insert Data in table YEMP_DETAILS
IF ER_ENTITY IS NOT INITIAL.
INSERT YEMP_DETAILS FROM ER_ENTITY.
ENDIF.

ENDMETHOD.


fig.3


Here in the fig.3, here we modified code to raising exception only once not individually as above scenario, so if In HTTP request all the three fields are initial and in HTTP response all three error messages are displaying.

ADD_ERROR_DETAIL: Here we have to pass error detail work area of type /IWBEP/IF_MESSAGE_CONTAINER=>TY_S_ERROR_DETAIL. Since it is work area, we cannot pass error details directly to method because we have more than one validations. Instead we have to assign details to a local work area and then we have to pass that work area into that method parameter.

DATA : LS_ERROR TYPE /IWBEP/IF_MESSAGE_CONTAINER=>TY_S_ERROR_DETAIL.

*    " Read Request Data
CALL METHOD IO_DATA_PROVIDER->READ_ENTRY_DATA
IMPORTING
ES_DATA = ER_ENTITY.

" Validations
IF ER_ENTITY-EMPID IS INITIAL.
LS_ERROR-MESSAGE_TEXT = 'Enter Id'.
LS_ERROR-SEVERITY = 'E'.
ENDIF.
*
IF LS_ERROR IS INITIAL AND ER_ENTITY-NAME IS INITIAL.
LS_ERROR-MESSAGE_TEXT = 'Enter Name'.
LS_ERROR-SEVERITY = 'E'.
ENDIF.

" Instantiate Message Container
DATA : LO_MSG TYPE REF TO /IWBEP/IF_MESSAGE_CONTAINER.
CALL METHOD ME->/IWBEP/IF_MGW_CONV_SRV_RUNTIME~GET_MESSAGE_CONTAINER
RECEIVING
RO_MESSAGE_CONTAINER = LO_MSG.

CALL METHOD LO_MSG->ADD_ERROR_DETAIL
EXPORTING
IS_ERROR_DETAIL = LS_ERROR.   " Error detail

" Raising exception
RAISE EXCEPTION TYPE /IWBEP/CX_MGW_BUSI_EXCEPTION
EXPORTING
MESSAGE_CONTAINER = LO_MSG.

"Insert Data in table YEMP_DETAILS
IF ER_ENTITY IS NOT INITIAL.
INSERT YEMP_DETAILS FROM ER_ENTITY.
ENDIF.


fig.4


In fig.4, In HTTP Request both name and city field values are initial but in HTTP Response only error message related to 'name' displayed.

ADD_MESSAGE_TEXT_ONLY:  In this method no need of passing message class, id, type instead we directly have to pass message text and type whether it is Error/ Warning/Success.

METHOD EMPDETAILSSET_CREATE_ENTITY.

" Read Request Data
CALL METHOD IO_DATA_PROVIDER->READ_ENTRY_DATA
IMPORTING
ES_DATA = ER_ENTITY.

" Instantiate the Message Container
DATA : LO_MSG TYPE REF TO /IWBEP/IF_MESSAGE_CONTAINER.
CALL METHOD ME->/IWBEP/IF_MGW_CONV_SRV_RUNTIME~GET_MESSAGE_CONTAINER
RECEIVING
RO_MESSAGE_CONTAINER = LO_MSG.

IF ER_ENTITY-EMPID IS INITIAL.
CALL METHOD LO_MSG->ADD_MESSAGE_TEXT_ONLY
EXPORTING
IV_MSG_TYPE = 'E'   " Message Type - defined by GCS_MESSAGE_TYPE
IV_MSG_TEXT = 'Enter Employee id'.  " Message Text
ENDIF.

IF ER_ENTITY-NAME IS INITIAL.
CALL METHOD LO_MSG->ADD_MESSAGE_TEXT_ONLY
EXPORTING
IV_MSG_TYPE = 'E'   " Message Type - defined by GCS_MESSAGE_TYPE
IV_MSG_TEXT = 'Enter Name'.  " Message Text
ENDIF.

IF ER_ENTITY-CITY IS INITIAL.
CALL METHOD LO_MSG->ADD_MESSAGE_TEXT_ONLY
EXPORTING
IV_MSG_TYPE = 'E'   " Message Type - defined by GCS_MESSAGE_TYPE
IV_MSG_TEXT = 'Enter City'.  " Message Text
ENDIF.

" Raising Exception
IF LO_MSG IS NOT INITIAL.
RAISE EXCEPTION TYPE /IWBEP/CX_MGW_BUSI_EXCEPTION
EXPORTING
MESSAGE_CONTAINER = LO_MSG.
ENDIF.

" Insert Data in table YEMP_DETAILS
IF ER_ENTITY IS NOT INITIAL.
INSERT YEMP_DETAILS FROM ER_ENTITY.
ENDIF.


fig.5


In fig.5, in HTTP request both empid and city are initial and in HTTP response both error messages are handled along with corresponding text and severity.

ADD_MESSAGE_FROM_BAPI: we have to pass BAPI work area and also target id i.e, message class name. since we have to pass work area name to the method first we have to assign BAPI message detail to work area.

DATA: LS_BAPI TYPE BAPIRET2. " Bapi Workarea

" Read Request Data
CALL METHOD IO_DATA_PROVIDER->READ_ENTRY_DATA
IMPORTING
ES_DATA = ER_ENTITY.

IF ER_ENTITY-EMPID IS INITIAL.
LS_BAPI-ID = 'YB_MSG'.
LS_BAPI-NUMBER = '001'.
LS_BAPI-TYPE = 'E'.
ENDIF.

IF LS_BAPI IS INITIAL AND ER_ENTITY-NAME IS INITIAL.
LS_BAPI-ID = 'YB_MSG'.
LS_BAPI-NUMBER = '002'.
LS_BAPI-TYPE = 'E'.
ENDIF.

IF LS_BAPI IS INITIAL AND ER_ENTITY-CITY IS INITIAL.
LS_BAPI-ID = 'YB_MSG'.
LS_BAPI-NUMBER = '003'.
LS_BAPI-TYPE = 'E'.
ENDIF.

IF LS_BAPI IS NOT INITIAL.
" Instantiate Message Container
DATA : LO_MSG TYPE REF TO /IWBEP/IF_MESSAGE_CONTAINER.
CALL METHOD ME->/IWBEP/IF_MGW_CONV_SRV_RUNTIME~GET_MESSAGE_CONTAINER
RECEIVING
RO_MESSAGE_CONTAINER = LO_MSG.   " Message Container Interface
ENDIF.

IF LO_MSG IS BOUND.
CALL METHOD LO_MSG->ADD_MESSAGE_FROM_BAPI
EXPORTING
IS_BAPI_MESSAGE            =  LS_BAPI  " Return Parameter
IV_MESSAGE_TARGET          =  'YB_MSG'  " Target (reference)(e.g.Property ID) of a message
.
" Raising Exception
RAISE EXCEPTION TYPE /IWBEP/CX_MGW_BUSI_EXCEPTION
EXPORTING
TEXTID            = /IWBEP/CX_MGW_BUSI_EXCEPTION=>BUSINESS_ERROR
MESSAGE_CONTAINER = LO_MSG.
ENDIF.

" Insert Data in table YEMP_DETAILS
IF ER_ENTITY IS NOT INITIAL.
INSERT YEMP_DETAILS FROM ER_ENTITY.
ENDIF.


fig.6


In fig.6, in HTTP Request all id, name and city fields are initial but in HTTP Response only one message was displaying along with target name and message.

ADD_MESSAGES_FROM_BAPI: This method will add multiple messages in odata response. For this we have to pass BAPI internal table. Since it is internal table we cannot directly pass messages to method instead we gave to append message details to internal table first then we have to pass that internal table to method.

METHOD EMPDETAILSSET_CREATE_ENTITY.

DATA: LT_BAPI TYPE TABLE OF BAPIRET2.

" Read Request Data
CALL METHOD IO_DATA_PROVIDER->READ_ENTRY_DATA
IMPORTING
ES_DATA = ER_ENTITY.

" Checking Validations
IF ER_ENTITY-EMPID IS INITIAL.
APPEND VALUE #( ID = 'YB_MSG' NUMBER = '001' TYPE = 'E' ) TO LT_BAPI.      ENDIF.

IF ER_ENTITY-NAME IS INITIAL.
APPEND VALUE #( ID = 'YB_MSG' NUMBER = '002' TYPE = 'E' ) TO LT_BAPI.
ENDIF.

IF ER_ENTITY-CITY IS INITIAL.
APPEND VALUE #( ID = 'YB_MSG' NUMBER = '003' TYPE = 'E' ) TO LT_BAPI.      ENDIF.

IF LT_BAPI IS NOT INITIAL.

" Instantiate Message Container  DATA : LO_MSG TYPE REF TO /IWBEP/IF_MESSAGE_CONTAINER.
CALL METHOD ME->/IWBEP/IF_MGW_CONV_SRV_RUNTIME~GET_MESSAGE_CONTAINER
RECEIVING
RO_MESSAGE_CONTAINER = LO_MSG.   " Message Container Interface
ENDIF.

IF LO_MSG IS BOUND.
CALL METHOD LO_MSG->ADD_MESSAGES_FROM_BAPI
EXPORTING
IT_BAPI_MESSAGES = LT_BAPI.   " Return parameter table

" Raising Exception
RAISE EXCEPTION TYPE /IWBEP/CX_MGW_BUSI_EXCEPTION
EXPORTING
TEXTID        = /IWBEP/CX_MGW_BUSI_EXCEPTION=>BUSINESS_ERROR
MESSAGE_CONTAINER = LO_MSG.
ENDIF.

" Insert Data in table YEMP_DETAILS
IF ER_ENTITY IS NOT INITIAL.
INSERT YEMP_DETAILS FROM ER_ENTITY.
ENDIF.

ENDMETHOD.


fig.7


Here in the fig.7, In HTTP request all the three fields are initial and in HTTP response all three error messages are displaying along with raised exception.

Conclusion:  Based on requirement we can choose any of the methods available to perform error handling in OData.
5 Comments