Skip to Content
Author's profile photo Volker Drees

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

Hello again.
In the first part (1) we have created a service that consists of two entities (Sales Order and Sales Order Line Item) and two related entity-sets. The runtime artifacts have been generated and the OData service has been registered and activated.
In this part (2) we will map both entity-sets to the related data providers – in our case the 2 EPM BAPIs.
When it comes to data provider mapping / implementation of OData services you usually start with the Query method as this is a typical entry point when consuming a service. In our case we will first enable the query: “provide me all Sales Orders that exist”. In a real business case you would probably make some filtering mandatory to not overload the backend system. But let’s keep it simple for the time being… 

1. As mentioned we will start with the Query method for the SalesOrderCollection entity-set. Expand the node Service Implementation ->  SalesOrderCollection and right-click GetEntitySet (Query) and select Map to Data Source:

/wp-content/uploads/2012/10/pic26_150400.png
2. In the map to data source window, enter the following values and choose Enter:
Target System Local
Data Source Type Remote Function Call
Data Source Name BAPI_EPM_SO_GET_LIST
/wp-content/uploads/2012/10/pic27_150407.png
3. The mapping has already done because the data model has been built based on the same RFC interface. For each property, set the Mapping Direction to Output. Choose Enter:
/wp-content/uploads/2012/10/pic28_150408.png
Now we can move on and do the mapping for the Read operation (GetEntity) of the SalesOrderCollection.
1. Right-click GetEntity (Read) and select Map to Data Source:
/wp-content/uploads/2012/10/pic31_150409.png
2. In the Map to Data Source dialog box, enter the following values and choose Enter:
Target System Local
Data Source Type Remote Function Call
Data Source Name BAPI_EPM_SO_GET_DETAIL
/wp-content/uploads/2012/10/pic32_150410.png
3. This time there are no default mapping settings because the data model has been defined based on a different RFC module.
Expand the HEADERDATA node from the tree on the right-hand side:
/wp-content/uploads/2012/10/pic33_150411.png
4. Drag&drop the following fields from the right-hand tree to the Data Source Parameter column of the grid in the middle of the screen:
RFC Field (right –hand side) Entity Property
SO_ID SoId
NOTE Note
BUYER_ID BuyerId
BUYER_NAME BuyerName
CURRENCY_CODE CurrencyCode
GROSS_AMOUNT GrossAmount
NET_AMOUNT NetAmount
TAX_AMOUNT TaxAmount
/wp-content/uploads/2012/10/pic34_150412.png

In any Read Operation we also need to provide the primary key of the underlying entity as an input parameter. For this we have to manually add a new line to the mapping screen.

1. Choose the Append Row pushbutton:

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

2. On the new line press F4 to select the entity set property. Double-click SoId to select the entry:

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

3. Expand the SO_ID node from the tree on the right-hand side:

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

4. Drag&Drop the RFC field SO_ID (from node SO_ID) to the newly-created line:

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

5. This performs the mapping on the input parameter (Sales Order ID to fetch the Sales Order details):
/wp-content/uploads/2012/10/pic39_150417.png

Now we can move on with mapping the Query operation for the Sales Order Item entity-set

1. Expand the node Service Implementation -> SalesOrderItemCollection and right-click GetEntitySet (Query) and select Map to Data Source:

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

2. In the Map to Data Source dialog box, enter the following values and choose Enter:

Target System Local
Data Source Type Remote Function Call
Data Source Name BAPI_EPM_SO_GET_DETAIL

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

3. There is again no default mapping because the data model has been built based on a different RFC module. Expand the ITEMDATA node from the tree on the right-hand side:

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

4. Drag&drop the following fields from the right-hand tree to the Data Source Parameter column of the grid in the middle of the screen:

RFC Field (right –hand side) Entity Property
SO_ID SoId
SO_ITEM_POS SoItemPos
PRODUCT_ID ProductId
NOTE Note
CURRENCY_CODE CurrencyCode
GROSS_AMOUNT GrossAmount
NET_AMOUNT NetAmount
TAX_AMOUNT TaxAmount
QUANTITY Quantity
QUANTITY_UNIT QuantityUnit

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

