Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member

Introduction

The RFC/BOR Generator allows to generate OData services based on existing RFC function modules or BOR-Interfaces without writing a single line of code. The problem with using the RFC/BOR generator is however that not all RFC function modules are well suited to be used in the generator because of their interface structure and that there is not always a RFC function module available that can be mapped to a method of an OData service. Also some customers prefer to develop RFC function modules rather than performing a code based implementation of an OData service.

As a result it is sometimes necessary to develop an appropriate RFC function module that can be used with the RFC/BOR generator.

This how-to guide therefore describes how to implement an OData service starting by creating RFCs (ABAP functions) that reflect the signature of OData EntityTypes. The RFCs are used to generate an OData service with no manual code within the service provider implementation.

You may use this approach if

  • You don’t want to implement an OData service provider class
  • There is the add-on IW_BEP is not available at the business backend

In this guide the Cross Application Time Sheet will be used as a basis. The service will contain two entities: TimeConfirmation and AttendanceAbsence and a bidirectional association between the entities. To simplify our example, it will support the confirmation of attendances and absences only.

Prerequisites

This document assumes the following:

  • You have access to a NetWeaver 7.0, 7.01, 7,02, 7.31 into which the SAP NetWeaver Gateway ABAP add-ons have been installed. (For detailed installation requirements please see SAP Note 1569624)
  • You have access to an ECC system with the cross application timesheet (CA-TS) installed and configured.
  • You have at least a basic understanding of ABAP development.

It should be understood that an SAP NetWeaver Gateway system is not a new type of SAP system; it is merely a set of ABAP add-ons that can be applied to a SAP NetWeaver 7.00, 7.01, 7.02 and 7.31  (For detailed installation requirements please see SAP Note 1569624).

The add-ons, taken together, form the Gateway system; however, the add-ons can be installed either all together on a single ABAP system or split across two ABAP systems. For a detailed discussion of the different deployment options please see the blog SAP NetWeaver Gateway deployment options in a nutshell from andre.fischer

Although there are several ABAP add-ons making up a Gateway system, for the purposes of this discussion, the important ones are GW_CORE and IW_BEP because these two components determine in which system your development and configuration are performed.

a) GW_CORE and IW_BEP in the same system If GW_CORE and IW_BEP are installed in the same SAP system, then this system will call the ABAP functions that are described in this how-to guide using a business system using an RFC destination. Such an installation scenario is recommended if the backend business system does not contain the software component IW_BEP.

b) GW_CORE and IW_BEP in different systems If GW_CORE and IW_BEP are in different systems, then the system containing GW_CORE will be your Gateway server, and the system containing IW_BEP will be your backend business system. This deployment option requires less remote call between the ABAP system for processing $expand query options for example.

In order to perform the tasks in this tutorial, you will need to log on to whichever ABAP system contains the IW_BEP component with a user id having sufficient authorization to perform ABAP development and has been registered as a developer.

You will also need to log on to the ABAP system containing the GW_CORE add-on in order to perform a single configuration task.

Task 1: Create ABAP DDIC Structures


Step 1: Create the DDIC Structure That Contains the Elements of the EntityType


The first step is to create one structure per OData entity that reflects exactly the structure of the OData entity. Please keep in mind that the ABAP types will be mapped to EDMX types later on.  You will find details on the type mapping at gateway documentation:
Mappings and the ABAP Type Editor - SAP NetWeaver Gateway - SAP Library


Use transaction SE11 or SE80 to create the structure ZGW_TIMECONF_CATS_RECORD.

You may optionally create a structure for the AttendanceAbsenceType entity. However, in this example the structure of table T544T is used to demonstrate projection and renaming of attributes later on.


Step 2: Create a DDIC structure for the OData filters


The OData service generator at SEGW is able to map range tables to OData filters. There a structure for each column that shall support filtering an additional structure is required.
Create a structure ZGW_TIMECONF_SEL_DATE to support filtering on the element workdate.


Create a structure ZGW_TIMECONF_SEL_AWART to support filtering on the element ABS_ATT_TYPE.


Task 2: Create the Functions for the OData Standard Operations and the Entity TimeConfirmation


