RAP - Semantic Key
What do you need the semantic key for and how is it represented in the ABAP RESTful Programming Model? You can find out more here.
Table of contents
In this article we will take a closer look at the semantic key, how it is represented and what it does in our application.
Introduction
In the ABAP RESTful Programming Model, we mainly use UUID keys in our applications to store our data. This saves us from having to check the unique key, but it does not only have advantages. Since such a key cannot be remembered. In such cases, you can use semantic keys. The semantic key is a unique and readable key within the data, but was not created as a key field. A few rules should be observed:
- The key can be changed at any time
- Uniqueness must be ensured through checks
- The key can be used for navigation
Representation
Let's take a look at how we can define the key. To do this, we will extend our application for the Report Pattern to include a semantic key.
Extension
In the consumption view "ZBS_R_DRPCurrency" we need to include the annotation "ObjectModel.semanticKey". To do this, we specify all the elements that belong to our key and make it unique. Here is the excerpt from the view:
@ObjectModel.semanticKey: ['Currency']
define root view entity ZBS_C_DRPCurrency
provider contract transactional_query
as projection on ZBS_R_DRPCurrency
{
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 1.0
@Search.ranking: #HIGH
key Currency,
Result
Let's take a look at the entry page before defining the new semantic key. There are no changes or abnormalities to be seen here. Every column in the table looks the same at first.
After we have set the key, the list changes and the key is highlighted in bold. In addition to the highlighting, the data set now also shows whether a draft is available for it. Previously, it was not clear from the list which data set was in the draft and had to be found out using the filter.
Navigation
In this section, we want to change our translation app, which works with a UUID as a key, but still uses a unique composite key.
Extension
To do this, we extend the consumption view "ZBS_C_DMOLanguage", this time with two fields that form the key.
@ObjectModel.semanticKey: [ 'SourceLanguage', 'SourceText' ]
define root view entity ZBS_C_DMOLanguage
provider contract transactional_query
as projection on ZBS_R_DMOLanguage
{
key Identification,
SourceLanguage,
SourceText,
Result
In this case, let's take a look at the navigation. You can find this in the URL at the end of the service. Without a semantic key, the entity key is used for navigation.
/Language(Identification=4ae9a11c-f565-1eef-8fe9-2d306bea1dc2,IsActiveEntity=true)
After we have extended the semantic key with the two fields, the path for navigation also changes and we can now get to the entity with readable keys.
/Language(SourceText='Apfel',SourceLanguage='DE')
Uniqueness
It is now important to ensure the uniqueness of the data records. At the database level, we have not defined a mechanism that checks the uniqueness or rejects such entries. This means that we can now create duplicate data records.
We therefore have to take action in the application ourselves and implement validation. To do this, we extend our behavior definition "ZBS_R_DMOLanguage".
validation CheckSemanticKey on save { create; update; field SourceLanguage, SourceText; }
The implementation of a simple check would therefore look like this. In the first step, we read the data records to be checked, which we receive via KEYS. Then we select via our Core Data Service with the local table as a JOIN to get data records with a different UUID, but which have the same semantic key. The result is then data records that already exist with the same key, so we output the error message for our hit.
READ ENTITIES OF ZBS_R_DMOLanguage IN LOCAL MODE
ENTITY Language FIELDS ( SourceLanguage SourceText ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_selected).
SELECT
FROM ZBS_R_DMOLanguage AS db
INNER JOIN
@lt_selected AS local ON local~Identification <> db~Identification
AND local~SourceLanguage = db~SourceLanguage
AND local~SourceText = db~SourceText
FIELDS db~Identification,
local~Identification AS LocalId
INTO TABLE @DATA(lt_duplicates).
LOOP AT lt_duplicates INTO DATA(ls_duplicate).
INSERT VALUE #( Identification = ls_duplicate-LocalId ) INTO TABLE failed-language.
INSERT VALUE #( Identification = ls_duplicate-LocalId
%msg = new_message_with_text( text = |Semantic key not unique| ) ) INTO TABLE reported-language.
ENDLOOP.
We now receive an error message in our Fiori app and the data record is not created. This means that the key can only be created uniquely.
Complete example
As always, you can find the changes to the two applications in the GitHub repository and in the corresponding commit so that you can understand all changes to the objects.
Conclusion
The semantic key enriches the app with various functions that give us further information and make the keys more readable. However, you must also ensure that the keys remain unique.
More information:
SAP Community - UUID and Semantic Key