5. In the Direction Column set all fields to Output. Choose Enter:

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

6. Choose Append Row button:

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

7. From the input help, select SoId for the new line:

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

8. Expand the SO_ID node from the right-hand tree:

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

9. Drag&drop the RFC field SO_ID (from node SO_ID) to the newly created line:

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

Now we are done with the data provider mapping (at least for the Query and Read operations we need). Now we can re-generate the runtime artifacts and run our OData service.

1. Choose the Generate pushbutton:

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

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

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

3. Start the Gateway Client (Transaction /IWFND/GW_CLIENT) in a separate window to run the service. Provide the following URI to get the Sales Order Collection. This executes the query method of the Sales Order entity-set: 
/sap/opu/odata/sap/ZGW100_XX_SO_SRV/SalesOrderCollection

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

4. Choose any sales order entry and use the URI to navigate to the sales order detail, for example:
/sap/opu/odata/sap/ZGW100_XX_SO_SRV/SalesOrderCollection(‘0500000001’)

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

5. Get the related sales order line items via the following URL:
/sap/opu/odata/sap/ZGW100_XX_SO_SRV/SalesOrderItemCollection/?$filter=SoId eq ‘0500000001’

 

/wp-content/uploads/2012/10/pic57_150432.png
To navigate from the Sales Order entity to the related line items (Entity-Set), you need to construct the URI yourself. In the next part (3) you will see how to define an association and a navigation property between the two Entities.