One of the goals of this how-to is demonstrate the implementation of an OData service without manual code within the Service Provider Implementation. To achieve this, a dedicated function for each supported OData operation is required.  Most of these functions are pretty simple. However, the Get Entity Set requires some thoughts.


Step 1: Create a GetEntitySet Function


There are two types of import parameters that can be mapped with SEGW without manual code.

  • Each column that supports OData filters need to be reflected with a range table. In this exercise at Task 1 there are two examples.
    These range tables are additionally required to support to-many associations. The generated code will use the element that is specified at the referential constrains of an association to map is to a range table.
  • To optimize on performance you may add a max hits parameter as well. The generator at SEGW is able to connect this parameter to the $top and $skip query option.


As a result of such a request the requested entices shall be returned or an error message. This ideally achieved by table parameters of the function

  • In this example the DDIC structure ZGW_TIMECONF_CATS_RECORD is used to define return parameter for the entity set.
  • For potential error messages always use the DDIC structure BAPIRET2.

  1. Create a Function Group with name Z_GW_TIMECONFIRMATION for example.
  2. Create a Function with name Z_GW_TIMECONF_GET_ENTITYSET and choose the Processing Type Remote-Enabled module at the attributes tab.
  3. Add the importing parameter iv_maxhits
  4. Add table parameters for the entityset, the filter and the error messages
  5. Add the following code at the Source code tab

  DATA lv_employee_number TYPE hr_pernr.
  DATA lv_lines TYPE i.
  DATA ls_filter_date LIKE LINE OF filter_date.

  DATA ls_sel_employee  TYPE bapihrselemployee.
  DATA lt_sel_employee LIKE STANDARD TABLE OF ls_sel_employee WITH DEFAULT KEY.
  DATA lt_catsrecords TYPE STANDARD TABLE OF bapicats2 WITH DEFAULT KEY.
  DATA ls_entity LIKE LINE OF entityset.
  FIELD-SYMBOLS: <fs_catsrecords> TYPE bapicats2.

  DATA lv_entity_count TYPE i.


  CALL FUNCTION 'HR_GETEMPLOYEEDATA_FROMUSER'
    EXPORTING
      username                  = sy-uname
    IMPORTING
      employeenumber            = lv_employee_number
      return                    = return
    EXCEPTIONS
      user_not_found            = 1
      countrygrouping_not_found = 2
      infty_not_found           = 3
      OTHERS                    = 4.
  IF sy-subrc <> 0.
MESSAGE e001(ztime_confirmation) WITH sy-uname.
*   Infotype Communication (105) is not maintained for user &1.
  ENDIF.

  ls_sel_employee-option = 'EQ'.
  ls_sel_employee-sign = 'I'.
  ls_sel_employee-high = lv_employee_number.
  ls_sel_employee-low = lv_employee_number.
  APPEND ls_sel_employee TO lt_sel_employee.


  DESCRIBE TABLE filter_date LINES lv_lines.
  READ TABLE filter_date INTO ls_filter_date INDEX 1.
  IF lv_lines NE 1 OR ls_filter_date-option NE 'BT' OR  ls_filter_date-sign NE 'I'.
* error handling for unsuported filter
  ENDIF.
  IF lv_lines = 0.
    ls_filter_date-low  = '18000101'.
    ls_filter_date-high = '99991231'.
  ENDIF.

  CALL FUNCTION 'BAPI_CATIMESHEETRECORD_GETLIST'
    EXPORTING
      fromdate        = ls_filter_date-low
      todate          = ls_filter_date-high
    TABLES
      sel_employee    = lt_sel_employee
      catsrecords_out = lt_catsrecords
      return          = return.

  LOOP AT lt_catsrecords ASSIGNING <fs_catsrecords>
     WHERE abs_att_type IN filter_attabs.
    IF ( lv_entity_count > iv_maxhits AND iv_maxhits NE 0 ).
      EXIT.
    ENDIF.
    IF <fs_catsrecords>-status < '40' AND <fs_catsrecords>-catshours IS NOT INITIAL.
      MOVE-CORRESPONDING <fs_catsrecords> TO ls_entity.
      APPEND ls_entity TO entityset.
      ADD 1 TO lv_entity_count.
    ENDIF.
  ENDLOOP.

