This document continues the series A Programming Model for Business Applications. If you havn´t read the first parts in the series, I recommend that you read the first three parts:
A Programming Model for Business Applications (1): Assumptions, Building Blocks, and Example App
A Programming Model for Business Applications (2): Implementing the Entity Model with CDS
A Programming Model for Business Applications (3): Calculated Elements and Properties
In this part, I want to discuss the implementation of the service adaptation read services on the server side (service adaptation view and OData definition, xsodata file) and we will have a look at the OData implementation in the SAP UI5 UI.
As introduced in part 1 of this series, we would like to discuss the services for two UIs:
Service Adaptation View
Let us move to the read service in the service adaptation layer now. Let us start with the prospect UI service (see Figure 4 in part 1). The requirements to the backend service are:
Again CDS limitations in SPS8 prevent us implementing the view with CDS. So, we define the view with the following select statement as Prospect.hdbview.
select
BP.ID_,
BP.ID,
BP."CategoryCode",
BP."Status.Code",
ST."DescriptionText" as "Status.DescriptionText",
BPC."Person.GivenName",
BPC."FormattedName",
ADR."DefaultEmailURI" as "EmailURI",
ADR."DefaultPostalAddress.CityName" as "CityName"
from <schema>.<path>::bo.businesspartner.BusinessPartner" as BP
inner join <schema>.<path>::bo.businesspartner.BusinessPartner$C" as BPC
on BP.ID_ = BPC.ID_
inner join <schema>.<path>::bo.businesspartner.Customer" as CUS
on BP.ID_ = CUS."Parent_ID_"
left outer join <schema>.<path>::bo.businesspartner.LifeCycleStatus" as ST
on BP."Status.Code" = ST."Code"
left outer join <schema>.<path>::bo.businesspartner.AddressInformation" as AI
on BP.ID_ = AI."Parent_ID_" and AI."DefaultIndicator" = 1
left outer join <schema>.<path>::bo.address.Address" as ADR
on AI."Address.ID_" = ADR."ID_"
where CUS."ProspectIndicator" = 1
and BP.ID_ in (select "Customer.ID_" from <schema>.<path>::bo.salesterritorymgmt.Customer" )
Discussion:
Based on this view, we can now define the OData definition (Prospect.sxodata) as:
service {
<schema>.<UIpath>::Prospect"
as "Prospect"
key ("ID_");
}
In the browser, you can now consume the OData service using the following URL:
http://<host>:<port>/<UIpath>/Prospect.xsodata/Prospect?$format=json
Here is an example
{
d:
{
results:
[
{
__metadata:
{
uri: "(...)/Prospect.xsodata/Prospect(90006)",
type: "(...)Prospect.ProspectType"
},
ID_: "90006",
ID: "C003",
CategoryCode: "1",
Status.Code: "2",
Status.DescriptionText: "Active",
Person.GivenName: "Frieda",
FormattedName: "Frieda Friday",
EmailURI: null,
CityName: null,
}
}
]
}
}
On the UI (Figure 3 in part 1) you can see a link, Enter Ship-To Address. The idea behind this link is that you can optionally maintain a dedicated ship-to address. As
the next step, I will implement the backend service for this secondary address.
As first step, I create a second view called ShipToAddress.hdbview, which is basically a copy of the Prospect view, with one exception: instead of the
filter AI."DefaultIndicator" = 1 , we define the filter as AI."AddressUsage" = 'SHIP_TO'.
As a second step, I extend the OData definition by the ShipToAddress and an association from Prospect to ShipToAddress:
service {
<schema>.<path>::Prospect"
as "Prospect"
key ("ID_")
navigates ( "ToShipToAddress" as "ShipToAddress" );
<schema>.<path>::ShipToAddress" as "ShipToAddress"
key ("ID_");
association "ToShipToAddress"
principal "Prospect"("ID_") multiplicity "1"
dependent "ShipToAddress"("ID_") multiplicity "1";
}
As a result, I can read the secondary address (if available) by the following OData call:
http://<host>:<port>/<path>/Prospect.xsodata/Prospect?$format=json&$expand=ShipToAddress
Based on the same principle, the implementation of the Sales Order OData service is straight forward: It consists of the Sales Order view, an Item view and the OData definition:
service {
<schema>.<path>.SalesOrder"
as "SalesOrder"
key ("ID_")
navigates ( "ToItem" as "Item",
"ToSalesOrder$P" as "SalesOrder$P" );
<schema>.<UIpath>.Item" as "Item";
<schema>.<path>.SalesOrder$P" as "SalesOrder$P";
association "ToItem"
principal "SalesOrder"("ID_") multiplicity "1"
dependent "Item"("Parent_ID_") multiplicity "*";
association "ToSalesOrder$P "
principal "SalesOrder"("ID_") multiplicity "1"
dependent "SalesOrder$P"("ID_") multiplicity "1";
}
Discussion:
Finally, let us have a look at the OData implementation in the SAP UI5 UI. It consists of the following code lines in the view and controller implementation.
1) Set the model (e.g. in the view implementation, (createContent method of the main view)
var oModel = new sap.ui.model.odata.ODataModel("<path>/SalesOrderView.xsodata", true);
oModel.setDefaultCountMode(false);
this.setModel(oModel);
Discussion: Setting the count mode to false is helpful to avoid unnecessary roundtrips (unless you really need it).
2) Attach the model to a list (in the respective view implementation):
var oMain = sap.ui.getCore().byId("<id of the main view>");
var oModel = oMain.getModel();
oMasterList.setModel(oModel);
3) Implement the controller for filling the list of orders (e.g. in the onBeforeShow method):
oMasterList.bindItems("/SalesOrder", oList._oItemTemplate, oMasterList._oItemSorter);
To read the properties with the data, replace "/SalesOrder" by "/SalesOrder?$expand=SalesOrder$P". After this change, the OData call will expand the association to the properties view and read them into the OData model.
4) Implement the controller for filling the list of items (e.g. in the onSelectionChange method):
var selectedItem = oMasterList.getSelectedItem();
var bindingContext = selectedItem.getBindingContext();
var itemContext = bindingContext.sPath;
oItemList.destroyItems();
oItemList.bindItems(itemContext + "/Item", oList._oItemTemplate, oItemList._oItemSorter);
Discussion: itemContext contains “/SalesOrder(<key>)”., itemContext + "/Item" is the path to load the Items following the Item association in the
service definition.
The OData services are not yet ready for write services, because the views behind the OData services span multiple entities, and so the OData service cannot write to the database tables. If you try to write data with a POST or PUT request, the service will answer with an error message: “Service exception: data manipulation operation not legal on this view.“ In the next blog, I will explain how to implement the write services: A Programming Model for Business Applications (5) Write Service: Business Object, Service Adaptatio....
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
34 | |
25 | |
12 | |
7 | |
7 | |
6 | |
6 | |
6 | |
5 | |
4 |