How $expand Influences the Importing Parameters of GET_ENTITYSET in SAP Gateway
Did you know that the method parameter IV_SOURCE_NAME of GET_ENTITYSET has different values depending on whether the service is triggered with or without $expand? This also applies to the parameter IT_NAVIGATION_PATH. I recently found out about this the hard way because not knowing this caused a bug in my code. I think it’s worth sharing my findings. Basically, you will see that using $expand fills the parameters mentioned above differently compared to directly triggering GET_ENTITYSET without $expand but still with Navigation Properties.
First of all, I’m using NW 7.4 SP12 together with SAP_GWFND SP12 (and some additional patches/notes).
We’re going to use the GWSAMPLE_BASIC project/service that is shipped with your GW installation. You can simply go to the Service Builder (transaction code SEGW) and open the project /IWBEP/GWSAMPLE_BASIC. I like this project because I could see how SAP implements GW services – and I learned a lot from that in the past 🙂 Also, check Demo service ZGWSAMPLE_SRV | SCN by Andre Fischer which tells you a little more about the data model of the Gateway Sample Project.
Now let’s first set a breakpoint in the method CONTACTSET_GET_ENTITYSET of the class /IWBEP/CL_GWSAMPLE_BAS_DPC_EXT. You can navigate there directly from SEGW (see screenshot above), or just use SE80.
Now, after we have set the breakpoint, let’s try some example URLs and see what happens.
1. Without $expand: /sap/opu/odata/IWBEP/GWSAMPLE_BASIC/SalesOrderSet(‘0500000000’)/ToBusinessPartner/ToContacts
As you can see this URL is using two Navigation Properties. First, we navigate to the BusinessPartner of a given SalesOrder, then to the BusinessPartner’s contacts. This will only return the contact data to the caller of the service. Calling this URL will hit the breakpoint we set above:
While we are in the debugger inside CONTACTSET_GET_ENTITYSET let’s check the two mentioned parameters:
- IV_SOURCE_NAME ==> ”SalesOrder”
- IT_NAVIGATION_PATH ==> two entries, ToBusinessPArtner, ToContacts (see screenshot below)
This basically tells us from the source “SalesOrder”, we first navigated to the BusinessPartner and then to the contacts. The itab IT_NAVIGATION_PATH also contains information about the Target_Type (=Entity) and the corresponding namespace. So far so good. Now let’s assume we want a given SalesOrder and the contacts of its BusinessPartner in one request. We will achieve this using $expand.
2. With $expand: /sap/opu/odata/IWBEP/GWSAMPLE_BASIC/SalesOrderSet(‘0500000000’)?$expand=ToBusinessPartner/ToContacts
Again, hitting this URL will hit our breakpoint. However, this time both IV_SOURCE_NAME and IT_NAVIGATION_PATH have different values (see screenshots below):
- IV_SOURCE_NAME ==> ”BusinessPartner”
- IT_NAVIGATION_PATH ==> 1 entry, ToContacts (for some reason the TARGET_TYPE_NAMESPACE is not filled)
This basically tells us from the source “BusinessPartner” we navigated to the contacts. However, this is not what I expected. I expected that using $expand in this scenario would be equal to calling our first URL from above in Step 1 (/sap/opu/odata/IWBEP/GWSAMPLE_BASIC/SalesOrderSet(‘0500000000’)/ToBusinessPartner/ToContacts).
Instead, when using $expand in our scenario it’s basically equal to calling the URL /sap/opu/odata/IWBEP/GWSAMPLE_BASIC/BusinessPartnerSet(‘0100000000’)/ToContacts, the explanation comes next.
3. Behind the scenes: /sap/opu/odata/IWBEP/GWSAMPLE_BASIC/BusinessPartnerSet(‘0100000000’)/ToContacts
So, when using $expand, we now know what is actually called behind the scenes by the Gateway. Well, let’s prove this in the debugger by calling /sap/opu/odata/IWBEP/GWSAMPLE_BASIC/BusinessPartnerSet(‘0100000000’)/ToContacts directly:
As you can see the result is equal to what we had in Step 2 – and that’s the prove:
- IV_SOURCE_NAME ==> ”BusinessPartner”
- IT_NAVIGATION_PATH ==> 1 entry, ToContacts
However, this time for some reason the TARGET_TYPE_NAMESPACE is filled correctly – which I can’t explain 🙂
I’m sure there is a good reason for the different values passed to the parameters – but I don’t know that reason 🙂
Anyway… I’m aware of this now and I hope you are as well.
there is a big difference between getting entities through a navigation and expanding entities. In the first case, the Gateway framework calls the data provider to get the target entities (and only those) providing the navigation path information. In your example: the contacts.
With $expand you are actually retrieving certain entities (sales order 0500000000 in your case) including sub-entities (business partner contacts) inline. Depending on the $expand clause the tree of sub-entities might be quite complex. If the data provider does not re-define the specific expand methods the Gateway framework will resolve the expand tree recursively calling the corresponding data provider class methods on each level of resolution. This is why it looks as if you navigate from the business partner - that was just the previous resolution step.
The missing namespace might rather be a bug 😉
Thanks for getting back to this and for highlighting some insights.