Skip to Content
Author's profile photo Volker Drees

Step-by-step guide to build an OData Service based on RFCs – Part 1

Hello fellow OData Service developers out there.

When it comes to OData Service development with SAP NetWeaver Gateway a very typical use case is to build a service that is based on an RFC module (or a set of RFC modules) – e.g. for a List / Detail application. For such a scenario there are dozens of RFC modules (BAPIs) available in the SAP standard that can be used. And of course you can also build and consume your own (Z-)RFC modules if the existing modules don’t satisfy your needs…

For additional information regarding the Service Builder please also see Thomas Meigens Blog: The new SAP NetWeaver Gateway Service Builder: Build new OData Services in 3 Quick Steps

In this Step-by-step Guide we will build an OData Service that consumes two RFC modules from the EPM (Enterprise Procurement Model) demo content. From this EPM demo content we pick two BAPIs that retrieve the list and detail of Sales Orders / Line Items. The data model is pretty simple. We have one entity for the Sales Order header data, and one entity for the Sales Order Line Item.

The two BAPIs that we will use in our service are: BAPI_EPM_SO_GET_LIST and BAPI_EPM_SO_GET_DETAIL

This guide is based on SAP NetWeaver Gateway 2.0 SP5. We will be mainly using the SAP NetWeaver Gateway Service Builder for the service creation. The Service Builder allows us to build our service without writing a single line of code (although you still can do coding – if you want…).

In this first part (1) we will build a Meta Model of the service. In the second part (2) we will perform the service implementation.

So let’s get started.

1. Create a new project ZGW100_XX_SO  (SO stands for Sales Order). XX is just a placeholder for a group number and GW100 indicates the course number – as the screen shots were taken from the GW100 training course material that I have created.

/wp-content/uploads/2012/10/pic1_150680.png

/wp-content/uploads/2012/10/pic2_150681.png

2. Create the first entity by importing an RFC interface. For this right-click on Data Model and choose Import -> RFC/BOR Interface

/wp-content/uploads/2012/10/pic3_150682.png

3. Enter the following values in the wizard and then choose Next:

Entity Type Name SalesOrder
Target System Local
Data Source Type Remote Function Calls
Data Source Name BAPI_EPM_SO_GET_LIST

/wp-content/uploads/2012/10/pic4_150683.png

4. Expand the SOHEADERDATA node and select the following fields:
SO_ID,  NOTE,  BUYER_ID, BUYER_NAME,  CURRENCY_CODE,  GROSS_AMOUNT, NET_AMOUNT,  TAX_AMOUNT  
Note that SOHEADERDATA is not selected. Choose Next.

/wp-content/uploads/2012/10/pic5_150684.png

5. In the first line, SO_ID, select the field Is Key and choose Finish:

/wp-content/uploads/2012/10/pic6_150685.png

6. Create the second entity again by importing an RFC interface. Right-click Data Model and choose Import -> RFC/BOR Interface

/wp-content/uploads/2012/10/pic7_150686.png

7. Enter the following values in the wizard and choose Next:

Entity Type Name SalesOrderItem
Target System Local
Data Source Type Remote Function Calls
Data Source Name BAPI_EPM_SO_GET_LIST

/wp-content/uploads/2012/10/pic8_150687.png

8. Expand the SOITEMDATA node and select the following fields:
SO_ID,  SO_ITEM_POS,  PRODUCT_ID,  NOTE,  CURRENCY_CODE,  GROSS_AMOUNT,  NET_AMOUNT,  TAX_AMOUNT,  QUANTITY,  QUANTITY_UNIT
Note that SOITEMDATA is not selected. Choose Next.

/wp-content/uploads/2012/10/pic9_150688.png

9. In the first and second line, SO_ID,  SO_ITEM_POS, select the field Is Key and choose Finish:

/wp-content/uploads/2012/10/pic10_150689.png

Now our project has 2 entities – one for the Sales Order and one for the Sales Order Line Item. As a next step we create entity-sets out of these entities.

1. Expand the node Data Model and double-click Entity Sets:

/wp-content/uploads/2012/10/pic11_150690.png

2. Click the Create button twice to add two new lines to the table:

/wp-content/uploads/2012/10/pic12_150691.png

3. Enter the following values:

Name  

Entity Type Name

 

SalesOrderCollection SalesOrder
SalesOrderItemCollection SalesOrderItem

4. Choose Save:

/wp-content/uploads/2012/10/pic13_150692.png

Now the basic definition of the Model is done. As a next step we can generate the necessary runtime artifacts.

1. Choose the Generate pushbutton:

/wp-content/uploads/2012/10/pic14_150693.png

2. Leave the default values and choose Enter:

/wp-content/uploads/2012/10/pic15_150694.png

