Skip to Content
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.
To report this post you need to login first.

27 Comments

You must be Logged on to comment or reply to a post.

  1. Matteo Somensi

    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

    (0) 
    1. akshath lt

      Hi Matteo,

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

      Once you cross check with BASIS team if possible.

      (0) 
  2. 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.

    (0) 
  3. Volker Drees 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

    (0) 
    1. 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

      (0) 
      1. Volker Drees 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

        (0) 
  4. 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

    (0) 
  5. 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

    (0) 
    1. 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

      (0) 
  6. 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

    (0) 
    1. Volker Drees 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

      (0) 
  7. 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

    (0) 
    1. Volker Drees 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

      (0) 
      1. 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

        (0) 
        1. Volker Drees 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

          (0) 
  8. 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

    (0) 
  9. 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

    (0) 
  10. 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

    (0) 
    1. Volker Drees 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

      (1) 

Leave a Reply