Skip to Content
Author's profile photo Volker Drees

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

Thanks for sticking to this multi-part step-by-step guide.

Looking into this part (3) means that you have successfully completed the first part (1) and the second part (2) and you are now curious to see how our EPM OData Service will be extended with an Association and a Navigation Property. This will allow us to navigate from the Sales Order to the related Sales Order Line Items by using a link instead of manually putting a filter together. Furthermore this also allows us to use the $expand statement to fetch the Sales Order together with all Sales Order Line Items in one http call.

We are still in the Service Builder and enhancing our project that we created in part 1 and extended in part 2.

1. Double-click Associations:

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

2. Choose the Create pushbutton:

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

3. Enter the following values for the Association and choose Enter:

Name SalesOrderSalesOrderItems
Principal Entity* SalesOrder
Principal Entity Cardinality* 1
Dependent Entity* SalesOrderItem
Dependent Entity Cardinality* M

*) This field has an input help

Now we will Create a referential constraint for the association

1. Expand the Associations node and the SalesOrderSalesOrderItems node and double-click Referential Constraints:

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

2. Choose the Create pushbutton:

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

3. Enter the following values and choose Enter:

Principal Key* SoId
Dependent Property* SoId

*) This field has an input help   

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

Now we create an association set for the association

1. Double-click Association Sets:

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

2. Choose the Create pushbutton:

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

3. Enter the values and choose Enter:

Name SalesOrderSalesOrderItems
Association* SalesOrderSalesOrderItems

*) This field has an input help

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

And finally we create a navigation property based on the referential constraint

1. Expand Data Model -> Entity Types -> SalesOrder and double-click Navigation Properties:

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

2. Choose the Create pushbutton:

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

3. Enter the following values and choose Enter:

Name SalesOrderItems
Relationship Name* SalesOrderSalesOrderItems

*) This field has an input help

Now we need to re-generate the runtime objects and we’re then ready to test the service

1. Choose the Generate pushbutton:

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

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

/wp-content/uploads/2012/10/pic72_150613.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 metadata for the service:
/sap/opu/odata/sap/ZGW100_XX_SO_SRV/$metadata
/wp-content/uploads/2012/10/pic73_150618.png

The Sales Order collection now includes a navigation property.

4. When you now select a sales order entry using
/sap/opu/odata/sap/ZGW100_XX_SO_SRV/SalesOrderCollection(‘0500000001’), for example, you can simply add the navigation link /SalesOrderItems to navigate to the line items without having to set a filter yourself:

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

5. And finally you can use $expand to read all sales order items for a given sales order in a single http call.
Simply provide the following URI:
/sap/opu/odata/sap/ZGW100_XX_SO_SRV/SalesOrderCollection(‘0500000001’)/?$expand=SalesOrderItems

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

The $expand statement is handled by the framework (no additional implementation is required). Since the framework does not know that both entities can be obtained using a single RFC call, it executes two calls to the underlying BAPI. This can be improved by manually implementing (re-defining) the GET_EXPANDED_ENTITY method.

So we are done. The Service is up and running.

I hope you enjoyed creating and consuming an OData Service that is based on RFC modules.