Please note the Technical Service Name ZGW100_XX_SO_SRV is equal to the External Service Name required to consume this service later on.

3. Choose Local Object:

/wp-content/uploads/2012/10/pic16_150695.png

4. Verify that the runtime objects have been generated successfully:

/wp-content/uploads/2012/10/pic17_150696.png

Now we can Register and Activate the Service.

1. Double-click Service Maintenance:

/wp-content/uploads/2012/10/pic18_150697.png

2. Select system ZME and choose the Register button. Please note that the entries listed here depend on the System Alias configuration you have done in the SAP NetWeaver Gateway Implementation Guide (IMG). In a local deployed environment (Backend and Hub components deployed on the same box) you might also find “LOCAL” with the RFC destination “NONE” here.

/wp-content/uploads/2012/10/pic19_150698.png

3. Confirm the warning message displayed in the popup:

/wp-content/uploads/2012/10/pic20_150699.png

4. Press F4 to select the system alias. Select ERP_EMEA from the input help. Please note that you won’t get any popup if there is only 1 System Alias maintained. As mentioned above, depending on the deployment method and IMG configuration you possibly see an alias “LOCAL” instead of the ones shown in the screen shot:

/wp-content/uploads/2012/10/pic21_150700.png

5. Confirm the Select System Alias popup:

/wp-content/uploads/2012/10/pic22_150701.png

6. Leave the default values and enter $tmp as the package and choose Enter:

/wp-content/uploads/2012/10/pic23_150702.png

The External Service Name is defaulted with the Technical Service Name from the Generation Step.

7. Verify that the service has been registered and activated successfully:

/wp-content/uploads/2012/10/pic24_150703.png

Now we can run our service the first time. Please note that we’ve only maintained the basic model data so far. As a consequence we can access the metadata of the service, but not yet any business data (that will come in part 2).

1. Open a new window, start transaction /IWFND/GW_CLIENT.

2. Enter URI:  /sap/opu/odata/sap/ZGW100_XX_SO_SRV/$metadata and choose Execute:

/wp-content/uploads/2012/10/pic25_150704.png

ZGW100_XX_SO_SRV is the External Service Name that was registered before.

So we are done – for the moment. We have created a Service Builder Project with two entities and two entity-sets. We have generated the runtime artifacts and registered and activated our OData service. In part 2 we will map the data provider to bring life into our OData service.