Assigned Tags

      31 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      hi,

      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 Former Member
      Former Member

      Hi Matteo,

      Check with connection of NW & ECC (Back end) system connected properly or not.

      Once you cross check with BASIS team if possible.

      Author's profile photo kyo choi
      kyo choi

      Check the ST22, most likely you ran into memory space issue since you are trying to list all the records.

      Try following URI instead,

      /sap/opu/odata/sap/ZEPM_BAPI_SRV/SalesOrderItemCollection/?$filter=SoId eq '0500000000'

      Author's profile photo ARSHAD SHAIKH
      ARSHAD SHAIKH

      Hi Volker,

      I followed your blog. i am not getting error but,

      /sap/ZSALES_ORDER_SRV/SalesOrderSet

      In VBAK i have many Sales Orders but it show only first 2 and without any other deails like

      Note,Buyer Id ,Buyer Name all.

      Table entries.

      VBAK.PNG

      Nodata.PNG

      If I pass correct Sales order id /sap/ZSALES_ORDER_SRV/SalesOrderSet('0000004975')

      I am getting this error

      InvalidSalesOrder.PNG

      Can you help me out in resolving the problem.

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

      Hello Arshad,

      as mentioned in the first part the BAPIs used are accessing the EPM demo content. They are not accessing the SD tables (like VBAK).

      Instead you find the sample sales orders of EPM in table SNWD_SO.

      Hope this helps.

      Best Regards,

      Volker

      Author's profile photo ARSHAD SHAIKH
      ARSHAD SHAIKH

      Thanks Volker,

      can you suggest me how to access the data from standard tables (like VBAK),

      I have to create complete service for Sales Order and Purchase order,

      Best Regards,

      Arshad Shaikh

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

      Hello Arshad,

      I'd propose to access standard tables via the related BAPIs. E.g. for Sales Orders there is the BAPI_SALESORDER_GETLIST function module.

      Best Regards,

      Volker

      Author's profile photo Shakeeluddin Khaja
      Shakeeluddin Khaja

      Very useful info. Thanks Volker

      Author's profile photo Patrick Dean
      Patrick Dean

      Super useful! Thanks for the details! 😎

      Author's profile photo saurabh vakil
      saurabh vakil

      Hi,

      We have followed your first blog Step-by-step guide to build an OData Service based on RFCs – Part 1 and are trying to implement the steps mentioned in this blog. While performing the step


      1. Expand the node Service Implementation -> SalesOrderItemCollection and right-click GetEntitySet (Query) and select Map to Data Source:

      we find that when we right click on GetEntitySet (Query) we see the option Map to Data Source in disabled format.

      Can you please let me know what may be the reason for this?

      Regards,

      Saurabh

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

      Hi Saurabh,

      are you still in Edit mode?  "Map to Data Source" should be disabled only in Display mode.

      Best Regards,

      Volker

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

      Or have you already mapped a data source?  In this case the menu option is also greyed out.

      Regards, Volker

      Author's profile photo Ashok Dhayalaraj
      Ashok Dhayalaraj

      Hi Volker,

      I am using a standard BAPI BAPI_PO_GETITEMSREL to get the Release Items where two of the parameters are input. But when I try to compile the data mapping by having them as input, it says that there is no output defined for the two parameters. I am not understanding this concept. Kindly let me know if I am missing out anything.

      Thanks and Regards,

      Ashok Dhayalaraj

      Author's profile photo Ashok Dhayalaraj
      Ashok Dhayalaraj

      Hi Volker,

      Sorry. I had the input parameters as key fields and so it was expecting that those fields also should have an output.

      Thanks and Regards,

      Ashok Dhayalaraj

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

      Hi Ashok,

      great. Thanks for updating us on how you solved the problem.

      Best Regards, Volker

      Author's profile photo Somnath Paul
      Somnath Paul

      Hello,

      First of thanks for this nice blog. I followed and this is working fine for Header part but when it is for item, then response says, Sales Order ID is initial.

      "Consumer problem: Sales Order Id is initial"

      Whereas I am trying  with following URI:

      /sap/opu/odata/sap/ZGW100_XX_SO_SRV/SalesOrderItemCollection/?$filter=SoId eq '0500000001'

      But item works fine when my request URI is:

      /sap/opu/odata/sap/ZGW100_XX_SO_SRV/SalesOrderItemCollection('0500000001')


      Could anyone help me to understand where problem could be?

      - Thanks , Somnath

      Author's profile photo Somnath Paul
      Somnath Paul

      Hello,

      I was trying and found the issue was in mapping for both read as well Query.

      Means in case of Item, I had to map the SoId against SO_ID as below:

      Query Mapping - Item.png

      Read Mapping - Item.png

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

      Hello Paul,

      in this example we are not mapping the GetEntity (Read) operation for the SalesOrderItemCollection entity set as there is no suitable RFC that can serve this request. So if you map the SalesOrder-ID as input parameter in the GetEntitySet (Query) it should work fine.

      Best Regards,

      Volker

      Author's profile photo FAHAD HAMSA
      FAHAD HAMSA

      Hi Volker,

      You have explained it very nicely. I have never done anything in ABAP, still I was able to understand and execute it by following the steps mentioned.

      I am facing a small issue while implementing this. My questions may be very silly, but please consider them as some queries from a novice ABAP programmer 🙂 .

      When I execute BAPI_EPM_SO_GET_LIST without providing MAX_ROWS from SE37, it is taking very long time to return the result as it is an open query and the system has lots of records. When I executed my oData service, I got the following Connection timeout error.

      Error.jpg

      So, I have added a new property in SalesOrder entity type (MaxRows with type Edm:Int32), and mapped it with import parameter - MAX_ROWS of GET_LIST BAPI. When I tried to pass a constant value for this from mapping ('100'), I am getting error (You can see all the details in the following image. It is not accepting number without apostrophe wrapping).

      Error2.jpg

      So my questions are:

      1. How can I pass a constant value using mapping (in the above example)

      2. If I want to pass MaxRows during this oData url execution (so that the result would become more dynamic in nature), what shall I do?

      3. I tried to add some code in GET_ENTITY method (of DPC_EXT class) for experiment purpose. However, the code is always getting erased when I generate Runtime objects. How can I retain the custom code which I have done there during Runtime Object creation?

      Can you please explain these with more details?

      Thanks

      Fahad

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

      Hi Fahad,

      let me try to answer your questions:

      1.: As the error message says, pass a constant value or an entity set property. If you remove the entity set property it should work.

      2.: For this you can use $top  (e.g. .../SalesOrderSet?$top=100)

      3.: I guess you are editing the DPC base class. The base class will be regenerated every time. If the method name is shown with blue color it points to the base class although you are editing the ext class. You once need to redefine the method (2nd last button) in the ext class (this turns the color of the method name to black).

      Hope this help.

      Best Regards, Volker

      Author's profile photo FAHAD HAMSA
      FAHAD HAMSA

      Hi Mark,

      Thanks for the response.

      I have tried the following url.

      /sap/opu/odata/SAP/ZFAH_GW_EPM_RFM_SRV/SalesOrderSet?$top1

      However, it took almost a minute to execute and presented Connection Timeout error (screen shot below for rference)

      Error.jpg

      I guess the service url executing the BAPI without any filter (please note the BAPI is freezing if I execute it without passing import parameter in SE37) and then tries to apply the filter on the retrieved result.

      Hence I tried to pass the value for MAX_ROWS during service execution. However, I am stuck there as well as it is not accepting the constant value '10' or 10 for the new parameter (throwing the error which I have mentioned before). Also, I am not sure how to pass a user input value for import parameter MAX_ROWS from service url.

      Any suggestion on how to resolve this scenario?

      Thanks,

      Fahad Hamsa

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

      Hi Fahad,

      the correct URI is  ...?$top=1

      In the generated coding the MAX_ROWS parameter is not used. So you need to redefine the generated GET_ENTITYSET method (e.g. copy from the base class) and make sure to set the MAX_ROWS parameter.

      Best Regards,

      Volker

      Author's profile photo Menegazzo Marco
      Menegazzo Marco

      Hi Volker

      Many thanks for your tutorial, it was very helpfull for me.

      I'm facing a strange problem...i followed you step by step but my service is not working:

      Calling getEntity:

      /sap/opu/odata/sap/zfiori_read_orders_srv_02/EtOrdersSet('40502394') it works fine, and in abap side i have the parameter VBELN valorized correctly.

      But when i try to call GetEntitites:

      /sap/opu/odata/sap/zfiori_read_orders_srv_02/EtOrdersSet?$filter=Vbeln eq '40502394', i'm receiving VBELN truncated at the 5th position:

      so, in ABAP side, i0m receiving VBELN = 0000040502.....


      i really don't know where i'm doing wrong...any suggestion?


      Thanks in advance.

      Marco

      Author's profile photo Amit Singh
      Amit Singh

      Hi Volker,

      Thanks for the great tutorial. I appreciate your wonderful work.

      I am facing a problem. I followed all steps but not getting any data from backend.OData Service Error.jpg

      Thanks,

      Amit

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

      Hi Amit,

      it seems that no EPM data exists in your system. Try to run Tx SEPM_DG to generate some.

      Regards, Volker

      Author's profile photo Amit Singh
      Amit Singh

      Thanks Volker,

      I am getting data now.

      Regards,

      Amit

      Author's profile photo Menegazzo Marco
      Menegazzo Marco

      Hi Volker

      using this format i'm passing only one parameter to the service:

      /sap/opu/odata/sap/zfiori_read_orders_srv_02/EtOrdersSet('40502394')


      if i wonna pass more then one parameter, something like vbeln and posnr but not using FIlter, how can i do that?


      Thanks

      Marcp

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

      Hi Marco,

      for that you need to flag more than one property as key when defining the entity type of your entity set. In that case the URI would look like:

      .../Service/EntitySet(KeyProp1='...',KeyProp2='...',KeyProp3='...')   and so on.

      Best Regards,

      Volker

      Author's profile photo Ghosal Puskar
      Ghosal Puskar

      Hello Volker,

       

      How could I add the messages generated in the Return Table of "BAPI_EPM_SO_GET_DETAIL" for the same filter passed in the URL. For example I want to see if any message exists for SoId = '400001' and show this message in web service.

       

      Thanks and Best Regards,

      Puskar Ghosal

      Author's profile photo Phani Rajasekhar
      Phani Rajasekhar

      How to connect & expose the SAP ECC data to power BI via netweaver gateway. We have created the project under SEGW however we are not able to find any document about the connectivity to build between the ECC and Power BI. Any inputs would be highly appreciated.

      Author's profile photo kyo choi
      kyo choi

      https://docs.microsoft.com/en-us/power-bi/desktop-connect-odata