ENDFUNCTION.

Step 2: Create a GetEntity Function

The GetEntity function returns a single record specified by the key.  Consequently there is an import parameter for the key, an exporting structure for result and a tables parameter for potential error messages.

To keep the size of this how-to guide in limits, you find the parameters and the source code of the function in table below. Please keep mind that the function needs to be RFC enabled and consequently all parameter “Pass Value” be checked.

Function NameZ_GW_TIMECONF_GET_ENTITY
Import
Parameter NameAssociated Type
IV_KEYCATSCOUNTE
Export
Parameter NameAssociated Type
ENTITYZGW_TIMECONF_CATS_RECORD
Tables
Parameter NameAssociated Type
RETURNBAPIRET2

Source Code:

  DATA ls_sel_employee  TYPE bapihrselemployee.
  DATA lt_sel_employee LIKE STANDARD TABLE OF ls_sel_employee WITH DEFAULT KEY.
  DATA lt_catsrecords TYPE STANDARD TABLE OF bapicats2 WITH DEFAULT KEY.
  FIELD-SYMBOLS: <fs_catsrecords> TYPE bapicats2.

  DATA lv_pernr  TYPE catsdb-pernr.
  DATA lv_workdate TYPE catsdb-workdate.


* there is no function available that reads by primary key
*  1. select form the db directly
*  2. use retrieved workdate and pernr as parameter for the bapi
* So authority check and exits are procesed
  SELECT SINGLE pernr workdate INTO (lv_pernr , lv_workdate)
     FROM catsdb WHERE counter = iv_key.
  IF sy-subrc NE 0.
* error handling
  ENDIF.
  ls_sel_employee-low = lv_pernr.
  ls_sel_employee-option = 'EQ'.
  ls_sel_employee-sign = 'I'.
  APPEND ls_sel_employee TO lt_sel_employee.
  CALL FUNCTION 'BAPI_CATIMESHEETRECORD_GETLIST'
    EXPORTING
      fromdate        = lv_workdate
      todate          = lv_workdate
    TABLES
      sel_employee    = lt_sel_employee
      catsrecords_out = lt_catsrecords
      return          = return.

  LOOP AT lt_catsrecords ASSIGNING <fs_catsrecords> WHERE counter = iv_key.
    MOVE-CORRESPONDING <fs_catsrecords> TO entity.
  ENDLOOP.
  IF entity-counter IS INITIAL.
** error handling
  ENDIF.

Task 3: Create the Functions to read the Attendance and Absence Types

The Attendance and Absence Type entity is used to demonstrate a bidirectional association. On the UI this entity could be used to fill a dropdown box on a UI and to retrieve the texts describing the attendance/absence codes.

Step 1: Create a GetEntitySet Function

In this example there is a filter on the attendance/absence codes is supported.

Function NameZ_GW_TIMECONF_GET_ATT_ABS_SET
Import
Parameter NameAssociated Type
FILTER_ATTABSZGW_TIMECONF_SEL_AWART
ATTENDANCE_ABSENCET554T

Source Code

  DATA lv_employee_number TYPE hr_pernr.
  DATA lt_attendance_absence LIKE attendance_absence[].
  FIELD-SYMBOLS <fs_attabs> LIKE LINE OF attendance_absence[].


  CALL FUNCTION 'HR_GETEMPLOYEEDATA_FROMUSER'
    EXPORTING
      username                  = sy-uname
    IMPORTING
      employeenumber            = lv_employee_number
    EXCEPTIONS
      user_not_found            = 1
      countrygrouping_not_found = 2
      infty_not_found           = 3
      OTHERS                    = 4.
  IF sy-subrc <> 0.
    MESSAGE e001(ztime_confirmation) WITH sy-uname.