Assigned Tags

      32 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Syambabu Allu
      Syambabu Allu

      Hi Drees,

       

      Nice Blog.

       

      When i am trying to create project through SEGW project is created success but in import menu option i am not getting BAPI/RFC Interface tab.

       

      Ref: Using SP04

       

      Thanks,

      Syam.

      Author's profile photo Volker Drees
      Volker Drees
      Blog Post Author

      Hi Syam,

      that is correct. The mentioned features are available as of GW2.0 SP5.

       

      Best Regards,

      Volker

      Author's profile photo Syambabu Allu
      Syambabu Allu

      Hi Drees,

       

      Thanks for the information.

      Author's profile photo Former Member
      Former Member

      hi, someone can help me?

      I followed step by step your guide, but it does not work, the service when I call SalesOrderCollection or SalesOrderItemCollection gives me an error like this:

      Immagine.JPG

      Author's profile photo Olivia Wang
      Olivia Wang

      From the sample above, it is aimed to show the metadata of the OData service...

      So the URL that needs to be passing is:

      /sap/opu/odata/sap/Z_SERVIZIO_MATTEO_SRV/$metadata

      Author's profile photo Nick Archontis
      Nick Archontis

      Thanks! Very clear and precise.

       

      Nick.

      Author's profile photo Former Member
      Former Member

      Excellent blog, thanks Volker.

      Maybe worth mentioning the EPM Data Generator transaction is sepm_dg for those that are using a fresh system without data yet.

       

      Cheers

      Phillip

      Author's profile photo Akhila M
      Akhila M

      Thanks so much Volker, It is really helpful

      Author's profile photo Arshad Ansary
      Arshad Ansary

      Hi Volker,

       

      Thanks for the blog. This is very helpful for beginners in Gateway.

      I followed your steps and I registered the service using  /iwfnd/maint_service in LOCAL server.

       

      1 While creating data model for Gateway servcice , I am not able to select the individaul fields w/o selecting the SOITEMDATA and SOHEADERDATA nodes.

       

      2 I am not able to test the service in /IWFND/GW_CLIENT it syas some HTTP error. But I copied the URL and paste it in chrome browser . I am able to get the result but the individual fields in Entity is not shown

      GW_metadata.jpg

       

      Regards

      Arshad

      Author's profile photo Volker Drees
      Volker Drees
      Blog Post Author

      Hi Arshad,

      the reason for not marking SOHEADERDATA was to keep the Entity Type name that you defined on the first page of the wizard. The blog was created based on GW 2.0 SP5. Now with SP8 (and SP9 coming soon) the behavior of SEGW has changed a bit. So it's not a problem if the SOITEMDATA or SOHEADERDATA nodes are marked. You just need to make sure that you get the expected Entity Type name in the end.

      Also the Entity-Sets you do not need to add manually anymore. This is done using the "Create Default Entity Set" check-box automatically.

       

      As per the 2nd error it's more tricky to say what is wrong. I learned that you e.g. need to have the certificates generated in STRUSTSSO2. But there might be more steps necessary.

       

      Best Regards,

      Volker

      Author's profile photo Martin Maruskin
      Martin Maruskin

      Hi Volker,

       

      interesting blog! I have a question whether pagination can be done within your example - BAPI BAPI_EPM_SO_GET_LIST. I see that within the code of the BAPI the pagination related parameter (IS_PAGING_OPTIONS) of method QUERY_BY_HEADER are not passed. So I not think it is supported but maybe you found a way for this...

       

      In case you agree with me that no pagination supported by the above mentioned BAPI... Are you aware of any other standard SAP BAPI which supports pagination functionality within the result set?

       

      thanks

      m./

      Author's profile photo Volker Drees
      Volker Drees
      Blog Post Author

      Hello Martin,

      the BAPI BAPI_EPM_SO_GET_LIST unfortunately does not expose the parameter IS_PAGING_OPTIONS. Therefore it is not possbile to use it when calling the BAPI.

       

      In the generated DPC method (...GET_ENTITYSET) the paging is handled out of the box. But this is done in a generic way - after the BAPI has provided the full list. You can adjust the generated coding to fill the MAX_ROWS parameter based on the paging request. That can improve the performance when calling the BAPI.

       

      I'm not aware of any standard BAPI that supports full paging. If you have access to a NW 7.40 system with SAP_GWFND SP8 installed you can check my sample service (

      /sap/opu/odata/IWBEP/GWSAMPLE_BASIC) which implements the paging by performing a direct database access (SELECT).

       

      Best Regards, Volker

      Author's profile photo Martin Maruskin
      Martin Maruskin

      Thanks for clarifying this, much appreciated!

      Author's profile photo Arshad Ansary
      Arshad Ansary

      Hi Volker,

       

      I am in SP10 and I am not able to find your sample service GWSAMPLE_BASIC in /IWFND/MAINT_SERVICE. Can you post the code of pagination handling in select

       

      if we can limit the records at the select itself(instead of at the DPC classes),we can hugely improve the performance.

       

      Moreover how the pagination should work along with sort is also a question. Because ideally sort should happen first and then top skip pagination should happen next.

       

      In our project we are currently getting all records from DB  and then doing sorting and pagination after that which is affecting perfomance

       

      Regards

      Arshad

      Author's profile photo Volker Drees
      Volker Drees
      Blog Post Author

      Hi Arshad,

      I assume you are on 7.40? Have you tried to use "Add Service" to add the GWSAMPLE_BASIC service if it is not yet present in the list of registered services?

       

      As per the pagination in a SELECT statement, you can only use the "up to x rows" statement to reduce the number of items to be read. As a consequence the efficiency is higher if you are browsing the first pages of your entityset.

       

      In my example I first prepare some helper varaibles (all of type i):

       

           lv_top  = io_tech_request_context->get_top( ).

           lv_skip = io_tech_request_context->get_skip( ).

           IF ( lv_top > 0 ).

             lv_maxrows = lv_top + lv_skip.

           ENDIF.

       

      And in the SELECT statement I use the lv_maxrows variable to limit the number of records to be read. sy-dbcnt helps me to skip the records at the beginning (though they still need to be read from the DB). Sorting and filtering takes place along with the SELECT statement.

       

              SELECT

                <...some fields...>

                INTO (<...some fields...>)

                FROM ( <...some joined tables...> )

                UP TO lv_maxrows ROWS

                WHERE (lv_where_clause)

                ORDER BY (lv_orderby_clause).

       

                IF ( sy-dbcnt > lv_skip ).

                  APPEND ls_entity TO et_entityset.

                ENDIF.

              ENDSELECT.

       

      hth

      Best Regards, Volker

      Author's profile photo Former Member
      Former Member

      Thank you for the blog. It was really helpful to get started.

       

      -Archana

      Author's profile photo Former Member
      Former Member

      Hi Volker,

       

      This is an excellent document. Thank You.

       

      During "Service Maintenance", after I select the system, I see all buttons like "Register,Maintain, Error Log and Gateway Client" are disabled(greyed out). What cloud be the reason?

       

      Please help. Is that role assignment issue?

       

      Regards,

      Kavitha

      Author's profile photo Volker Drees
      Volker Drees
      Blog Post Author

      Hi Kavitha,

      the mentioned buttons are typically greyed out if the project has not been generated. In that case no runtime artifacts exist which can be used for e.g. registration.

       

      Can you please try to generate the project and check if the buttons are still disabled?

       

      Best Regards, Volker

      Author's profile photo Former Member
      Former Member

      Done..

       

      Thanks

      Author's profile photo Former Member
      Former Member

      Great Note on OData Services. Thank you so much.

      Author's profile photo Anuj Srivastava
      Anuj Srivastava

      Hello Volker,

       

      I am new to SAP Netweaver Gateway. after following your article i am able to create GW service. The issue i am facing is that coming in java format when I am executing the URI.

      The data type of date field is Edm.DateTime but still date is coming in java format.

      how and where this can be changed?

      Request you to please help.

       

      Thanks

      Anuj

      Author's profile photo Anuj Srivastava
      Anuj Srivastava

      Hello Volker,

       

      I am new to netweaver gateway and after going thru your document, i am able to create a service. Only issue i am facing is that in json format, the date is in strings. We need date format as YYYYMMDD. The date is EDM.datetime but still getting java format for date in output.

      Request you to help me on this issue.

       

      Thanks

      Anuj

      Author's profile photo Volker Drees
      Volker Drees
      Blog Post Author

      Hello Anuj,

      consuming the OData service using $format=json just changes the format of the output - not the content. An Edm.DateTime exposed in json is formated like "\/Date(1449231600000)\/" in case of "2015-12-04T12:20:00". I'm not a java expert but I assume there are functions that allow you to convert the json string back into a date with or without a time.

       

      Best Regards, Volker

      Author's profile photo Anuj Srivastava
      Anuj Srivastava

      Thanks Volker. will contact java person.

       

      Thanks

      Anuj

      Author's profile photo Juan Carlos Bermudez
      Juan Carlos Bermudez

      Hi Volker,

      Seems after the migration to the new blogs your post got messed up.

      If by any change you have a copy of it, could you rebuild it ?

      Or work with the folks at SAP so it can be re-established ?

      Thank you !

      J.C.

      Author's profile photo Former Member
      Former Member

      Hi Volker
      In the basic tutorial of odata there are different options for querying data.

      link to basic tutorial - http://www.odata.org/getting-started/basic-tutorial/#filter

      Are all of these supported in SAP gateway or only a few. For example in transaction /n/IWFND/GW_CLIENT, when i press Add uri option, i the following are NOT there
      $select
      $search
      $filter etc

      Thank you

      Author's profile photo Ramakrishna Prasad Gelli
      Ramakrishna Prasad Gelli

      Mentioned Thomas Blog link is dead..here is the right link incase you are lloking for that blog.

       

      https://blogs.sap.com/2012/09/07/the-new-gateway-service-builder-how-to-build-odata-services-from-sap-business-suite-data-in-3-quick-steps/

      Author's profile photo David Raven
      David Raven

      Hi,

      First thanks for this tutorial.

       

      I am trying to execute the gateway client but I get : Method 'HEADERSET_GET_ENTITY' not implemented in data provider class.

       

      The function created in se37 is quite simple and this is the interface:

      *"*"Local Interface:
      *"  IMPORTING
      *"     VALUE(I_ID) TYPE  CHAR10
      *"     VALUE(I_DETAIL_NO) TYPE  CHAR2
      *"     VALUE(IS_HEADER) TYPE  ZLMS_HEADER_T
      *"  TABLES
      *"      T_FLIGHTS TYPE  ZLMS_FLIGHTS_TY OPTIONAL

       

      Can you please help me with this issue ?

       

      Thanks.

       

      Regards.

      Author's profile photo Neha Mahanty
      Neha Mahanty

      Hi Volker,

      This is a great link for beginners like me .. very informative..

       

      Thanks

      Neha

      Author's profile photo מתן סבטי
      מתן סבטי

      Hello Drees.

      First of all thank you for your awesome blog, it is really detailed and simple to read and understand.

      I have a problem with registering the service maintenance. First of all it is not ZME with client 800, but MG1 with client 1(I figure the problem might hide in that matter), and when I try to click register i get a message 'Could not connect to the selected system'.

      Do you know what the problem is about? thank you very much!

      Author's profile photo Irving Alexis
      Irving Alexis
      Hello everyone, in the first section, step number nine. What criteria are used to assign the keys? When importing my RFC with different values ​​to the exercise, I get mapping errors due to the assignment of keys.
      Thank you so much.
      Author's profile photo Irving Alexis
      Irving Alexis
      Hello everyone, in the first section, step number nine. 
      What criteria are used to assign the keys? 
      When importing my RFC with different values ​​to the exercise, 
      I get mapping errors due to the assignment of keys.
      Thank you so much.