NW ABAP Gateway (OData), ABAP RESTful Application Programming Model, SAP Gateway, SAP BTP

Service Consumption Model 2 for OData Client Proxy

Introduction

This blog post will describe the Service Consumption Model 2 for OData. I will describe its benefits, provide a description of the model, take a look at the OData Client Proxy at runtime and also dive into the ABAP cross trace integration as well.

If you want to receive or send data to an OData V2 or V4 service within SAP BTP, ABAP Environment or SAP S/4HANA ABAP Environment, you can use the “Service Consumption Model 2” for OData. As of 2311, it is also possible to consume also Complex Types, Complex Collection, Action (bound) and Functions (bound). Of course, the consumption of EntityTypes and EntitySets is also possible.

In addition you get fewer generated artifacts. The persistence of the underlying model has changed completely. In the first version you get an abstract CDS View for each EntityType. For large services with multiple EntityTypes, you could end up with a lot of artifacts. Now only one class with type definitions is created.

Many artifacts in the first version of the Service Consumption Model for OData

Use case

If you have an SAP BTP, ABAP Environment or SAP S/4HANA ABAP Environment system you can use the Service Consumption Model for OData. From here you can connect to a Cloud or an On premise system.

Scenario

In my scenario I am consuming the /dmo/travel service from another Cloud system. A call to the EntitySet Travel returns the following data:

GET /sap/opu/odata4/dmo/api_travel_u_v4/srvd_a2x/dmo/travel_u/0001/Travel
{
    "@odata.context": "$metadata#Travel",
    "@odata.metadataEtag": "W/\"20230919122803\"",
    "@odata.nextLink": "/sap/opu/odata4/dmo/api_travel_u_v4/srvd_a2x/dmo/travel_u/0001/Travel?$skiptoken=100",
    "value": [
        {
            "@odata.etag": "W/\"SADL-202305191948080000000C~20230519194808.0000000\"",
            "AgencyID": "70041",
            "AgencyName": "Maxitrip",
            "BeginDate": "2023-06-03",
            "BookingFee": 40.0,
            "CurrencyCode": "USD",
            "CustomerID": "594",
            "CustomerName": "Ryan",
            "EndDate": "2024-03-31",
            "LastChangedAt": "2023-05-19T19:48:08Z",
            "Memo": "Vacation",
            "SAP__Messages": [
            ],
            "Status": "P",
            "StatusText": "Planned",
            "TotalPrice": 1889.0,
            "TravelID": "1"
        },
        ...

Service Consumption Model 2 for OData

As of 1808, you can use the Service Consumption Model for OData. From 2311 on, the wizard in the ADT will automatically uses the new version.

Wizard

Select File -> New -> Service Consumption Model and choose OData as Consumption mode in ADT.

The consumption system requires a representation of the remote service. This knowledge is used to create the URL, write and read the JSON form the HTTP requests and responses. Therefore, the wizard needs the EDMX file (a service metadata document that describes the data model exposed by the service as an HTTP endpoint. OData uses EDMX as the format for this description) of the remote service. You can get this by adding $metadata to the end of the service document, in my case it is the following URL:

GET /sap/opu/odata4/dmo/api_travel_u_v4/srvd_a2x/dmo/travel_u/0001/$metadata

I saved this file on my computer to use this in the wizard. In addition I chose ZBG_TRAVEL_SCM as the class name. This class is the model representation and will contain all the types for my client.

EDMX import and class name

The EDMX file is analyzed beforehand to identify potential problems. It may be that certain artifacts are ignored, for example, parts of them violate the OData metadata rules. In my case, the EDMX file describes several EntityTypes, EntitySets, a complex type and a Bound action.

Analyse of EDMX file

The next step looks for the OptimisticConcurrency annotation of the Org.OData.Core.V1 vocabulary. If an EntitySet has this annotation, modifying requests must use an etag. If an EntitySet does not have this annotation, you can select the ETag support here.

ETag support

Finally, I get the Service Consumption Model 2 for OData:

Service Consumption Model 2 for OData

In the upper left section, you can see the model class that describes the /dmo/travel service. I use the code snippets from Travel EntitySet and Read list as operation, as a starting point for my OData client.

Model class

The model class has the following parts:

  1. Type definitions that can be used in my client code. I use a table of zbg_travel_scm=>tys_travel_type to retrieve the travel data.
  2. To find the corresponding types, constants are created for EntitySets, EntityTypes, ComplexTypes, Actions and Functions. Here is the ABAP doc for the EntityType constant, including the link to the type:

3. The model definition is done in several method implementations. The types are used to define all the artifacts of the remote service. In addition a mapping between the ABAP and the EDMX name is done here. ABAP artifacts are limited to 30 characters. In EDMX they can be up to 128 characters long in camel case.

If you need to customize the result of the wizard, e.g. because you need to adapt to certain naming conventions, you can modify the source code of the generated class and adapt it to your needs.

Support for Action and Functions

To call an action or a function, structures and tables for the parameter are generated. With 2311 the ADT integration is still missing. So I can’t select a bound action, an action import, a bound function or a function import and use the code snippet from the ADT. However, the parameter structure is there and I can use it at runtime to call the operation.

Connecting to a remote service

In a cloud system I need an outbound communication scenario, an outbound service and a communication arrangement for the http connection. Tutorial: Prepare Consuming System and Service Consumption Model describes the steps to achieve this.

OData Client Proxy at Runtime

For my client, I have used the code snippet from ADT (right hand side in the Service Consumption Model) to read the EntitySet Travel. The client code uses the type from the model. I changed three things after that:

  1. Establish the HTTP connection using the communication scenario and the outbound service.
  2. Change the IV_RELATIVE_SERVICE_ROOT parameter of the factory (line 56 in the screenshot below) to point to the OData service. This path depends on the communication system.
  3. Add the out->write() statement at the end (line 81).

And voila, the GET request and transformation of the JSON response to ABAP was done for me.

OData Client Proxy at Runtime

Conclusion

The Service Consumption Model 2 for OData supports more OData features and generates fewer artifacts. The model class can be adapted to the my needs, if the result of the wizard does not exceed my expectations. It would be great to get feedback from you if this is indeed the case to further improve the wizard.

Tip for developers

Sometimes it is good to know what the OData Client Proxy does under the hood. Especially connecting to another system can be tricky. Therefore is the OData Client Proxy part of the ABAP Cross trace (ADT Windows -> Show View -> ABAP Cross trace):

Activate OData Client Proxy in cross trace

In the trace result you can see for example the response payload and the CSRF token fetch:

http payload in cross trace