*   Infotype Communication (105) is not maintained for user &1.
  ENDIF.

  CALL FUNCTION 'CATS_GET_ABSENCE_ATTENDANCE'
    EXPORTING
      i_pernr            = lv_employee_number
    TABLES
      attendance_absence = lt_attendance_absence.

  LOOP AT lt_attendance_absence ASSIGNING <fs_attabs> WHERE awart IN filter_attabs.
    APPEND <fs_attabs> TO attendance_absence.
  ENDLOOP.

Step 2: Create a GetEntity Function

Function Name
Import
Parameter NameAssociated Type
IV_ATT_ABS_CODEAWARRT
Export
Parameter NameAssociated Type
ATTENDANCE_ABSENCET554T

Source Code

   DATA lt_att_abs LIKE STANDARD TABLE OF attendance_absence.

  CALL FUNCTION 'Z_GW_TIMECONF_GET_ATT_ABS_SET'
    TABLES
      attendance_absence = lt_att_abs.

  READ TABLE lt_att_abs INTO attendance_absence
      WITH KEY awart = iv_att_abs_code.

Task 4: Create a Service Builder Project

In this and the following tasks you use the functions created in the previous tasks to generate the data model and the service.
Use transaction SEGW and create a project (CTRL+F5)

Task 5: Define the Data Model

Step 1: Create EnityType and EntitySet for TimeConfirmation.

At task 1 you created a structure that reflects that contains all attributes of the entity time confirmation. To create the EntityType and EntitySet TimeConfirmation left click on DataModel at the navigation tree and choose import RFC/BOR Interface.

At the first step of the wizard you specify the name of the EnityType. Choose Remote Function Call and use the Function Z_GW_TIMECONF_GET_ENTITY.
Make sure that you have ticked “Create Default Entity Set”. So you don’t need to create the entity set later on.



Choose all properties of ENTITY data source parameter.


Select counter as the key of the Entity.

Step 2: Create EnityType and EntitySet for AttendanceAbsenceType

Repeat the same steps described at Step 1: Create EnityType and EntitySet of TimeConfirmation.  to create the EntityType and EntitySet for Attendance and Absence Types.

  1. Use Context Menu of Data Model to choose import and RFC/BOR interface.
  2. At the first step of the wizard specify AttendanceAbsenceType as EntityTypeName and Z_GW_TIMECONF_GET_ATT_ABS as the function name.
  3. At the second step of the wizard choose AWART and ATEXT of the parameter ATTENDANCE_ABSENCE
  4. Choose a meaningful name for AWART and ATEXT like in the screenshot below.
  5. Check “Is Key” for AWART

Step 3: Create an association

Create the association between the two entities of the Service.
In the navigation tree left-click on Association and choose create to start the association wizard.
At the first wizard step specify the association name, the entities, the cardinalities and the navigation properties as shown in the screen shot below.

At the second wizard step you specify the referential constraints. This constraint is used by generator to resolve the association during runtime.

Task 6: Map Data Model to Data Source

Finally you need to map the EntitySets to the RFCs.

Step 1: Create the Mapping for the EntitySet AttaendanceAbsenceTypeSet

GetEntity

Left click at CreateEntity of AttendanceAbsenceTypeSet in the section Service Implementation. At the context menu choose Map to Data Source



Choose Remote Function Call and the function Z_GW_TIMECONF_GET_ATT_ABS.


First Drag IV_ATT_ABS_CODE from the right tree titled data source parameters to the field data source parameters of the “Mapping of Operation …” table. Then click on propose mapping. The system will add an additional line of the output mapping of AttendanceAbsenceTypeCode.

GetEntitySet

Continue with mapping for GetEntitySet to the function Z_GW_TIMECONF_GET_ATT_ABS_SET.

OData OperationGetEntitySet
Function NameZ_GW_TIMECONF_GET_ATT_ABS_SET
Input
Entity Set PropertyData Source Parameter
AttendanceAbsenceTypeCodeIV_ATT_ABS_CODE
Output
Entity Set PropertyData Source Parameter
AttendanceAbsenceTypeCodeATTENDANCE_ABSENCE\AWART
AttendanceAbsenceTypeTextATTENDANCE_ABSENCE\ATEXT

Step 2: Create the Mapping for the EntitySet AttaendanceAbsenceTypeSet

GetEntitySet

