OData service development with SAP Gateway using CDS via Referenced Data Sources
Updates
- 02.06.2016 Added link to blog that describes how to implement updates
- 09.06.2016 Added section how to create the CDS view used for generating an OData service via Referenced Data Sources
- 26.04.2017 Replaced screen shots that now show the latest version of ADT tools
Introduction
In a previous blog OData service development with SAP Gateway – code-based service development – Part I I described how to implement as basic OData Service using code based implementation.
Since the recommended development approach as of SAP NetWeaver 750 is to use CDS views I would like to show how a service having the same capabilities as the service in the blog mentioned above can be generated based on CDS views.
It will turn out that from a development perspective in the ABAP stack this is much less effort if appropriate CDS views are in place and if your backend system is based on SAP NetWeaver 750.
If however no appropriate CDS view is in place instead of having the effort of developing an OData service via code based implementation you would have the effort to develop the appropriate DDL source code.
Prerequisites
As a prerequisite we are using a consumption view ZSEPM_C_SALESORDER_<#> since it is not good practice to access core CDS views directly.
This consumption view is then also not annotated as an analytical view as the underlying core CDS view SEPM_I_SALESORDER_E.
How to create this consumption view ZSEPM_C_SALESORDER_<#> is shown in the following.
If you are using a system for a SAP CodeJam you can skip this step or create your own CDS view by replacing the hash tag <#> with your group number.
Creating the consumption view
Please note:
The creation of a consumption view is only necessary if you want to follow this how-to-guide on your own system or if you want to use your own CDS view.
For a SAP CodeJam or other SAP event we will use a system where this view has already been created.
- Start the ABAP Development Tools
From the menu choose New –> ABAP Project
Select the system (here A4H) from the list of system connections and choose Next
- In the “Connection Settings” screen press Next
- Enter your credentials
- Right click on your system connection and select New –> Other …
Select Data Definition and press Next
- Enter the following details for the new DDL source and press Finish
Package: $TMP
Name: ZSEPM_C_SALESORDER_<#>
Description: SalesOrders – EPM Demo Data
Cut and paste the source code and press the Activate button. This will create the CDS view that we will use in this how to guide
You will have to adapt the name of the SQL view, the name of the CDS view and you should maintain the annotation for @EndUserText.label so that it contains your group number.
DDL source code
@AbapCatalog.sqlViewName: 'ZSEPM_ISOE_<#>'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'SalesOrders – EPM Demo Data'
define view Zsepm_C_Salesorder_<#>
as select from SEPM_I_SalesOrder_E
{
@ObjectModel.text.association: '_Text'
key SalesOrder,
@ObjectModel.readOnly: true
CreationDateTime,
@ObjectModel.readOnly: true
LastChangedDateTime,
@ObjectModel.readOnly: true
IsCreatedByBusinessPartner,
@ObjectModel.readOnly: true
IsLastChangedByBusinessPartner,
@ObjectModel.readOnly: true
Customer,
@ObjectModel.readOnly: true
TransactionCurrency,
@ObjectModel.readOnly: true
GrossAmountInTransacCurrency,
@ObjectModel.readOnly: true
NetAmountInTransactionCurrency,
@ObjectModel.readOnly: true
TaxAmountInTransactionCurrency,
@ObjectModel.readOnly: true
SalesOrderLifeCycleStatus,
@ObjectModel.readOnly: true
SalesOrderBillingStatus,
@ObjectModel.readOnly: true
SalesOrderDeliveryStatus,
@ObjectModel.readOnly: true
SalesOrderOverallStatus,
@ObjectModel.readOnly: true
Opportunity,
/* Associations */
_Customer,
_Item,
_Text
}
Generating an OData service via Referenced Data Source
- We first have to start with creating a new Service Builder project called ZE2E100_<#>_2 since the project in the previous blog mentioned above was called ZE2E100_<#>
Note: Replace <#> with your group number - Right click on the folder Data Model.Choose Reference –> Modeled Data Source Reference from the context menu
- The Reference Data Source Wizard opens.
On the first screen choose:
CDS Core Data Services for the field Modeled Data Source Type.
ZSEPM_C_SALESORDER_<#> for the field Modeled Data Source Name
- In the second window of the wizard select the following associations’_CUSTOMER and _ITEM.Please note that the cds views SEPM_I_BUSINESSPATNER_E and SEPM_I_SALESORDERITEM_E are automatically selected as well.Press Finish
- Press the Generate Runtime Objects button
- In the Model and Service Definition screen leave the default values unchanged and press Continue.
- In the Create Object Directory Entry dialogue press Local Object or enter $TMP.
- Expand the folder Service Maintenance right click on the entry GW_HUB and choose Register.
- In the Add Service dialogue enter $TMP for the package assignment or press Local Object.
- Expand the folder Service Maintenance right click on the entry GW_HUB and choose SAP Gateway Client.Press <Execute>
- Check the Service Document
It shall contain three entity sets:
- Zsepm_C_Salesorder_<#>
- SEPM_I_SalesOrderItem_E
- SEPM_I_BusinessPartner_E
- Check the metadata document by selecting <Add URI option> and select $metadata
Check the Metadata Document
Please note that the entity type ZSEPM_I_SalesOrder_EType contains:
- Two navigation properties to_Customer and to_Item
- A property SalesOrder_Text that has been generated by the SADL framework based on the annotation @ObjectModel.text.association: ‘_Text’.
Please note this property is annotated as sap:updatable=”false”;
- Now we can test the service and we will see that it supports various query options, $expand and selecting single entities out of the box.
To do so execute the following URI’s in the SAP Gateway Client (transaction /n/IWFND/GW_CLIENT):
- /sap/opu/odata/SAP/ZE2E100__2_SRV/Zsepm_C_Salesorder_?$filter=GrossAmountInTransacCurrency ge 100000&$select=SalesOrder,GrossAmountInTransacCurrency,TransactionCurrency&$format=json
- $skip and $top together with $inlinecount work out of the box as well
/sap/opu/odata/SAP/ZE2E100__2_SRV/Zsepm_C_Salesorder_?$filter=GrossAmountInTransacCurrency ge 100000&$select=SalesOrder,GrossAmountInTransacCurrency,TransactionCurrency&$top=2&$skip=1&$inlinecount=allpages&$format=json
Please note that via &$inlinecount=allpages we retrieve the number of entries that would be returned without using $skip and $top
- Read a single entity from the list of the sales order/sap/opu/odata/SAP/ZE2E100_<#>_2_SRV/Zsepm_C_Salesorder_<#>(‘5000000<X>‘)?$format=jsonPlease note that the weird looking key stems from the fact that the CDS view is annotated as an analytical view.
- Read the list of items of a single sales order via the navigation property to_Item /sap/opu/odata/SAP/ZE2E100_<#>_2_SRV/Zsepm_C_Salesorder_<#>(‘5000000<#>‘)/to_Item?$format=json
How to implement updates in a service that has been generated using referenced data sources will be described in the following blog
Hi Andre ,
Thanks for Information !!!
Please share ur valuable suggestion .
Consider 2 User can access this Sales Order oData Service "User1" and "User2" . Now "User1" can view Sales Order of particular set of Customer like "C1" and "C2" and "User2" can view other set of Customer like "C3" and "C4".
how can we achieve like this Authorization !!!
Regards,
Jibin Joy
HI Jibin,
Use this space (comment section) only to discuss about topics directly related to the blog. Use the forum for any questions.
Regards
Krishna
Hi All,
Above Clarification has been moved
Regards,
Jibin Joy
Hi Andre,
e.g. i decide to use Gateway with the deployment option "Hub architecture with development on the server" as you described here. Will the automatic generation via an ABAP CDS View by using the annotation @OData.publish work?
I'm asking because i'm not sure whether the description here with "..SAP Gateway hub system. ..." considers both possible Hub deployment options.
BR
Eugen
Hi Andre, thanks for your blog post.
I got notified that comments weren't possible, so I wanted to check back and see if it is possible to post comments now, since there might be people who would like to give additional feedback or get questions on your blog cleared. Have a nice day!
Regards, Mynyna
Hi André,
I've followed the described steps in a SAP NetWeaver ABAP 7.50 SP5 system and can query the service. But I want to make the service subscribable. For this I've followed the steps described in Configurations on the SAP Backend System for Push Oriented Scenarios. In the MPC class I've used the following coding to set the subscribable flag for the Entity Set:
When I now call the Service via the URL "/sap/opu/odata/sap/ZSEPM_C_SALESORDER_SRV/?$format=json" I get the following result:
So you see that the Entities that should be returned for a subscribable service:
do not exist. Hope you can give some guidance.
Best regards
Gregor
Hi Gregor,
you have to enter a few more lines of coding that I have copied from the define method of /IWBEP/CL_MGW_PUSH_ABS_MODEL.
Reason is that the DEFINE method of the generated MPC class
does not call the DEFINE method of the Superclass.
So if your DEFINE method looks like this the two entity sets
NotificationCollection
SubscriptionCollection
will show up and can be called since the CRUD methods are handled by the framework for example by calling /IWBEP/IF_MGW_CORE_SRV_RUNTIME~READ_ENTITYSET in the base class /IWBEP/CL_MGW_PUSH_ABS_DATA.
Please note that the methods of the interface /IWBEP/IF_MGW_CORE_SRV_RUNTIME must not be redefined since they belong to the framework.
Only methods of the application interface /IWBEP/IF_MGW_APPL_SRV_RUNTIME may be redefined
Hi André,
I've just tested your suggestion in my system and yes it solves my issue. Thank you!
But is there a valid reason why the define method does not call it's super class?
Best regards
Gregor
Hi André,
unfortunately I've never tried the URI that I get back from the Path:
/sap/opu/odata/iwfnd/NOTIFICATIONSTORE/NotificationCollection
The Path part of the URI looks like that:
/sap/opu/odata/sap/ZMATERIALS_SRV;mo/ZDDL_MATERIALS(SAP__Origin='LOCAL',MaterialNumber='000000000000004711')
When I call this URL the following error is returned:
What changes do I have to add to the coding so that this issue does not occur?
When I use the Path:
/sap/opu/odata/sap/ZMATERIALS_SRV/ZDDL_MATERIALS('000000000000004711')
everything is just fine.
Best regards
Gregor
you could use the following URL:
/sap/opu/odata/sap/ZMATERIALS_SRV;o=LOCAL/ZDDL_MATERIALS(‘000000000000004711’)
So adding the name of the system alias of your backend after the root URL of your service.
Best Regards,
Andre
Hi André,
but shouldn't the URI in the Notification be correctly generated or evaluated by SAP Gateway? I think it's the best to raise an incident in the service marketplace anyway. What do you think?
Best regards
Gregor
Hi Gregor,
you are right. This seems to be a bug.
In my Sandbox System however it works to run the following requests:
/sap/opu/odata/sap/ZE2E100_XX_2_SRV;mo/Zsepm_C_Salesorder_Tpl(SAP__Origin='LOCAL2',SalesOrder='500000000')
/sap/opu/odata/sap/ZE2E100_XX_2_SRV;mo/Zsepm_C_Salesorder_Tpl(SAP__Origin='LOCAL',SalesOrder='500000000')
after having created a second system alias LOCAL2.
Hi, Andre.
I create oData service using cds+referenced data Source in SEGW. But flag filterable in SEGW for entity type fields is unchecked and i cant filter oData service.
How can i set flag filterable for one of field of entityType ?
Hi Alexander,
the filterable flag has no influence on the runtime of an OData service. It is just metadata information that shall inform the client whether an entity set supports the filtering of data or not.
An entity set which is based on a CDS view and that have been generated using the referenced data source approach should support filtering out out of the box.
Have you tried to filter the data using the SAP Gateway client as described above or have you just checked the flag in SEGW?
If there is still a problem please post your question in the question section or raise a customer ticket.
Best Regards,
Andre
Thanks, Andre.
I will try filtering in GW client
Hi Andre,
is it possibly to set NOT „filterable“ or NOT „sortable“ per CDS-Annotation?
That means without coding these in the define method.
Thank you in advance.
Best regards,
Timo
excellent blog andre.
Sorry Andre, I deleted my message before had a chance to read your reply. So I'm posting it again for others' benefit.
My question was whether changing a cds view (ie adding a field) would refresh the odata entity. And your answer was:
Yes, it is easy to recreate the reference in SEGW (that's why I decided to remove my original message 🙂 ). Thanks for your answer, appreciate it.
Ramin.
Wouldn't the alternative be to create the data entity manually in SEGW and associate it to the CDS view's ddic structure, instead of a Reference to CDS?
In the case of updates to the cds view then, you'd just have to drag and drop the new fields into the Service Implementation of the data entity.
I'm trying to decide which alternative is easier, less prone to errors.
Hi Ramin,
I wouldn't recommend to use the mapped data source approach. The mapped data source approach is the predecessor of the reference data source approach.
Using the reference data source approach you don't even have to regenerate the SEGW project when adding additional fields to the underlying CDS view (see also chapter 7.3.2 in our book).
Only when adding additional CDS views to the hierarchy or value helps the SEGW project has to regenerated.
The RDS approach is definitely the future proof approach.
Which release are you working on?
When working on SAP S/4HANA 1909 or later you should check out the ABAP RESTful Programming Model instead of using the RDS approach.
Kind regards,
Andre
We are on 7.5 Business Suite system, not upgraded to S4 yet.
We have a lot of mapped odata services unfortunately.
Thanks for your advice, I will let other developers in our team know.
This might be because mapped data source was introduced in 740 and RDS only in 750.
It should however be quite easy to create new RDS based services alongside to the existing services that are based on mapped data source since you just have to select the CDS views rather than having to create entity types via DDIC import and associations manually.
The $metadata documents of the new services will slightly differ though.
On the other hand you have to judge whether it is worth the effort to change existing services just for the sake of using the latest runtime implementation ;-).
When upgrading to SAP S/4HANA 2020 FSP1 you should definitly check if you would want to create RAP based services using an unmanaged implementation.
Thanks for detailed blog and your valuable contribution!
Can we make RAP based OData service subscribable, like we used to do in SEGW based OData service with SubscriptionCollection and NotificationCollection?
Dear Andre
I have been using "CDS via Referenced Data Sources" for a couple of Fiori projects now. I am quite a fan of this concept as it allows me full flexibilty for "CUD" and "A" (for Action), yet gives me a lot of "pre-built" Code for "R" (=Read).
As a Frontend i always chose a SAPUI5 Floorplan like "List-Detail" and I tried to use as much "Smart" Fields/Tables as possible to benefit from Annotations.
Altogether a perfect match!
Now I read that "CDS via Referenced Data Sources" is not upgraded to oData V4 what i very much regret.
I tried to use RAP since 1909...and was never a fan....the framework hides too much under the hood...and is not flexible.......Never understood SAP chose EML over pure ABAP....for Behavior Definition.
Not a chance that SAP is reconsidering this decision?
Thanks a lot for your message and your view about this.
Kind Regards
Paul
Hi Paul,
the decision that RAP is the new strategic programming model was taken already a few years back. And all new development in SAP S/4HANA is done using RAP and also existing services are migrated into RAP as well.
In the 1909 release RAP is still in its early phase. It becomes better and more powerfull with 2020 and nearly complete feature scope was reached with 2022.
Since you are using RDS you have already built your data model in CDS so you should be able to migrate such applications to become RAP application with either unmanaged implementation (1) or in newer SAP S/4HANA releases to a managed implementation with unmanaged save (2).
RAP also offers you the option to use the OData v4 based service binding, so that you thus can publish the same service implementation using OData V4 without changing a single line of code. However the implementation must be aware of draft. And V4 is not supported without draft together with Fiori Elements (you don't get a create button there without draft when using OData V4).
You should try to carve out the write access within your DPC_EXT CUD methods so that it can be called by either your RDS implementation in SEGW and RAP so that both services could run side by side when you want to migrate your existing RDS based implementation to use RAP in the future.
Managed with unmanaged save (2) would be the preferred option, however it requires you to send the data to the unmanaged save in such a way that it is already consistent (checked by your validations).
RAP lets you also use draft which is definitily an advnatage opposed to the SEGW based RDS implementation where draft was only available as of 751 and then only when using the Fiori Programming Model that made use of BOPF objects and which is not supported for brownfield implementations as you have it probably in your RDS projects where you call existing API's to perform the creation and update of your data.
The good news is that your existing applications based on RDS will continue to run so you can take your time to move them to RAP or just use RAP first in net new implementations.
Kind regards,
Andre
Good day Andre
Thanx a lot for your much appreciated comment. Since our company is now on Rel. 2022, I will give RAP a second chance....for new projects......yet with a little bit of regret 😉
Liebe Grüsse
Paul
You can try out our tutorials.
abap-platform-rap-workshops/rap1xx/rap100 at main · SAP-samples/abap-platform-rap-workshops (github.com)