This blog is meant as an introduction of a series of blogs in which I will explain the use of the new SAP Gateway V4 framework.

It is meant for those readers that must create OData V4 series now and that cannot wait until an end-2-end support for OData V4 will be available through the new ABAP programming model.

Before starting code based OData V4 development you should check my blog OData service development options where I outline in more detail what the recommended options for OData development are right now.

Updates

  • 13.12.2017 – added link to the first how to guide and the blog that explains the OData service devlopment options in more detail

Table of contents

This blog is part of blog series about OData V4 code based development

OData V4 code based implementation – Overview

OData V4 code based implementation I (basic interface, read access)

OData V4 code based implementation I (basic interface, create&update)

Source Code

Data provider class – zcl_e2e001_odata_v4_so_data

Model provider class – zcl_e2e001_odata_v4_so_model

Exception class – zcx_e2e001_odata_v4_so

Interface – zif_e2e001_odata_v4_so_types

Consumption view – sales order – ze2e001_c_salesorder

Consumption view sales order items – ze2e001_c_salesorderitem

Interface view – ze2e001_i_salesorderitem_e

What’s new in the protocol?

The main paradigm: Reduction of data

The main paradigm of the OData V4 paradigm is the reduction of data. This reduction is achieved through a more powerful query language and a new optimized JSON protocol. At the same time it is possible to leverage richter metadata as compared to OData V2.

New JSON format

The OData V4 protocol comes with a very lean JSON procol. The response payload now basically only contains name value pairs. The metadata has been reduced to a a single line

"@odata.context" : "$metadata#SalesOrder/$entity"

as opposed to the more richer metadata information in the V2 response payload, both highlighted in blue in the following figure.

Slide1 1 2996261

Cross service references

Cross service navigation enables inter communication of services. With this, navigation properties of entities of one service can reach entities of another service in a service group. With the support of cross service navigation several requirements of SAP Fiori like applications can be addressed.

1.) The rich metadata can be leveraged but at the same time not the complete data model has to be loaded at startup time of an application. There is rather the option to have a lazy loading of parts of a service model on demand.

2.) Services can be reused more easily since services can be partioned without the loss of navigation.

Examples of such services that can be reused in various SAP Fiori applications are Users, Attachments, Conditions, Addresses, …

Please note:

Cross service references are only possible within one service group.

If a request like the following is issued:

/SalesOrderItems(SalesOrder='500000000', SalesOrderItem='10')/_Product

one would receive a response like the following where it is indicated via the @odata.context annotation that this response stems from another service.

{ "@odata.context" : "../../sap/Product/0001/$metadata#Product/$entity", "value" : [ { "Product" : "HT-1000", "Currency" : "EUR", ... } ] } 

Support for Any and All

New is the support of the query options any and all.

With these it is now possible to find all sales orders where at least one of the items contains a particular product

/SalesOrders?$filter = _Item/any(d:d/Product eq 'HT-1007')

or it is possible to find all sales orders where every item has a price greater than $100

/SalesOrders?$filter = _Item/all(d:d/Price ge 100)

Filter on expanded result sets

New in OData V4 is the option for filtering on each level of an expanded enttiy set. In the following figure you see a request that

  1. reads all business partners that are located in ‘Walldorf’
  2. reads all sales orders of those business partners where the gross amount exceeds 1100 Euro
  3. reads only those items that contain the product HT-1041.

Slide3 5591914

What’s new in the framework?

Advanced, intermediate and basic interfaces

The API that is used to develop OData V4 services has significantly changed compared to the API that is used to develop OData V2 services.

When you implement the methods of the basic interface you will get a working OData V4 service that will satisfy most requests. Complex requests such as $expand are then handled by the framework that will call the methods for the basic interface in the correct order.

The mplementation of the intermediate or advanced interface should however also be taken into account if your service implementation would be able to handle specific requests such as specific $expand or navigation calls more efficient than by calling the methods of the basic interface recursively.

 Name  Purpose
