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.