Technical Articles
OData Versioning
OData has become an inevitable topic for any SAP ABAP developer. I am sure most of us are involved in an OData development one way or the other.
Let’s discuss versioning, one of the advanced concepts of OData.
Note – I are working with OData version 2.0 in this article.
Motivation
Ever wondered if the business logic of an OData can be modified and activated as a different version without effecting the current business logic? I did and some of the scenarios I have faced are
Front-end team is not yet ready for the change but I would like to keep going.
I was working on an API and wanted to roll-out version 2 but wanted to maintain an active version 1 as well.
What kind of changes?
Mostly breaking changes that will not go well with the front-end implementation of the OData. Some of them are
- Adding a mandatory filter to the OData the front-end has not implemented
- New validation on the back-end that front-end is not adhering to
- Changing the key fields
- Deleting a field that is utilized by the front-end
Metadata based categorizing of OData versioning
These changes can be broadly categorized into 2 types based on the metadata
- OData versioning not including metadata change
- OData versioning including metadata change
Let’s discuss each one with an example.
Example OData
I have created an OData with the well known SAP’s FLIGHT test data.
- Using SEGW transaction create an OData project ‘ZODATA_VERSIONING’.
- From the context menu of ‘Data Model’ create entity type ‘AvailableFlight’ and generate the OData project.
- Change the ‘Technical Service Name’ to ‘FLIGHT’ and take a note of the Service Version 1. This is the default version of the OData ‘FLIGHT’ .As displayed below new Model Provider and Data Provider Classes are generated.
- Using transaction code ‘/IWBEP/REG_MODEL’ we can verify that the ‘Technical Model Name’, ‘Model Version’, ‘Model Provider Class’ are registered in the back-end system. We can verify the same and ‘/IWBEP/REG_SERVICE’ respectively.
- The model is registered stand alone.
- Using transaction code /IWBEP/REG_SERVICE we can verify that the ‘Technical Service Name’, ‘Service Version’, ‘Data Provider Class’ are registered in the back-end system.
- While the model is registered stand alone the service is registered in combination with the model.
- Now maintain the service in the Gateway system using T-CODE ‘/IWFND/MAINT_SERVICE’. Please note the service version ‘1’ and the Model version ‘1’ which were retrieved from the FLIGHT Technical Service Registration version 1 in the back-end.
- OData service ‘FLIGHT’ with version 1 on both backend and the Gateway is maintained successfully.
- The OData can be accessed via URL ‘/sap/opu/odata/sap/FLIGHT/AvailableFlightSet?$format=json’.
- This is nothing but the default version 1 of the OData.
- Adding ‘?v=1’ to the URL after the OData name provides the same result.
OData versioning not including metadata change
Let’s modify the OData logic without modifying the metadata.
Let’s say the requirement is to add a mandatory filter ‘CONNID’ but only to the new version.
- Copy the respective data provider class(*DPC_EXT) class as below and add the required mandatory filter.
-
METHOD AVAILABLEFLIGHTS_GET_ENTITYSET. DATA: LR_CONNID TYPE RANGE OF S_CONN_ID. DATA(LT_SO) = VALUE #( IT_FILTER_SELECT_OPTIONS[ PROPERTY = 'CONNID' ]-SELECT_OPTIONS OPTIONAL ). IF LT_SO IS INITIAL."Return no data if CONNID filter is blank. RETURN. ENDIF. SELECT * FROM SFLIGHT INTO TABLE @DATA(LT_SFLIGHT) WHERE CONNID IN @LT_SO. ET_ENTITYSET = CORRESPONDING #( LT_SFLIGHT ). ENDMETHOD.
- Register the new data provider class using transaction code ‘/IWBEP/REG_SERVICE’.
- Make sure to select OData name as ‘FLIGHT’, same as the previous ‘Technical Service Name’ and version 2.
- Add the new data provider class as below and save.
- Click on ‘Assign Model’ button and assign the old model provider class and version 1.
- Maintain the service in the Gateway using T-CODE ‘/IWFND/MAINT_SERVICE’.
- Please note the service version ‘2’ and the Model version ‘1’ which are retrieved from the FLIGHT Technical Service version 2 Registration in the back-end.
- On Gateway system via T-CODE ‘/IWFND/MAINT_SERVICE’, 2 versions of the OData FLIGHT are maintained.
- Both versions with different business logic can be accessed now.
- Accessing data via the version 1 or default version of the OData with no mandatory filter.
- Version 2 of the OData does not return any data unless mandatory filter is added to the query.
- Accessing data via the version 1 or default version of the OData with no mandatory filter.
- Make sure to select OData name as ‘FLIGHT’, same as the previous ‘Technical Service Name’ and version 2.
OData versioning including metadata change
Now the new requirement is to add version 3 of FLIGHT OData with no Price field and add the mandatory CONNID filter as per version 2 to ‘AvailableFlight’ entity.
For the metadata change we need to create a new version of the Model Provider Class. But we need to do this without loosing SAP Gateway Service Builder(SEGW) tool assistance.
- Copy the existing project via the SEGW T-CODE.
- Remove the ‘PRICE’ field from the OData ‘AvailableFlight’ entity.
- Generate the OData and change the ‘Technical Service Name’ to ‘FLIGHT’ and the ‘Service Version’ to 3.
- Add the mandatory filter logic as required in the data provider class ‘ZCL_ZODATA_VERSIONING3_DPC_EXT’. This code is same as version 2 of the OData.
-
METHOD AVAILABLEFLIGHTS_GET_ENTITYSET. DATA: LR_CONNID TYPE RANGE OF S_CONN_ID. DATA(LT_SO) = VALUE #( IT_FILTER_SELECT_OPTIONS[ PROPERTY = 'CONNID' ]-SELECT_OPTIONS OPTIONAL ). IF LT_SO IS INITIAL."Return no data if CONNID filter is blank. RETURN. ENDIF. SELECT * FROM SFLIGHT INTO TABLE @DATA(LT_SFLIGHT) WHERE CONNID IN @LT_SO. ET_ENTITYSET = CORRESPONDING #( LT_SFLIGHT ). ENDMETHOD.
-
- Now maintain the service in the Gateway using T-CODE ‘/IWFND/MAINT_SERVICE’. Please note the service version ‘3’ and the Model version ‘1’ which are retrieved from the FLIGHT Technical Service version 3 registered in the back-end.
- All 3 versions of the OData SFLIGHT are registered on the Gateway system.
- Query the version 3 of the OData with the mandatory filter and the deleted PRICE field.
In this article, you learned
- Registering the OData Technical Model Name in the back-end.
- Registering the OData Technical Service Name in the back-end.
- Maintaining the OData Service in the Gateway.
- Registering different versions of OData Technical Model Name and Technical Service Name in the backend.
- Maintaining different versions of OData Service in the Gateway.
Further reading
- You can get a overview of ABAP OData from ABAP OData
- Check ABAP Profiling for performance analysis of OData or general ABAP.
Feel free to check ABAP Profiling for performance analysis.
Good overview and this is good to keep in the back of your head.
In a use case where it is a matter of software logistics between backend and frontend, I would prefer to sync between both parties and align transports. If it would be a matter of really going 'API based', where we do not directly control the consumers, we could utilize your mentioned principles and techniques. But if the latter is the case, I wonder what the advantages of the backend techniques are in comparison to the API Management techniques.
Transporting both FE(front-end) and BE(back-end) together is what I support and follow as well. But my point is more on keeping the team busy in dev system.
That is,
That is where BE can create version 2 and be done with the work. When FE is ready, FE can integrate with version 2, BE can deactivate version 1 and move both FE and BE changes to next environment.
I see. Another good topic to mention is that you can create seperate Gateway projects with each their entities, to finally embed the entities under a main endpoint, allowing you to transport each DPC class independently
E.g.
Sorry to digress from the main topic, but how can we embed one GW project into another GW project ?
Ram Bandla Thanks for this interesting article on versions. One question, can the Front End use version 2 as well by adding the suffix ;v=2 to the OData service url ?
Hi Titus Thomas
Yes, we can. That is the benefit of this approach. The GW client is acting as a browser. If you try it via browser you get the same result. Of course you need right access to the oData both for GW client and browser.
Ram
Thanks for sharing, very interesting subject!
Some questions. To be honest, it lost me at "copy the respective data provider class(*DPC_EXT) class". Is this actually a good idea? I always thought that we should just leave SEGW do its own thing and take care of all the DPC etc. generation. (For the same reason, I always put only minimum code in the ...DPC_EXT methods.)
Also, it seems that the goal is not to keep two versions indefinitely but actually reconcile them eventually into a single service. Is that correct? Wouldn't having multiple projects / copied classes present some challenges when the time comes to combine everything together?
I'm familiar with the challenges of "back end works ahead of front end" but the way we resolved this in the past was to use a temporary SEGW project or simply work on a class in isolation as much as possible and then plug it into SEGW project when the other side was ready for implementation. These are not ideal solutions either, of course, so I'm very interested in better development management tools.
Thank you!
P.S. It's spelled "OData". Thought I'd point this out. 🙂
Thanks Jelena Perfiljeva for the comment.
Versioning can be achieved via copying *DPC_EXT class or copying the SEGW project itself.
Keeping minimum code in *DPC_EXT is what I follow and suggest.
OData corrected.
Ram
The topic service versioning is nicely explained.
I would have the following remarks:
Adding ‘?v=1’ to the URL after the OData name provides the same result.
should read as follows
Adding ‘;v=1’ to the URL after the OData name provides the same result.
(Though we have developed service versioning ;-))
From a technical point of view you use two different URL's when accessing your OData services either by adding a version ;v=2 or by changing the service name.
/sap/opu/odata/sap/FLIGHT;v=2/AvailableFlightSet
/sap/opu/odata/sap/FLIGHT2/AvailableFlightSet
Kind regards,
Andre