/IWBEP/IF_V4_DP_BASIC
  • Methods provide basic functionality
  • (Create, Update, Delete, Navigation, …)
  • When being implemented à Working OData service supporting most requests
 /IWBEP/IF_V4_DP_INTERMEDIATE
  •  Medium complex functionality
  • eTag handling, PATCH, $expand
  • Contains generic calls to other (especially the basic) interfaces
 /IWBEP/IF_V4_DP_ADVANCED
  • Always called first by the framework
  • Contains generic calls to the other (especially the basic) interfaces
  • Will for example be overwritten by the new RESTful ABAP Programming model (planned)
 /IWBEP/IF_V4_DP_BATCH
  • $batch. Generic $batch and changeset
 /IWBEP/IF_V4_DP_PROCESS_STEPS
  • Transaction and lifecycle handling

io_request and io_response

All interface methods have an import parameter called io_request. It can be used to retrieve all information you need to handle the request in your service implemenation.

A UPDATE_ENTITY method for example will have the following methods

  • GET_BUSI_DATA to retrieve entity data from the request, for example the payload of the incoming request.
  • GET_ENTITY_SET to retrieve the entity set of the processed entity. So we can switch to entity set specific methods

The corresponding parameter ip_response is used to return business data to the SAP Gateway framework and to tell the framework which processing steps the service implementation has handled iself (see todo and done flags below).

Generic framework support – example $expand

As already mentioned you will get a working OData V4 service by only implementing the methods of the basic interface.If a client calls the following URL:

GET .../ze2e001_salesorder/0001/SalesOrder('500000000')?$select=Salesorder,Customer& $expand=_Item($select=Salesorderitem,Product,Grossamountintransaccurrency,Transactioncurrency)

the SAP Gateway framework will call the following basic methods in your service implementation:

 # Method call Purpose
 1  …_BASIC~READ_ENTITY This method will read the data of the sales order header
 2  …_BASIC~READ_REF_TARGET_KEY_DATA This method will read the key fields of the items that can be used by the READ_ENTITY_LIST method as a $filter statement
 3  …_BASIC~READ_ENTITY_LIST This method reads the items.

and would finally return the following data

{ "@odata.context" : "$metadata#SalesOrder(Salesorder,Customer,_Item(Salesorderitem,Product,Grossamountintransaccurrency,Transactioncurrency,Salesorder))/$entity", "Salesorder" : "500000000", "Customer" : "100000000", "_Item" : [ { "Salesorder" : "500000000", "Salesorderitem" : "10", "Product" : "HT-1000", "Transactioncurrency" : "EUR", "Grossamountintransaccurrency" : 1137.64 }, { "Salesorder" : "500000000", "Salesorderitem" : "20", "Product" : "HT-1001", "Transactioncurrency" : "EUR", "Grossamountintransaccurrency" : 2972.62 }, ... ] }

Please note:
With OData V4 now query options are supported on all levels of an $expand statement.

ToDo and Done-Flags

The SAP Gateway V4 framework has introduced so called ToDo-Flags which provide a hint for the application developer what his implemenations has to do. Depending ont the query options that have been used in the request you will get simple list with boolean values for the following flags:

deltatoken, select, filter, skip, orderby, skiptoken, search, top, …

Done-Flags confirm that the response fits to the request. They allow the application developer to inform the framework to handle feature generically e.g., $top, $skip, and $select. Using such flags also allows an implementation tobe compatible in the future. Instead of a wrong result an exception will be raised if a done flag is not set.

The list of todo and done flags will vary depending on the method which is called. (READ; READ_LIST, CREATE, …)

For a simple GET request with a $filter query option:

…/SalesOrder?$filter=Customer eq ‚SAP‘

a service implementation would have to look like as follows.

At the beginning of our service implementation we have to check whether we have to handle the filter option. For this we call the method io_request->get_todos. Then we have to check whether the flag ls_todo_list-process-filter is set. If yes, the filter string is requested via the method io_request->get_filter_osql_where_clause and the flag that we have handled the filter query option is set in the structure ls_done_list. This information is at the end sent back to the framework via the method io_response->set_is_done that takes the done-list as a parameter.

io_request->get_todos( importing es_todo_list = ls_todo_list ). ... if ls_todo_list-process-filter = abap_true. io_request->get_filter_osql_where_clause( importing ev_osql_where_clause = lv_where_clause ). ls_done_list-filter = abap_true. endif. ... " Report list of request options handled by application io_response->set_is_done( ls_done_list ).