Odata Note Part3
Odata Note Part3
Introduction
This series of blogs is an attempt to provide a comprehensive guide to OData and how it is consumed in the
SAP world. There has been a lot of content on the Internet explaining what is OData, how the services and
published and how to consume which is scattered and assumes that the reader has clarity already on some
very important fundamentals. However, there are so many aspects which deserves more than just a mention.
In this blog, we will try and cover the topic 360 degrees.
We start with the very basics of HTTP and then gradually build on to OData and finally conclude with a detailed
end-to-end exercise on how to create an OData service and how to consume it.
▪ You would typically need a Web Browser, address of the document you want to read or the URL
(Uniform Resource Locator), a Web Server running at the system where the document is located.
▪ Web Browser is a software which is responsible to retrieving and presenting resources on the web.
Web Browser parses the HTML response received from the Web and prepares a DOM Tree. DOM
stands for Document Object Model and it is a language-independent convention of representing objects
in HTML. Web Browser acts as an interface between you and the World Wide Web.
▪ You can request for a document located somewhere on this planet by providing its address via the
browser which sends HTTP requests to the web server. The Web server then sends back HTTP
response that is parsed by the Web Browser for you to view the document on your machine.
▪ HTTP stands for Hyper Text Transfer Protocol and as the name suggest it defines the semantics of
what the browser and the web server can communicate to each other. The how part of the
communication or the byte by byte transfer of the data packets across the network is not HTTP but it is
done via TCP/IP protocols.
▪ An important component in the story so far is also the Web Server. In a nutshell, Web Server is a server
program which sits on a physical server and waits for requests from a client. Whenever a request is
received the Web Server prepares a response and sends it back to the client using HTTP protocol. It is
important to note that HTTP is not the only but, by far most commonly used protocol and that the client
here can be a browser or any other software that communicates in HTTP.
“HTTP is based on a Client-Server architecture style and it uses a stateless request/response protocol to
communicate between the client and the web server. The HTTP protocol helps define what requests can be
sent across by the client and response sent by web server. The communication of data over the network is
however done using on TCP/IP protocol”.
It is evident that HTTP is based on client server architecture from our description till now, browser being the
client which sends HTTP request and web server which sends the response back to the browser. But, why
stateless?
Every single HTTP request that is received by the web server is forgotten after a response has been sent
across. Web servers do not process an HTTP request by remembering the previous request.
URI or the Uniform Resource Identifier can be classified as a name, locator or both that identifies a resource
uniquely.
URL (Uniform Resource Locator) is actually a subset of URI that not only identifies a resource uniquely but
also provide means of locating the resource.
GET
This is used to retrieve information about the resource from the server.
POST
HTTP Response from the Web Server comes with data and the status code. The status code provides a
context to the response. For instance, if you do not correctly provide the resource location, the web browser
will send you a response which you are not expecting. Along with the data response comes the status code,
known universally in the HTTP world, that explains to the user what could be the reason for an unexpected
response.
It means the request has been received and the process is continuing.
2xx: Success
For example, status code 400 means Bad Request. It means that the server did not understand the request.
OData allows creation and consumption of RESTful APIs. In the next blog, I will cover what are RESTful APIs
as the next stepping stone towards understanding OData.
What is REST?
REST or Representational State Transfer is an architectural style that uses simple and lightweight mechanism
for inter-machine communication. It is an alternative to the RPC (Remote Procedure Calls) and Web Services.
REST is resource based unlike RPC or SOAP which are action based. In SOAP you will have a request to get
material data whereas in REST, material will be identified as a resource using URI and then use HTTP verbs to
determine which operation shall be performed on the resource. It is important to note here that it is possible to
have multiple URIs pointing to the same resource.
Representation of the resource is not the resource itself but only a representation.
The term representation is how the resources are manipulated in a REST based architecture
Representations depict parts of the resource state which are transferred between client and server in mostly
JSON or XML format. Client will typically have enough information to manipulate the resource on the server.
For example, if Person is modelled as a resource and there is a service to get contact information of a person
then the representation that you will get of that Person would be Name, Address and Phone details in JSON or
XML format.
1. Uniform Interface
Uniform Interface is fundamental to the design of any REST based service. The uniform interface simplifies
and decouples the architecture, which enables each part to evolve independently.
What that means is that it should be possible to identify the individual resource in the request, for example
using URI. Once the Client has a representation of the Resource then, it should have enough information to
update or delete the resource. And that the Client should not assume that any particular action is available on
a resource beyond those described in the representation received from the server previously.
2. Stateless
The Server should not contain any Client state. It is possible to process a request only if they are
self-descriptive and that the request should have enough context to act upon. For example, if the Person
resource address needs to be updated then it is required that the Client pass on the particular Person resource
details in the request for which it has received the representation from the Server in the previous request. If the
state has to be maintained, it should be at the Client side.
3. Client-Server
We have already established this constraint that the RESTful architecture is a Client-Server architecture.
Resource representations are transferred between client and server. We should always keep at the back of our
minds that the Client of RESTful APIs will not have direct connects to the Resources.
4. Cacheable
Another constraint on a RESTful API is that any response that is coming from the Sever should be cacheable
on the Client side. Caching could be implicit, explicit or negotiable. Implicit and Explicit caching is
self-explanatory whereas Negotiable caching means that the Server and Client agree on how long a
representation can be cached on the Client.
5. Layered System
The constraint of Layered System is closely related to the above two constraints of Client-Server and
Cacheable. It suggests that the Client of a RESTful API should not assume that there will be a direct
connection between the client and the server. There could be multiple layers of software or/and hardware in
between the two. The Client need not know whom exactly it is talking to and whether a response is coming
from the server or is accessed from a local cache. This improves scalability.
6. Code on Demand
This constraints suggests that it should be possible that a Server can extend a Client temporarily. It means that
Server can transfer logic to the client as representation to be executed at the client.
This is the only optional constraint.
A RESTful service needs to adhere to all of the above mentioned constraints (except Code on Demand) to be
called as a RESTful API.
What is OData?
“Open Data Protocol (OData) is an open data access protocol from Microsoft that allows the creation and
consumption of query-able and interoperable RESTful APIs in a simple and standard way”.
The protocol enables the Clients to publish and manipulate the resource identified by URIs and defined in a
data model using simple HTTP messages.
To put it in simple words, OData is an open source to exchange data over the Internet. Server hosts the data
and clients can call this service to retrieve the resources and manipulate them. Servers expose one or more
endpoints which are services that refer to the resources. Clients need to know this server side endpoint to call
the service to query or manipulate the data. The protocol is HTTP based and designed with a RESTful mindset
which means it follows the constraints to be called as a RESTful service.
Since the protocol is HTTP based, any programming language with HTTP stack can be used to consume
OData services. Existing Client side libraries can be used to transform the JSON or ATOM payloads from the
server into objects making programming simple. On the other hand, many libraries exist on the Server side to
generate the payloads in ATOM or JSON from the existing data.
It is important to note that both Client side and Server side development can be in completely different
programming languages till the time both are able to communicate via HTTP.
Clients consume the service to query and manipulate the data from OData Services and are also called as
Consumers of OData Service.
Similarly, Servers that expose the OData services via endpoints are known as Producers of Odata services.
So, we now know that in OData protocol, the resources are exposed in two formats; XML based Atom and
JSON.
Atom is a combination of two protocols, Atom Syndication and Atom Publishing protocol. The Atom
Syndication Format is an XML language used for web feeds, while the Atom Publishing Protocol (AtomPub or
APP) is a simple HTTP-based protocol for creating and updating web resources.
JSON stands for JavaScript Object Notation is a lightweight data-interchange format. JSON is self-descriptive
and easy to use and is completely language-independent.
Exposing your data with OData services comes with multifold advantages. For example, as we mentioned
earlier, as a consumer, you need not worry about the programming language used by the producer as long as
the services are exposed as OData service.
ODBC for the Web
ODBC (Open Database Connectivity) is a standard API to access the database management systems
independent of the database management systems or operating systems. ODBC manages this by adding
drivers between the Application layer and the DBMS to translate the queries fired by application into
instructions which DBMS can understand.
OData has similarity with the ODBC in a sense that here, OData provides the middleware between producers
and consumers to communicate data. There is a uniform way to consume data and is independent of the
producer much like ODBC. The fact that OData is based on HTTP RESTful services makes it the ODBC for
the Web!
Point-to-point solutions are not the right way as it has a lot of drawbacks including duplication of development
effort, increased cost, complex landscape, poor scalability and difficulty to maintain.
SAP Netweaver Gateway is a technology that has the answer to this. It can seamlessly connect devices,
platforms and environments to SAP Enterprise Data using the OData services. SAP Netweaver Gateway offers
connectivity to SAP Business data using any programming language and without the need of strong SAP
development knowledge.
SAP Netweaver Gateway comes with design-time tools to facilitate modeling OData services for consumption.
These tools improve user experience and provide automatic connectivity to the SAP backend that reduces
development efforts and improves productivity.
SAP Netweaver Gateway sits on top of the existing SAP Backend infrastructure. There are set of add-on
components that needs to be installed on a SAP Backend system to enable SAP Netweaver Gateway
services. It is this architecture that enables consumption of SAP data by variety of interfaces such as BAPIs
and RFCs
SAP Netweaver Gateway Service Builder tools is SAP GUI based modeler to create and publish Odata
services using transaction SEGW.
There is also an Eclipse-based Odata Modeler tool available. It provides an easier way to model the service
that is a much easier way to develop if you are not too familiar with ABAP programming language. The models
can be conveniently created here are exported to the development environment for the Gateway.
SAP has leveraged the extensibility feature provided by Atom Publishing protocol to add SAP specific
annotations. AtomPub allows you to add your own markups in the service document. SAP adds annotations
from the ABAP Data Dictionary, for example, labels to the documents which can then be consumed by the
front end application without having to worry about translations in this case.
In my next blog, I will focus on the various deployment options for SAP Netweaver Gateway.
SAP Netweaver Gateway prior to NW 7.4 had three add-ons namely GW_CORE, IN_FND and IW_BEP. While
the first two components were required for Gateway server functionalities, IW_BEP was used for Gateway
backend functionalities.
From the onset of NW 7.0 release, all the three components are bundled into a single component
SAP_GWFND or Gateway Foundation.
There are three possible deployment options to pick from and we will discuss each one of them.
In this deployment strategy, the SAP Netweaver Gateway is installed on a separate SAP machine referred to
as Gateway Hub. The OData services are registered and exposed from the Gateway Hub but are developed in
the SAP backend system. If SAP Business Suite backend systems are running on NW release prior to 7.4 then
component IW_BEP should be installed. For systems running on NW7.4 onwards the SAP_GWFND
component contains both Gateway server and backend functionalities as mentioned before.
● There is only a single access point of access to the SAP Backend systems. No direct access from the
outside world provides enhanced security.
●
● Gateway Hub can be a system running on newer release NW 7.31 or NW 7.4 with a Backed system
running on lower release is perfectly acceptable.
o Gateway on newer releases would mean support for SAP UI5.
o Supports added authentication features.
● Direct access to metadata (DDIC) and business data for OData Modeling by backend systems.
2. Hub Deployment: Development in the Hub
Hub Deployment with development in the Gateway Hub is an option where just like the previous option, there
is a dedicated Gateway Hub as a separate system from the backend system. Since, all the development
related to SAP Netweaver Gateway takes place in the Gateway Hub, backend not necessary should have any
Gateway components installed. It is a feasible option if you don’t want to do any kind of development in the
backend system and leverage what is already available.
● Access to the data source for Odata service development is only limited to existing BAPIs and RFCs.
●
● There will be no direct access to the backed dictionary objects to the Gateway Hub where the Odata
services are modeled. The access is limited to only remote access.
●
● Having a landscape with a dedicated system as Gateway Hub involves additional costs as compared to
an embedded deployment option. This is true for the above deployment option as well.
3. Embedded Deployment
In the Embedded Deployment option, the SAP Netweaver gateway components are installed as add-ons on
the SAP backed system itself. Both the Odata modeling and the exposing of the services is done from the
backend system. This deployment strategy saves cost as there is no dedicated Gateway Hub. Also, the
runtime overhead due to remote calls in the above two deployment options is reduced.
Disadvantages:
● If there are multiple SAP Business Suite Backed systems in the landscape then, each system will have
its own installation and configuration of Netweaver Gateway components.
●
● Upgrade of backed systems will follow a different cycle than that of Netweaver Gateway.
●
● Additional security measures needed as there is no single access point from the backend system to the
consumers.
We will define the problem statement and give you a glimpse of what we are trying to build as a small
application to showcase the power of OData. We will also build a simple Fiori-like app as a frontend consumer.
Knowledge of Fiori is not at all a must here. As I mentioned earlier, during the course of the end-to-end
exercise we will also explain various artifacts of OData.
In the next few blogs we will be creating a simple Master-Detail Fiori-like app based on SAP Flight Model
example. . We will leverage the existing backend developments to expose the data as OData service that will
be consumed by the frontend. Future blogs will follow the Embedded deployment environment but, most of the
steps we do here are applicable to the other two deployments. It is just a matter of where you do the modeling.
Here, is a link to the Overview of Fiori in case you wish to know more.
The app we are going to develop is a very simple app based on the SFLIGHT example to check seat
availability and add new flight tours.
Master-detail app will have the left navigation panel and will feature the list of Airlines along with codes. The
detail section of the app will contain the tabular list of different flights corresponding Airline. Users will be
allowed to select a flight and check for availability for a given date and class. App will also allow users to add
new flights for a specific Airline and dates on which the flights are scheduled. We will showcase the CRUDQ
operations along with navigations from master to object view and function imports during the course of this
app.
Master-Detail view with Airlines information on left navigation panel and various flights operating for a specific
airlines on the details section.
Check Availability scenario
Step by Step process to create Odata services in SAP / SAP HANA system
Click on Icon Create. A pop window will appear , Fill the details as per below mentioned in screen shot and click on
check icon or enter.
Below screen will appear where you can see below folder in project. In Folder data model, we can see three sub
folders. Entity Type – it acts as work area , Entity Sets -It act as internal table and associations.
Now we are going to define the structure of the work area and internal table. Right click on the Data model, select
import and select DDIC structure .
Here give the details of structure and structure name as per the screen below.
Select radio button Entity type and and click on checkbox entity set. fill ABAP structure as VBAK and click on next
Now you will get the pop up screen with VBAK table fields name. Select fields for your structure and click on next.
project5
Another window will appear where we have to select the key field. tick on Vbeln as the key field and click on finish.
You may get a warning message , it can be totally ignored.
Now expand folder entity type and fill the below parameters in properties , Please don’t tick the Null check box for
VBELN as it is key field.
Similarly Create Structure for SD Item following same steps
click on Save button at the top of menu bar
Now click on generate Icon, A pop up window will appear with class details , click on tick icon and proceed further. It
will ask for a package , give details and proceed further . These are also known as runtime artifacts.
Now double click on your project name . A pop up window will appear , enter the package details and click on the
tick icon. An Information message will be shown where it will confirm about the service is created and metadata
loaded successfully
Now click back and go to the main screen of transaction /IWFND/MAINT_SERVICE and find your service.
A new screen will come, Execute the transaction and check the response .
Under service implementation – Expand SDheaderSet. you will find different options. Right click on GetEntitySet
and select GO to ABAP workBench . It will redirect to the class
Now expand the method drop down and select the method for GetEntitySet for Header data and right click and
select redefine.
Write below code in method. Save and activate all related objects for classes.
Similarly , Write code for GetEntitySet for Item and activate .
Click and execute and you will get the header data in response
Similarly, Select entity set for item and execute . You will get data for item
Here , We had completed our Odata service creation with a Service Builder Project with two entities
and two entity-sets. We have generated the runtime artifacts and registered and activated our OData service.
We had redefined methods of header and item entity set , load metadata and test the entity set with for test data.
Task 2: Generate runtime objects and register and activate the service
1. Generate the runtime objects of your project
2. Register the service in the Gateway hub system (which is in this case the local system since we are using
Gateway in an embedded deployment scenario)
3. Test the service using the Gateway Client.
1. Implement the method PRODUCTS_GET_ENTITYSET in the extension class of the data provider class
2. We will use the function module 'BAPI_EPM_PRODUCT_GET_LIST' to retrieve the product data
3. Please note that the parameter ET_ENTITYSET that contains the data returned by the
GET_ENTITYSET method has the same structure as the structure BAPI_EPM_PRODUCT_HEADER
that has been used to generate the entity type Product.
1. Implement the method PRODUCTS_GET_ENTITY in the extension class of the data provider class
2. We will use the function module 'BAPI_EPM_PRODUCT_GET_DETAIL' to retrieve the product details
3. Please note that the parameter ER_ENTITY that contains the data returned by the GET_ENTITY
method has the same structure as the structure BAPI_EPM_PRODUCT_HEADER that has been used to
generate the entity type Product
Task 1: Creating a Data Model with entity Product and the entity set Products
Step -4
Go to transaction /IWFND/MAINT_SERVICE and find out you service , select your service and click on load
metadata.
Information messages will pop up – Metadata has been loaded successfully.
2. Enter the following value in the wizard and then press Enter:
Caution:
Please make sure that the Addressable flag is marked because otherwise GWPA will refuse to generate a consumer application.
Task 2: Generate runtime objects and register and activate the service
4. Verify that the runtime objects have been generated successfully:
Alternatively you can click on the entry GW_HUB on the left hand side, right click and select Register
from the context menu.
4. (Optional) If you have defined multiple system alias entries in the Gateway hub system that point back to
your backend press F4 to select a system alias and confirm the Select System Alias popup:
5. In the Add Service dialogue leave the default values and enter $tmp as the package and choose
Enter or press the button Local Object:
The External Service Name ZGW_PRODUCT_SRV is defaulted with the Technical Service Name
from the previous step.
6. Verify that the service has been registered and activated successfully:
2. This will start the Activate and Maintain Services transaction /IWFND_MAINT_SERVICE where the
service you have just registered is selected.
3. Press the button Gateway Client. This will open in a new window start transaction
/IWFND/GW_CLIENT using the the URI
2. Confirm the warning that the method PRODUCTS_GET_ENTITYSET has not yet been
implemented.
c. Or take the code from here using Cut & Paste
d. Activate the coding
method PRODUCTS_GET_ENTITYSET.
endmethod.
Start the Gateway Client (Transaction /IWFND/GW_CLIENT) in a separate window to run the service.
Provide the following URI to get the Product Collection:
/sap/opu/odata/sap/ZGW_PRODUCT_SRV/Products
Task 4 Service Implementation for GET_ENTITY
Prerequisites
- You have performed Task 1 to 3 and you have performed the following steps
o Project creation
o You have created a model with the entity set Products which is based on an entity type
Product that has been created using import of the DDIC structure
BAPI_EPM_PRODUCT_HEADER
o Implementation of the GET_ENTITYSET method
Objectives
In the following you will learn how to implement the GET_ENTITY method. For this we have to learn how to
retrieve the key(s )
/sap/opu/odata/sap/ZGW_PRODUCT_SRV/Products('AD-1000')
the framework takes care that the method PRODUCTS_GET_ENTITY of the data provider extension class
ZCL_ZGW_PRODUCT_DPC_EXT is called.
In order to provide the caller with the requested content the key value 'AD-1000' shall be retrieved using the
import parameter IO_TECH_REQUEST_CONTEXT.
This import parameter “speaks” the technical (internal) names and hence is not influenced by any
redefined function which could result that the external name of the key field can potentially be changed.
The internal names - unless explicitly set by the model provider - are derived from the "original" name.
We can set an external breakpoint in the PRODUCTS_GET_ENTITY method to check that the key value
‘AD-1000’ can be retrieved in the ABAP code as a key-value pair from the internal table. This table would
contain several entries in case the entity set has more than one key field.
The parameter ER_ENTITY which is used to return the data has the same type as the data dictionary object
that has been imported namely BAPI_EPM_PRODUCT_HEADER.
3. Confirm the message “Operation PRODUCTS_GET_ENTITY has not yet been implemented”
4. Scroll down to the method PRODUCTS_GET_ENTITY (1), switch to the edit mode (2) and choose redefine
(3)
5. You can retrieve the sample code from the following code snippet.
method PRODUCTS_GET_ENTITY.
endmethod.
6.(Optional) You can check how the data is retrieved in the ABAP code if you set an external breakpoint
Now let’s create an OData service which will insert, read, delete, update and query this table along with one custom operation
(UsersByCountry) as function import.
Function GET/POST Everything covered by GET and POST. But only use if scenario does not fit into
Import CRUDQ operations.
We can correlate Entity Set as Table Type, Internal table and Entity to work area, structure!
Procedure
Now right click on Data Model and Import –> DDIC Structure option, it will display a popup window. Provide DDIC structure name. In
this case table name ZUSERINFO. It will propose field and key mapping as well as object name which will be your entity name.
We will ignore MANDT as key field and also overwrite object name. I want my field names in upper camel case format so I will change it
accordingly. Let’s call entity type as User. It will look as below. Press enter.
Now let’s create Entity Set as UserCollection (or UserSet or Users). You can refer Creating High-Quality OData Services – SAP NetWeaver
Gateway Foundation (SAP_GWFND) – SAP Library
Right click folder name Entity Sets and click create. Provide entity set name as UserCollection and Entity Type name as User. It will
display as below.
Now let’s generate runtime artifacts. Click on the generate runtime objects button. It will display a popup as below. Keep the default
class names as-is and click on enter button.
On successful generation, you will see this kind of message log and generated artifacts. 4 classes will get generated. 2 for Data
provider and 2 for Model provider.
Now register your service under the service Maintenance folder. Click on Register button. Keep default values as-is and hit enter
button.
On successful registration, click Maintain button. This will open service catalog window along with an option to call Gateway Client.
Click on Gateway Client button to test the service. (you can also call transaction /IWFND/GW_CLIENT to open SAP NW Gateway
client)
Append $metadata to base service URL and press execute button. If everything is fine then you will HTTP Response as below.
Metadata provides information such as Entity type, key property, properties and Entity Set name.
So far we just defined single entity type and entity set. Now it’s time to code CRUDQ and function import methods.
Coding
There is no specific order to implement these methods but it is always good to 1st implement query and read operation as for Create
and Update, you will need request data which you will get if you already have query/read implemented.
1) Query Operation
First we will start implementing query operations. Before that, I will add one record in my ZUSERINFO table as
Now open the Runtime artifacts folder and right click on Class ZCL_ZUSERINFO_DPC_EXT and select Go to ABAP Workbench
option. Select edit mode and redefine method USERCOLLECTION_GET_ENTITYSET.
In the simplest form, this is what minimal coding will look like in GET_ENTITYSET method.
METHOD usercollection_get_entityset.
*Fill ET_ENTITYSET
ls_entity-userid = ls_userinfo-userid.
ls_entity-firstname = ls_userinfo-firstname.
ls_entity-lastname = ls_userinfo-lastname.
ls_entity-email = ls_userinfo-email.
ls_entity-phone = ls_userinfo-phone.
ls_entity-country = ls_userinfo-country.
ENDLOOP.
ENDMETHOD.
We are selecting all data from table ZUSERINFO and appending the result to exporting parameter ET_ENTITYSET.
Now you can go to GW client transaction and execute URI /sap/opu/odata/sap/ZUSERINFO_SRV/UserCollection which will display
one record which we already added into Z table.
Observe the method signature. put external breakpoint in method and execute query. You will find important information in method
parameters in debugging mode.
Below table will provide brief explanation of method parameters, alternative approach to get the value of those method parameters.
Last column specifies if we need to code to implement query operation.
OData Query Method Parameter Alternative way to get the value Coding required to implement
Query Operation
my_filter_options = io_tech_request_context-
>get_filter( )->get_filter_select_options( ).
my_filter_string = io_tech_request_context-
>get_filter( )->get_filter_string( ).
OR
UserCollection?$orderby=First
Name desc,LastName desc
UserCollection?search=’test’ IV_SEARCH_STRING data: my_search_string type string. Yes
my_search_string = io_tech_request_context
->get_search_string( ).
2) Read Operation
Now let’s implement GET_ENTITY method. Go to method USERCOLLECTION_GET_ENTITY and redefine it. Below is the minimal
code that we need to have in this method.
We need to read the key values passed from query URI and then fill the export parameter ER_ENTITY.
METHOD usercollection_get_entity.
lv_userid = ls_key_tab-value.
IF sy-subrc = 0.
er_entity-userid = ls_userinfo-userid.
er_entity-firstname = ls_userinfo-firstname.
er_entity-lastname = ls_userinfo-lastname.
er_entity-email = ls_userinfo-email.
er_entity-phone = ls_userinfo-phone.
er_entity-country = ls_userinfo-country.
ENDIF.
ENDMETHOD.
OData Query Method Parameter Alternative way to get the value Coding
required to
implement
Query
Operation
In case if we had association and IT_NAVIGATION_PAT DATA: my_nav_path type /iwbep/t_mgw_tech Yes
navigation between 2 entities H _navi.
my_nav_path = io_tech_request_context->ge
t_navigation_path( ).
UserCollection(‘Test’)?$format=json No No No
Also note that you cannot use system query options else you will get an error as System query options
‘$orderby,$skip,$top,$skiptoken,$inlinecount,’ are not allowed in the requested URI
3) Create Operation
Now we will focus on create operation by redefining method USERCOLLECTION_CREATE_ENTITY. Below is the code that will
perform POST operation.
Here we are reading the request data and then filling the exporting parameter ER_ENTITY.
METHOD usercollection_create_entity.
ls_userinfo-userid = ls_request_input_data-userid.
ls_userinfo-firstname = ls_request_input_data-firstname.
ls_userinfo-lastname = ls_request_input_data-lastname.
ls_userinfo-email = ls_request_input_data-email.
ls_userinfo-phone = ls_request_input_data-phone.
ls_userinfo-country = ls_request_input_data-country.
IF sy-subrc = 0.
ENDIF.
ENDMETHOD.
To test POST operation, 1st execute GET operation and then press Use as Request button which will copy the response to request
window and then select operation POST and execute.
In case you execute GET operation i.e. GET_ENITITYSET and then try to perform POST operation then you will get below kind of
error. Hence make sure that you execute GET to read single entity i.e. GET_ENTITY operation and then perform POST.
So correct steps are,
In case of Create operation, you cannot use system query options else you will get an error as
The Data Services Request contains SystemQueryOptions that are not allowed for this Request Type
This error message comes from the method PROCESS_ENTITY_SET (/IWCOR/CL_DS_PROC_DISPATCHER). Just in case if you are
4) Update Operation
Now we will implement the update operation by redefining method USERCOLLECTION_UPDATE_ENTITY. We need to put below code
in this method.
METHOD usercollection_update_entity.
lv_userid = ls_key_tab-value.
lastname = ls_request_input_data-lastname
email = ls_request_input_data-email
phone = ls_request_input_data-phone
country = ls_request_input_data-country
ENDIF.
ENDIF.
ENDMETHOD.
Here also first we need to execute GET operation to read the entity and then copy the response to request using Use as Request button and execute
PUT operation after editing required data. Successful HTTP response will look as below with status code as 204.
OData Query Method Parameter Alternative way to get the value Coding
required
to
implement
Query
Operation
lt_keys = io_tech_request_context->get_keys( ).
UserCollection(‘Test1’) IO_DATA_PROVIDER io_data_provider->read_entry_data( IMPORTING es_data = ls_req Yes
uest_input_data ).
5) Delete Operation
To implement the Delete operation, you need to execute the DELETE HTTP method for a particular key. Below is the code for the
method USERCOLLECTION_DELETE_ENTITY.
Here we are reading the key value of the record to be deleted and executing the Delete statement.
METHOD usercollection_delete_entity.
lv_userid = ls_key_tab-value.
ENDIF.
ENDMETHOD.
On successful record deletion, you will see HTTP response code as 204.
ls_key TYPE
/iwbep/s_mgw_tech_pair.
lt_keys =
io_tech_request_context->get_keys
( ).
6) Function Import
As per SAP documentation, Function Imports – SAP NetWeaver Gateway Foundation (SAP_GWFND) – SAP Library
The Open Data Protocol (OData) includes standard CRUD (Create, Retrieve, Update, and Delete) operations that map to the HTTP
methods POST, GET, PUT/MERGE, and DELETE.
In addition, OData supports further service operations (function imports) that can be invoked by the HTTP methods GET or POST for
anything that cannot be mapped to the standard CRUD operations. You can implement such additional service operations in the
Service Builder by creating function imports within your data model.
For example, you could create function imports for the following custom operations:
● Confirm Work Item
● Check Flight Availability
While it is simple to create new function imports to invoke custom operations, if the operation you want to use can be invoked using a
standard CRUD operation, you should not create a function import. That is, you should only create function imports for custom
operations that cannot be invoked using a standard operation.
In simple terms, if an operation cannot fit into CRUD scenario then you can perform it by function import.
And we want to get users by specific country then we can implement function import. Let’s call our function import as UsersByCountry!
Right click on Data model and create function import. Provide proper name. Again refer Creating High-Quality OData Services –
SAP NetWeaver Gateway Foundation (SAP_GWFND) – SAP Library
Provide required details such as mentioned below. Remember here we want to return collection of users and hence we selected Return
cardinality as 0..n with return entity set and HTTP method type as GET.
Now click on Function Import parameters and create import parameters as shown below. In this case we just want to pass value of
country and hence we will have one parameter as Country.
Finally save project, check project consistency and generate runtime objects. To check if everything is fine, in GW client execute
service metadata URL as /sap/opu/odata/sap/ZUSERINFO_SRV/$metadata which should show you function import definition in
metadata as below,
Now we will implement function import operation. Go to DPC_EXT class and redefine method
/IWBEP/IF_MGW_APPL_SRV_RUNTIME~EXECUTE_ACTION.
METHOD /iwbep/if_mgw_appl_srv_runtime~execute_action.
IF sy-subrc = 0.
lv_country = ls_parameter-value.
ENDIF.
ls_entity-userid = ls_userinfo-userid.
ls_entity-firstname = ls_userinfo-firstname.
ls_entity-lastname = ls_userinfo-lastname.
ls_entity-email = ls_userinfo-email.
ls_entity-phone = ls_userinfo-phone.
ls_entity-country = ls_userinfo-country.
APPEND ls_entity TO lt_entityset.
ENDLOOP.
ENDIF.
ENDIF.
ENDIF.
ENDMETHOD.
In the next screen enter below inputs to create Soheaderdata entitytype and SoheaderdataSet entityset
Select Key field in the next screen which is SO_ID in this case.
Press Finish button to create entitytype and entityset.
Repeat above steps to create entity type and entity set for item and products using structures: BAPI_EPM_SO_ITEM and
BAPI_EPM_PRODUCT_HEADER.
Select SO_ID and SO_ITEM_POS as key fields for item entity type
You can also see service implementations created for 3 entity sets.
Click on Generate run time objects button to create run time artifacts to implement CRUD operations
Classed generated:
Now expand service Maintenance folder and register ODATA service. And Then save project.
Alternatively you can also perform registering service manually using tcode: /IWFND/MAINT_SERVICE.
You will notice signal light turns to green in below screen shot
Specify association name, principal entity type name, dependent entity type name, Cardinality and Navigation Property in below window.
Specify referential constraints between Soheaderdata and Soitemdata and specify key relation in below window.
Finish setup in next window to create association and navigation property
Now create association and navigation property between Soitemdata and ProductHeaderdata similar way.
Delete below referential Constraints because there is no key relation
Now we are done with ODATA setup. In the next steps, we will implement data provider class methods to retrieve data.
In service implementation folder, for SoheaderdataSet entity set, we will implement method for GetEntitySet(Query) to retrieve all sales orders header
data.
http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/SoheaderdataSet
We will also implement URI parameters Filter, Skip, Top and Orderby in the above URL.
To learn more about URI parameter in odata services, refer to below link:
http://www.odata.org/documentation/odata-version-2-0/uri-conventions/
http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/SoheaderdataSet?$filter=CurrencyCode eq ‘EUR’
For Skip and Top URI parameter: This will skip for 2 entries and display next top 10 sales orders.
http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/SoheaderdataSet?$skip=2&$top=10
http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/SoheaderdataSet?$orderby=GrossAmount
Data declarations:
Get Filter and orderby URI parameter values. Filter or selection URI parameters can retrieved using below method.
IF io_tech_request_context IS BOUND.
DATA(t_orderby) = io_tech_request_context->get_orderby( ).
ENDIF.
* Get filter or select option information
DATA(lo_filter) = io_tech_request_context->get_filter( ).
DATA(lt_filter_select_options) = lo_filter->get_filter_select_options( ).
DATA(lv_filter_str) = lo_filter->get_filter_string( ).
Build dynamic where condition and select sale orders header data
To retrieve specific sales order data using below URL, we will implement method: SOHEADERDATASET_GET_ENTITY for GetEntity(Read).
http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/SoheaderdataSet(‘500000000’)
Redefine method in same class and copy below code in the method:
Method: SOITEMDATASET_GET_ENTITYSET to get all sales items for sales order using
URL: http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/SoheaderdataSet(‘500000000’)/SalesOrderItem
Below URL will calls methods SOHEADERDATASET_GET_ENTITYSET and SOITEMDATASET_GET_ENTITYSET in loop to retrieve all line items
related to all sales orders
http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/SoheaderdataSet?$expand=SalesOrderItem
Next we will implement SOITEMDATASET_GET_ENTITY to display sales item data for specific sales order and sales item. We can use below URL:
http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/SoitemdataSet(SoId=’500000000′,SoItemPos=’10’)
http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/SoheaderdataSet(‘500000000′)/SalesOrderItem(SoId=’500000000′,SoItemP
os=’10’)
Below URL also retrieves all items related to single sales order “500000000”: This will call methods SOHEADERDATASET_GET_ENTITY and
SOITEMDATASET_GET_ENTITYSET .
http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/SoheaderdataSet(‘500000000’)?$expand=SalesOrderItem
Below URL retrieves product details related to sales order 500000000 and Item 10:
http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/SoitemdataSet(SoId=’500000000′,SoItemPos=’10’)/SalesOrderProduct
This URL calls Methods SOITEMDATASET_GET_ENTITY and then PRODUCTHEADERDAT_GET_ENTITYSET
http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/SoheaderdataSet(‘5000000000′)/SalesOrderItem(SoId=’500000000′,SoItem
Pos=’10’)/SalesOrderProduct
Below URL will retrieve all items and product info related to order: 5000000000
http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/SoheaderdataSet(‘500000000’)?$expand=SalesOrderItem/SalesOrderProd
uct
http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/ProductHeaderdataSet
Check for entries in it_key_tab and it_navigation_path to see if we need to retrieve product details related to a particular order/item or need to display all
product details. If both importing tables it_key_tab and it_navigation_path are empty then retrieve all products using BAPI_EPM_PRODUCT_GET_LIST
and populate records to et_entityset.
In the else condition, check if URL has navigation property: SalesOrderItem, then get sales order and item number from it_navigation_path-key_tab OR
else use it_key_tab importing parameter.
* We can use below read(commented out) instead of conventional read statement, but if no navigation *property with
* SalesOrderItem is used in URL, below read will raise an exception: cx_sy_itab_line_not_found.
* With ABAP 7.5, we can use clause OPTIONAL along with below read so that it will not raise an
* exception and it would also set syst-subrc = 0. My current abap system is 7.4
* DATA(it_key_tab_tmp) = it_navigation_path[ nav_prop = 'SalesOrderItem' ]-key_tab.
READ TABLE it_navigation_path INTO DATA(w_navigation_path) WITH KEY nav_prop = 'SalesOrderItem'.
IF syst-subrc = 0.
DATA(it_key_tab_tmp) = w_navigation_path-key_tab.
ELSEIF it_key_tab IS NOT INITIAL.
it_key_tab_tmp = it_key_tab.
ENDIF.
DATA(lw_order_val) = it_key_tab_tmp[ name = 'SoId' ].
DATA(lw_item_val) = it_key_tab_tmp[ name = 'SoItemPos' ].
lw_orderno = |{ lw_order_val-value ALPHA = IN }|.
lw_itemno = |{ lw_item_val-value ALPHA = IN }|.
lw_so_id-so_id = lw_orderno.
CALL FUNCTION 'BAPI_EPM_SO_GET_DETAIL'
EXPORTING
so_id = lw_so_id
IMPORTING
headerdata = lw_header_so
TABLES
itemdata = lt_itemso.
In the above code using sales order number and item number, getting corresponding product number. Use BAPI: BAPI_EPM_PRODUCT_GET_DETAIL
to retrieve product details for particular product and populate et_entityset.
Next we will redefine and implement method: PRODUCTHEADERDAT_GET_ENTITY to get product details related to particular product using below
URL
http://system:hostnumber/sap/opu/odata/sap/ZEPM_MODEL_ODATA_SRV/ProductHeaderdataSet(‘HT-1000’)
Also let’s understand the difference between association/navigation and $expand. In short, it is as below,
Association/Navigatio Give me http://services.odata.org/OData/OData.svc/Categories(1)/Products?$format=json
n associated
(dependent)
entity/entities
using
Navigation
property
using
Navigation
property
you can also refer this nice blog Implementing Expand Entity/Entity Set by Srikanth Gajula
Scenario
We will read Sales order, items and product data from Enterprise Procurement Model (EPM). This is the pictorial representation of sales order, items and
product with their association.
We will use below BAPIs to get the Sales Order, Items and Product data in DPC_EXT class methods.
● BAPI_EPM_SO_GET_LIST
● BAPI_EPM_SO_GET_DETAIL
● BAPI_EPM_PRODUCT_GET_DETAIL
We will code for association/navigation and data provider expand scenario and will also understand the framework expand.
Before that just look at difference between Data provider expand and framework expand
As this is handled by framework, same logic may In some cases, this provides better
be called multiple times in loop resulting in poor performance depending on how the code is
performance implemented
Procedure
Create entity SalesOrder by importing DDIC structure as shown below. Please note that Entity set will be created by
default if the check box “Create Default Entity Set” is checked.
Repeat the process for entities SalesOrderItem and Product. End result will be as displayed below.
Now let’s create association, navigation etc. By using Create Association wizard, it is just 3 steps as displayed below. This will create Navigation
property, Association set etc.
Create association between entities SalesOrder and SalesOrderItem with navigation property as OrderToItems.
On similar lines, create association between entities SalesOrderItem and Product with navigation property as ItemToProduct.
Please note that we do not have referential constraints created between SalesOrderItem and Product.
In this section, we will redefine methods in DPC_EXT class. Please note that code provided in this blog is in simplest form. You may need to consider
proper error handling and other best practices while writing the code.
Association/Navigation
First we will implement logic in method SALESORDERSET_GET_ENTITYSET by redefining it.
We will use below execution URI in Gateway Client (Transaction /IWFND/GW_CLIENT) to check the response payload.
/sap/opu/odata/sap/ZTEST_DP_EXPAND_SRV/SalesOrderSet
METHOD salesorderset_get_entityset.
l_max_rows-bapimaxrow = '10'.
CALL FUNCTION 'BAPI_EPM_SO_GET_LIST'
EXPORTING
max_rows = l_max_rows
TABLES
soheaderdata = lt_salesorder.
*Fill ET_ENTITYSET
ENDLOOP.
ENDMETHOD.
Redefine method SALESORDERSET_GET_ENTITY as below and then execute with below URI
/sap/opu/odata/sap/ZTEST_DP_EXPAND_SRV/SalesOrderSet(‘500000009’)
METHOD salesorderset_get_entity.
lv_soid = ls_key_tab-value.
EXPORTING
input = lv_soid
IMPORTING
output = lv_soid.
EXPORTING
so_id = lv_soid
IMPORTING
headerdata = ls_salesorder.
*Fill ER_ENTITY
ENDMETHOD.
/sap/opu/odata/sap/ZTEST_DP_EXPAND_SRV/SalesOrderSet(‘500000008’)/OrderToItems
METHOD salesorderitemse_get_entityset.
DATA: ls_salesorder TYPE bapi_epm_so_header,
lv_soid = ls_key_tab-value.
EXPORTING
input = lv_soid
IMPORTING
output = lv_soid.
EXPORTING
so_id = lv_soid
IMPORTING
headerdata = ls_salesorder
TABLES
itemdata = lt_itemdata.
ENDLOOP.
ENDMETHOD.
Notice that we used navigation property OrderToItems to get the associated entities.
Framework expand
By executing below URI, it will call framework expand by default.
/sap/opu/odata/sap/ZTEST_DP_EXPAND_SRV/SalesOrderSet?$expand=OrderToItems
This will give you performance statistics for OData request. For more information, refer Some new features in SAP NW Gateway 2.0 SP08
If we execute URI /sap/opu/odata/sap/ZTEST_DP_EXPAND_SRV/SalesOrderSet(‘500000009’)?$expand=OrderToItems
/sap/opu/odata/sap/ZTEST_DP_EXPAND_SRV/SalesOrderSet(‘500000000′)/OrderToItems(SoId=’0500000000′,SoItemPos=’0000000010’)
Let’s implement SALESORDERITEMSE_GET_ENTITY so that we can read data for above URI as
METHOD salesorderitemse_get_entity.
lv_soid = ls_key_tab-value.
lv_soitempos = ls_key_tab-value.
EXPORTING
input = lv_soid
IMPORTING
output = lv_soid.
EXPORTING
input = lv_soitempos
IMPORTING
output = lv_soitempos.
EXPORTING
so_id = lv_soid
IMPORTING
headerdata = ls_salesorder
TABLES
itemdata = lt_itemdata.
so_item_pos = lv_soitempos.
IF sy-subrc = 0.
ENDIF.
ENDMETHOD.
Execution URI –
/sap/opu/odata/sap/ZTEST_DP_EXPAND_SRV/SalesOrderSet(‘500000001′)/OrderToItems(SoId=’500000001′,SoItemPos=’0000000010’)/ItemToProduc
t
METHOD productset_get_entity.
IF iv_source_name = iv_entity_name.
IF sy-subrc = 0.
lv_product_id = ls_key_tab-value.
CALL FUNCTION 'BAPI_EPM_PRODUCT_GET_DETAIL'
EXPORTING
product_id = lv_product_id
IMPORTING
headerdata = lv_product_header.
ENDIF.
ELSE.
IF sy-subrc EQ 0.
CASE ls_navigation-nav_prop.
WHEN 'OrderToItems'.
CASE ls_key_tab-name.
WHEN 'SoId'.
lv_soid = ls_key_tab-value.
WHEN 'SoItemPos'.
lv_soitempos = ls_key_tab-value.
WHEN OTHERS.
ENDCASE.
ENDLOOP.
ENDCASE.
ENDIF.
ENDIF.
EXPORTING
input = lv_soid
IMPORTING
output = lv_soid.
EXPORTING
input = lv_soitempos
IMPORTING
output = lv_soitempos.
EXPORTING
so_id = lv_soid
IMPORTING
headerdata = ls_salesorder
TABLES
itemdata = lt_itemdata.
*Fill ER_ENTITY
so_item_pos = lv_soitempos.
IF sy-subrc = 0.
lv_product_id-product_id = ls_itemdata-product_id.
EXPORTING
product_id = lv_product_id
IMPORTING
headerdata = lv_product_header.
ENDIF.
ENDIF.
ENDMETHOD.
Also note that we can read product directly using URI /sap/opu/odata/sap/ZTEST_DP_EXPAND_SRV/ProductSet(‘HT-1030’)
Product details will not filled as in the navigation keys are empty because we do not have referential constraint.
/sap/opu/odata/sap/ZTEST_DP_EXPAND_SRV/SalesOrderSet(‘500000000’)/$links/OrderToItems
/sap/opu/odata/sap/ZTEST_DP_EXPAND_SRV/SalesOrderSet(‘500000009’)/$links/OrderToItems/$count
Implementing GET_EXPANDED_ENTITYSET
Let’s redefine GET_EXPANDED_ENTITYSET. With redefinition (just blank code) execute again the
URI /sap/opu/odata/sap/ZTEST_DP_EXPAND_SRV/SalesOrderSet?$expand=OrderToItems
You will not get any response as you need to implement the code yourself.
One of the important point while implementing logic is Data declaration! Based on level till which you want to expand, you need to define your internal
table having nested structure or table type.
In below code, we want to expand Sales Order and its items. Hence the expand technical clause will be ORDERTOITEMS.
METHOD /iwbep/if_mgw_appl_srv_runtime~get_expanded_entityset.
DATA: BEGIN OF t_expand_so.
END OF t_expand_so.
l_max_rows-bapimaxrow = '10'.
EXPORTING
max_rows = l_max_rows
TABLES
soheaderdata = lt_salesorder
soitemdata = lt_itemdata.
CLEAR: ls_item.
ENDLOOP.data
APPEND ls_expand_so TO lt_expand_so.
CLEAR: ls_expand_so.
ENDLOOP.
* Fill EE_ENTITYSET
copy_data_to_ref(
EXPORTING
is_data = lt_expand_so
CHANGING
cr_data = er_entityset ).
ENDMETHOD.
Now we will try to expand to one level more i.e. we will expand sales order, its items and product of each item. In this case the expand technical clause
will be ORDERTOITEMS/ITEMTOPRODUCT.
METHOD /iwbep/if_mgw_appl_srv_runtime~get_expanded_entityset.
END OF t_orderitems.
END OF t_expand_so.
l_max_rows-bapimaxrow = '10'.
EXPORTING
max_rows = l_max_rows
TABLES
soheaderdata = lt_salesorder
soitemdata = lt_itemdata.
lv_product_id = ls_itemdata-product_id.
EXPORTING
product_id = lv_product_id
IMPORTING
headerdata = ls_product_header.
CLEAR: ls_item.
ENDLOOP.
ENDLOOP.
* Fill EE_ENTITYSET
copy_data_to_ref(
EXPORTING
is_data = lt_expand_so
CHANGING
cr_data = er_entityset ).
ENDMETHOD.
Implementing GET_EXPANDED_ENTITY
Let’s implement GET_EXPANDED_ENTITY.
Below is the query to execute and code to for implementation.
/sap/opu/odata/sap/ZTEST_DP_EXPAND_SRV/SalesOrderSet(‘500000005’)?$expand=OrderToItems/ItemToProduct
METHOD /iwbep/if_mgw_appl_srv_runtime~get_expanded_entity.
END OF t_orderitems.
END OF t_expand_so.
*Get the key property values and Read Sales Order and Item data
lv_soid = ls_key_tab-value.
EXPORTING
input = lv_soid
IMPORTING
output = lv_soid.
EXPORTING
so_id = lv_soid
IMPORTING
headerdata = ls_salesorder
TABLES
itemdata = lt_itemdata.
* Data processing logic
lv_product_id = ls_itemdata-product_id.
EXPORTING
product_id = lv_product_id
IMPORTING
headerdata = ls_product_header.
ENDLOOP.
* Fill ER_ENTITY
copy_data_to_ref(
EXPORTING
is_data = ls_expand_so
CHANGING
cr_data = er_entity ).
ENDMETHOD.
Important points to be considered while coding for association/navigation and data provider $expand,
● Use of navigation path and navigation key. Entities can be directly accessed or via navigation property. Code for both scenario
using navigation path and navigation keys.
● Data declaration of internal tables in case of data provider expand. Understand the relations between entities. while declaring
internal table, use navigation property name to address dependent entity structure. It should be same. Check below data
declaration.
END OF t_orderitems.
END OF t_expand.
ls_expanded_clause_items = 'ORDERTOITEMS/ITEMTOPRODUCT'.
ls_expanded_clause_partners = 'ORDERTOPARTNERS/PARTNERTOADDRESS'.
● We have a table in which it contains customer information, two or more customers' information have to be
approved at once. In this scenario to approve each customer information we will use Function Import.
● In OData every operation needs a separate method to trigger for function import we have method called
‘Execute_action’
Example-2
LINK-https://saplearners.com/function-import-in-sap-odata-service/
1. Tables involved: VBAK(Sales Document: Header Data), VBAP(Sales Document: Item Data).
2. Create a Project in SEGW(SAP Gateway Service Builder).
3. Import the DDIC Structure: VBAK(Sales Document: Header Data).
8. *--------------------------------------------------------------------*
9. * Deep Structure
10.*--------------------------------------------------------------------*
11. TYPES
12.: BEGIN OF ty_deep_entity,
13. vbeln TYPE vbeln_va, "Sales Document
14. erdat TYPE erdat, "Date on which the record was created
15. erzet TYPE erzet, "Entry time
16. ernam TYPE ernam, "Name of Person who Created the Object
17. vkorg TYPE vkorg, "Sales Organization
18.* Navigation property name should be used otherwise empty records will be shown
19. headertoitem TYPE TABLE OF ts_sales_item_data WITH DEFAULT KEY,
20. END OF ty_deep_entity.
*--------------------------------------------------------------------*
N.B:
The navigation property name should be used in case of a deep entity like shown in the image above
otherwise, empty records will be returned.
Do not regenerate the service before taking the backup as it will delete all the custom structures.
Just redefine the basic methods: *GET_ENTITY & *GET_ENTITYSET of the entities for easy
troubleshooting. No need to write any code within the methods. The $expand keyword will call only
the GET_EXPANDED_ENTITYSET method.
21.Go to the ZCL_ZGW_PRACTICE006_DPC_EXT class & redefine the
method: GET_EXPANDED_ENTITYSET.
ENDMETHOD.
70.Go to the TCODE: /N/IWFND/MAINT_SERVICE & REGISTER the service by providing the service name &
the Alias name(Central Hub Only).
71.Go to the TCODE: /N/IWFND/GW_CLIENT for testing the service. Enter the below URI in the Request
URI section.
/sap/opu/odata/sap/ZGW_PRACTICE006_SRV/Sales_Header_DataSet?$expand=HeaderToItem&$forma
t=json
72.Output:
Page | 95