Posts

Authentication Against SAP XSUAA from Local

Image
 Sometimes, we need to run SAPUI5 applications in the local desktop, and test it base on the remote data from SAP BTP. At the same time, remote BTP data is protected by SAP XSUAA and configured IDP. To access the remote protected data, we need the token issued by IDP. After getting the token, we can attach it to the HTTP header for each data request. Request Token The simplest way to request a token is using postman. By selecting oAuth authentication and provide required information, such as clientid and clientsecret, postman is able to request a token for us. If ui5 tooling is used for local SAPUI5 development, the returned the token by postman can be put into the yaml configuration file. The token info will be sent to remote BTP along with OData requests. One of the drawbacks of this manual approach is we are unable to know whether the token is expired or not. Each issued toke is only valid for a certain period of time which is determined by XSUAA configuration. To overcome this,...

Run SAP App Router Locally

 This is a summary after testing SAP App Router locally. Running SAP App Router locally may be not necessary for most cases, thus this is to demonstrate the technical possibility. Actually there are some famous blogs about this topic, hence I don't want to repeat those basic steps again here. What I want to highlight here are issues I met during my test.  For basic setup steps you can search for relevant posts. BTP Service and App For my test, I followed this public tutorial to setup BTP apps and service in my trial account.  But one important point which is missed in the tutorial is additional settings for XSUAA service configuration. In order to do authentication from local app router against remote BTP XSUAA service, below configuration is necessary. Otherwise, we will get invalid call back during oAuth authentication flow. "oauth2-configuration": {         "redirect-uris": [             "https://approuter-product-list...

Timestamp with Time Zone Annotation in Fiori Elements

Image
Assumption: UTC timestamp data is stored in the DB table Default Logic: Without any additional tweaking, UTC timestamp is sent to SAPUI5. SAPIU5 converts it to a time zone either set by FLP or by local operation system. For example, timestamp 202304200800.000000 is stored in the table and its metadata data type is Edm.DataTimeOffset. The time zone of the operation system is Europe/Berlin. Then it will be displayed as 2023-04-20 10:00:00(formate is determined by locale or FLP setting). The logic is very common and SAPUI5 supports this since from early versions. With Specified Time Zone: But there could also be requirements that to present certain timestamp values in dedicated time zones. Or display the same time in different concerned time zones on the UI. Think about a row of clocks which are showing time for cites New York, Berlin, Shanghai and Tokyo. They are running the same UTC time but in differnt time zones. With timezone relevant annotations, we can not achive this without any a...

Calling Function and Action in OData V4

In OData V2, there is only on concept called 'Function' or 'Function Import'. But in V4, this is divided into two categories by different purposes for which they are expected to serve.  According to the standard OData specification, functions MUST NOT have side-effects, which means it should not make any changes to current data. On the contrary, actions can be used to modify data. This note tries to document ways of calling them. And both are called operation. Unbound Function Unbound function can be used to do something based on all data of the connected entity, such as CalculateAveragePrice, CalculateStockAvailability etc..   Sample URL for calling it: https://abc.com/sap/opu/odata4/sap/zui_v4_test/srvd/sap/zsd_xc_test/0001/FunctionDemo/ com.sap.gateway.srvd.zsd_xc_test.v0001 .calculateTotal() The trick point here is to add the namespace before the actual function name. Unbound Action A typical example of an unbound action is creating a new instance of the connected e...

SAP Fiori Elements with Annotation Expression

Image
To note down annotation expression examples I have used and proved workable. Unfortunately, I didn't find any official documents so far. Will update here if I get any. Apply a Function A function can be used to calculate wanted value for a specified UI place. The example below is use 'odata.concat' to concatenate three fields with '-' as the separator, and display it as the title of the object page. Without this approach, backend service needs to add a dedicated field and do the concatenation at the backend. But I found that this doesn't work in DataField. I think the reason may be there is annotation ConnectedField for this purpose. This tested successfully with FE V2. IF-ELSE For some simple dynamic control cases, it is much easier to determine the result on the client side instead of the backend side. Below is an example of a general case that to display or hide a form group according to a field value. It evaluates a value from the field specified with tag ...

Inconsistent CDS Annotation Between DEV and QAS Systems

Months back I received an incident regarding a Fiori Elements application missed one field in QAS system, but worked correctly in DEV system. The FE app was developed by using ABAP Programing Model for SAP Fiori(CDS+BOPF). The disappeared field is rendered via standard annotation which is composed in ABAP CDS view. Investigations: Examine annotations which are derived from CDS view and consumed by FE. By comparing annotations generated by both system, I can see the missed field is not presented in the annotation's LineItem section. Thus I am confident FE works as expected; the issue was not caused by frontend. Instead, the QAS backend server was not providing a correct annotation file as defined in the CDS view. Debug ABAP code of generating annotations based on CDS view. After hours of debugging, I located the main code of generating annotations from CDS view definition. The core method is  CL_DD_DDL_ANNOTATION_SERVICE->GET_ANNOS. It receives the CDS view name and exports rudim...

OData V4: Use Fields from Child Entity as Filters

Think about a simple data model with a header entity(Header) and a child entity(Text) which are connected with navigations. And we want to provide fields from the child entity as possbile filters for query. With OData V2, we need to use virtual element and implement SADL filter exit to achive this. But in V4, we don't need self-implementation anymore since it is supported in nature.  In V4 it is called Lambda Operators, includes 'any' and 'all'. Details can be found from official document:  OData Version 4.0. Part 2: URL Conventions Plus Errata 03 (oasis-open.org) The 'Text' entity has a field named 'Language'. I want to get all 'Header' entity instances which its child entity 'Text' has records with 'Language' equals to 'DE'. This a simple INNER JOIN in SQL world. In OData V4, the URL syntax should have below pattern. https://host/odata/srv/Header? $filter= _Text/ any (d:d/Language eq 'DE') &$count=true ...