First drag and drop the range tables to the right EntitySet Properties. Then click on propose mapping to get a defaulted mapping. The system will insert two new lines for the output mapping of Workdate and AbsAttType

Click on the data source parameter IV_MAXHITS. Above the tree with data source parameters you find a row of icons. Click on the second icon from the right to map the $top (max hits) query option to the data source parameter IV_MAXHITS.

OData OperationGetEntitySet
Function NameZ_GW_TIMECONF_GET_ENTITYSET
Input
Entity Set PropertyData Source Parameter
WorkdateFILTER_DATE
AbsAttTypeFILTER_ATTABS
Output
Entity Set PropertyData Source Parameter
CounterENTITYSET/COUNTER
WorkdateENTITYSET/WORKDATE
EmployeenumberENTITYSET/EMPLOYEENUMBER
AbsAttTypeENTITYSET/ABS_ATT_TYPE
CatshoursENTITYSET/CATSHOURS
UnitENTITYSET/UNIT

GetEntity

First drag and drop the data source parameter IV_KEY the property Counter. Than choose Propose Mapping.

OData OperationGetEntity
Function NameZ_GW_TIMECONF_GET_ENTITY
Input
Entity Set PropertyData Source Parameter
Counter IV_KEY
Output
Entity Set PropertyData Source Parameter
CounterENTITYSET/COUNTER
WorkdateENTITYSET/WORKDATE
EmployeenumberENTITYSET/EMPLOYEENUMBER
AbsAttTypeENTITYSET/ABS_ATT_TYPE
CatshoursENTITYSET/CATSHOURS
UnitENTITYSET/UNIT

Create

First drag and drop the data source parameter RS_ENTITY_OUT\COUNTER the property Counter. Than choose Propose Mapping.

OData OperationCreate
Function NameZ_GW_TIMECONF_CREATE_ENTITY
Input
Entity Set PropertyData Source Parameter
Counter RS_ENTITY_OUT\COUNTER
Output
Entity Set PropertyData Source Parameter
CounterENTITYSET/COUNTER
WorkdateENTITYSET/WORKDATE
EmployeenumberENTITYSET/EMPLOYEENUMBER
AbsAttTypeENTITYSET/ABS_ATT_TYPE
CatshoursENTITYSET/CATSHOURS
UnitENTITYSET/UNIT

Delete

Propose Mapping will default a correct mapping for this operation.

OData OperationDelete
Function NameZ_GW_TIMECONF_DELETE_ENTITY
Input
Entity Set PropertyData Source Parameter
Counter IV_KEY

Update

Propose Mapping will default a correct mapping for this operation as well.

OData OperationCreate
Function NameZ_GW_TIMECONF_CREATE_ENTITY
Input
Entity Set PropertyData Source Parameter
CounterENTITYSET/COUNTER
WorkdateENTITYSET/WORKDATE
EmployeenumberENTITYSET/EMPLOYEENUMBER
AbsAttTypeENTITYSET/ABS_ATT_TYPE
CatshoursENTITYSET/CATSHOURS
Unit

ENTITYSET/UNIT

Task 7: Generate and Register the Service

To generate the service choose menu Project – Generate Service
Use the section Service Maintenance in the navigation tree to register and maintain your service.
You find further details on service maintenance at the SAP help portal:

Service Maintenance - SAP NetWeaver Gateway - SAP Library

Task 8: Test the Service

To be able to test this example

  • the Cross Application Time Sheet need to be configured at your system
  • your logon user need to be assigned to an employee id (Infotpye 105)
  • a default CATS profile needs to be maintained

You may use transaction /IWFND/GW_CLIENT to test your service.

  • Select all Time Confirmations: <service root>/TimeConfirmationSet
  • Select all Time Confirmations expanded with Attendance Absence Types: <service root>/TimeConfirmationSet?expand=to_AttendanceAbsence
  • Select all AttendacneAbsence Types :<service root>/AttendanceAbsenceSet
  • Select all AttendacneAbsence Types expanded with Time Confirmations:<service root>/AttendanceAbsenceSet?expand=to_TimeConfirmation
11 Comments