Assigned Tags

      24 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Wouter Peeters
      Wouter Peeters

      Hi Volker,

      Thx, these are a great tutorial series to get started with Gateway.

      But I'm having some troubles adding a navigation torwards the Product Detail, from the Sales Order Item entity. Do you have any pointers? Maybe this is a good idea for a part 4.

      Regards,

      wouter

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

      Hi Wouter,

      thanks for the feedback.

      Navigating from a Line Item to the related Product is a little trickier. This is because the URI that you use (e.g. ".../SalesOrderItemCollection( SoItemPos=..., SoID=...)/ToProduct" ) only has the key information of the Line Item. In order to be able to navigate to the product entry you first need to read the Line Item detail to fetch the related Product-Id, and from there fetch the entire product.

      Luckily this is taken care of by the Service Builder as well. You just need to make sure to maintain the Association and the Referential Constraint between the Line Item and the Product.

      hth.

      Regards, Volker

      Author's profile photo Wouter Peeters
      Wouter Peeters

      Hi Volker,

      Thanks for the reply, for more information there's a topic on the matter:

      http://scn.sap.com/thread/3434085

      Regards,

      Wouter

      Author's profile photo Vijay Dudla
      Vijay Dudla

      Hi Volker,

      I did the same steps but unable to use the navigation or expand option? what was the issue.

      Below is the metadata for my service.

      <?xml version="1.0" encoding="utf-8" ?>

      - <edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:sap="http://www.sap.com/Protocols/SAPData">

      - <edmx:DataServices m:DataServiceVersion="2.0">

      - <Schema Namespace="ZDEMO09_SRV" xml:lang="en" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">

      - <EntityType Name="Orderheader" sap:content-version="1">

      - <Key>

      <PropertyRef Name="Vbeln" />

      </Key>

      <Property Name="Vbeln" Type="Edm.String" Nullable="false" MaxLength="10" sap:label="Sales Document" sap:sortable="false" sap:filterable="false" />

      <Property Name="Erdat" Type="Edm.DateTime" Nullable="false" sap:label="Created on" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />

      <Property Name="Erzet" Type="Edm.Time" Nullable="false" sap:label="Time" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />

      <Property Name="Ernam" Type="Edm.String" Nullable="false" MaxLength="12" sap:label="Created by" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />

      <NavigationProperty Name="OrderItemSet" Relationship="ZDEMO09_SRV.SalesOrder" FromRole="FromRole_SalesOrder" ToRole="ToRole_SalesOrder" />

      </EntityType>

      - <EntityType Name="OrderItem" sap:content-version="1">

      - <Key>

      <PropertyRef Name="Posnr" />

      <PropertyRef Name="Vbeln" />

      </Key>

      <Property Name="Pstyv" Type="Edm.String" Nullable="false" MaxLength="4" sap:label="Item category" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />

      <Property Name="Matkl" Type="Edm.String" Nullable="false" MaxLength="9" sap:label="Material Group" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />

      <Property Name="Matnr" Type="Edm.String" Nullable="false" MaxLength="18" sap:label="Material" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false" />

      <Property Name="Posnr" Type="Edm.String" Nullable="false" MaxLength="6" sap:label="Item" sap:sortable="false" sap:filterable="false" />

      <Property Name="Vbeln" Type="Edm.String" Nullable="false" MaxLength="10" sap:label="Sales Document" sap:sortable="false" sap:filterable="false" />

      </EntityType>

      - <Association Name="SalesOrder" sap:content-version="1">

      <End Type="ZDEMO09_SRV.Orderheader" Multiplicity="1" Role="FromRole_SalesOrder" />

      <End Type="ZDEMO09_SRV.OrderItem" Multiplicity="*" Role="ToRole_SalesOrder" />

      - <ReferentialConstraint>

      - <Principal Role="FromRole_SalesOrder">

      <PropertyRef Name="Vbeln" />

      </Principal>

      - <Dependent Role="ToRole_SalesOrder">

      <PropertyRef Name="Vbeln" />

      </Dependent>

      </ReferentialConstraint>

      </Association>

      - <EntityContainer Name="ZDEMO09_SRV" m:IsDefaultEntityContainer="true">

      <EntitySet Name="OrderHeaders" EntityType="ZDEMO09_SRV.Orderheader" sap:pageable="false" sap:addressable="false" sap:content-version="1" />

      <EntitySet Name="OrderItems" EntityType="ZDEMO09_SRV.OrderItem" sap:pageable="false" sap:addressable="false" sap:content-version="1" />

      - <AssociationSet Name="SalesOrderSet" Association="ZDEMO09_SRV.SalesOrder" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:content-version="1">

      <End EntitySet="OrderHeaders" Role="FromRole_SalesOrder" />

      <End EntitySet="OrderItems" Role="ToRole_SalesOrder" />

      </AssociationSet>

      </EntityContainer>

      <atom:link rel="self" href="http://sapcis01.citrite.net:8080/sap/opu/odata/sap/ZDEMO09_SRV/$metadata" xmlns:atom="http://www.w3.org/2005/Atom" />

      <atom:link rel="latest-version" href="http://sapcis01.citrite.net:8080/sap/opu/odata/sap/ZDEMO09_SRV/$metadata" xmlns:atom="http://www.w3.org/2005/Atom" />

      </Schema>

      </edmx:DataServices>

      </edmx:Edmx>

      Thanks

      Vijay

      Author's profile photo Shakeeluddin Khaja
      Shakeeluddin Khaja

      Very useful info . Thanks Volker

      Author's profile photo Former Member
      Former Member

      Hi Volker,

      Your Tutorial has been very helpful. I am learning Webservices from scratch.

      I have a doubt.

      I cant find the ASSOCIATION SETS block in my SEGW Project. Would there be a reason for this?

      Thanks

      Abraham

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

      Hi Abraham,

      I assume you are using a newer version of SAP NetWeaver Gateway (the blog was written for SP5)?

      The Gateway Framework is automatically generating the Association Sets based on the defined Associations. That's the reason why the Service Builder is not showing them in the navigation tree anymore. But you can still create own Association Sets if you want (Right-Click on Data Model and choose Create -> Association Set).

      Best Regards, Volker

      Author's profile photo Rahul Keshav
      Rahul Keshav

      It worked for me...Thanks Volker......

      Author's profile photo Amber Badam
      Amber Badam

      very illustrative. nice blog. appreciate it.

      Author's profile photo Former Member
      Former Member

      Very Informative..

      Thanks.

      Author's profile photo Former Member
      Former Member

      Hi Volker,

      It is a wonderful doc, I can not tell you how much I appreciate your work, thanks. 😛

      Author's profile photo Alexander Turonok
      Alexander Turonok

      Hi Volker,

      amazing really valuable. thanks for your time composing this one. 

      Best Regards, Alex

      Author's profile photo BOGA UMASHANKAR
      BOGA UMASHANKAR

      Hi Volker,

      I would like to add few comment to this wonderful blog.

      People who are working on higher version of SAP Netweaver Gateway services who can't see the Associate Sets and Navigation folder in Gateway Service Builder Project they can actually follow navigation using following link

      Association and Navigation in OData Service - SAP Netweaver Gateway - SAP Fiori,SAP HANA,SAPUI5,SAP Netweaver Gateway Tu…

      This is only for navigation still they need to follow the same naming convention what you used in this document

      Uma

      Author's profile photo BOGA UMASHANKAR
      BOGA UMASHANKAR

      Hi Volker,

      Can you explain what is the difference between

      /sap/opu/odata/sap/ZGW100_01_SO_SRV/SalesOrderCollection('500000000')/?expand=SalesOrderItems

      and

      /sap/opu/odata/sap/ZGW100_01_SO_SRV/SalesOrderCollection('500000000')

      I think out put is looking same

      what is the use of $expand

      Thanks

      Uma

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

      Hi Uma,

      there is a typo in your URI. The '$' is missing. It should look like:


      /sap/opu/odata/sap/ZGW100_01_SO_SRV/SalesOrderCollection('500000000')/?$expand=SalesOrderItems


      With this you will see a difference.


      Best Regards,

      Volker

      Author's profile photo Patrick Dean
      Patrick Dean

      Step by step and succinct: Enough detail so we can't make any mistakes, not so much that we get confused as to what's going on. This is one I shall be showing to others when they need guidance!

      Author's profile photo Former Member
      Former Member

      Hey volker,

      I am new to the Odata services, can you explain in the same way for all the CRUD properties.
      That would be very helpful.

      Thanks and regards,
      Rohan.

      Author's profile photo Former Member
      Former Member

      hi volker,

      very useful blog . Me and one of my friend were following your  blog ,he successfully completed the task using association and navigation.

      When i am looking for all data it is ok.

      but i am facing unknown problem Can u please help me out.

      My mHeaderset is working fine it is giving back the required table entries, but when i am trying to retrieve the specific data it is throwing me 404.

      it is not taking my service. what can be the reason for it?

       

      Author's profile photo Srawan Kumar Dubbakka
      Srawan Kumar Dubbakka

      Hi Vijay,

      Can you put a break point in entityset method and check if the sales order which you are trying to retrieve has done conversion(CONVERSION_EXIT_ALPHA_INPUT).

       

      Srawan.

       

      Author's profile photo Arjya Kumar Das
      Arjya Kumar Das

      Hi Volker

      Hope you are doing good.As per the below screen the metadata connection is working fine and also completed part 3 .

       

      The below step is not working for me when I am trying to fetch fields instead of $metedata I am using SalesOrderCollection.Can you help to support as I need to provide a demo.Or If any case you can provide or number or chat window where we can discuss.

       

      4. When you now select a sales order entry using
      /sap/opu/odata/sap/ZGW100_XX_SO_SRV/SalesOrderCollection(‘0500000001’), for example, you can simply add the navigation link /SalesOrderItems to navigate to the line items without having to set a filter yourself.This portion is not working and I am getting error 404.Can you help to resolve this step.

      Author's profile photo David Raven
      David Raven

      Hi,

      Do I need to add coding in the DEEP method as I saw in other blogs?

       

      Thanks.

      Author's profile photo Aiolos Yang
      Aiolos Yang

      Hi Volker,

      your blog is pretty good, hope more in future. Thanks.

      Author's profile photo BOBAE Choi
      BOBAE Choi

      Thansk for this information.

      It's very useful.

      Author's profile photo María Isabel Rodríguez Canedo
      María Isabel Rodríguez Canedo

      Thanks for the complete information