From 98227b169a2515582bea383fd2fee96f350ca961 Mon Sep 17 00:00:00 2001 From: Robin de Silva Jayasinghe Date: Tue, 27 Oct 2026 09:07:44 +0100 Subject: [PATCH 1/4] Move draft user description docu from Java to Fiori guide Moves the "Showing a Custom User Description" section from the Java-specific fiori-drafts page into the shared guides/uis/fiori page, marked as Java-only via a warning callout. The Java page now has a learn-more link pointing to the new location. Closes https://github.wdf.sap.corp/cds-java/home/issues/2972 --- guides/uis/fiori.md | 50 ++++++++++++++++++++++++++++++++++++++++++++ java/fiori-drafts.md | 43 +------------------------------------ 2 files changed, 51 insertions(+), 42 deletions(-) diff --git a/guides/uis/fiori.md b/guides/uis/fiori.md index 4d1cb5e29c..29a55db11c 100644 --- a/guides/uis/fiori.md +++ b/guides/uis/fiori.md @@ -482,6 +482,56 @@ You can override generated side-effect annotations per entity, for example: Can be disabled with cds.fiori.draft_messages: false. ::: +### Showing a Custom User Description { #draft-user-description} + +::: warning Only Java +This feature is currently supported only on the Java runtime. +::: + +By default, the SAP Fiori draft UI displays the unique user name in fields such as *Locked by*. To show a human-readable name instead, enable the `draftUserDescription` CDS compiler option and populate the generated `InProcessByUserDescription` field via a custom handler. + +**1. Enable the compiler option** in your `.cdsrc.json`: + +```json +{ + "cdsc": { + "draftUserDescription": true + } +} +``` + +The compiler now adds `InProcessByUserDescription`, `CreatedByUserDescription`, and `LastChangedByUserDescription` to the `DraftAdministrativeData` entity. + +**2. Register a `@Before` handler** on `DRAFT_CREATE` across all draft services to populate the field: + +```java +@Component +@ServiceName(value = "*", type = DraftService.class) +public class UserDescriptionHandler implements EventHandler { + + @Autowired private UserInfo userInfo; + + @Before + protected void addDraftFields(DraftCreateEventContext context, List entries) { + CdsDataProcessor.Filter filter = + (path, element, type) -> "InProcessByUserDescription".equals(element.getName()); + CdsDataProcessor.Generator generator = (path, element, isNull) -> description(); + CdsDataProcessor.create().addGenerator(filter, generator).process(entries, context.getTarget()); + } + + private String description() { + return userInfo.getAdditionalAttribute("given_name") + + " " + + userInfo.getAdditionalAttribute("family_name"); + } +} +``` + +::: tip +The attribute names `given_name` and `family_name` correspond to JWT token claims provided by your IdP. Adjust them to match the claims configured in your environment. +::: + + ### Draft for Localized Data Annotate the underlying base entity in the base model with `@fiori.draft.enabled` to also support drafts for [localized data](./localized-data): diff --git a/java/fiori-drafts.md b/java/fiori-drafts.md index daf6cc0ceb..0730228c4c 100644 --- a/java/fiori-drafts.md +++ b/java/fiori-drafts.md @@ -333,48 +333,7 @@ public void createDraft(CreateDraftContext context) { ## Showing a Custom User Description { #draft-user-description} -By default, the SAP Fiori draft UI displays the unique user name in fields such as *Locked by*. To show a human-readable name instead, enable the `draftUserDescription` CDS compiler option and populate the generated `InProcessByUserDescription` field via a custom handler. - -**1. Enable the compiler option** in your `.cdsrc.json`: - -```json -{ - "cdsc": { - "draftUserDescription": true - } -} -``` - -The compiler now adds `InProcessByUserDescription`, `CreatedByUserDescription`, and `LastChangedByUserDescription` to the `DraftAdministrativeData` entity. - -**2. Register a `@Before` handler** on `DRAFT_CREATE` across all draft services to populate the field: - -```java -@Component -@ServiceName(value = "*", type = DraftService.class) -public class UserDescriptionHandler implements EventHandler { - - @Autowired private UserInfo userInfo; - - @Before - protected void addDraftFields(DraftCreateEventContext context, List entries) { - CdsDataProcessor.Filter filter = - (path, element, type) -> "InProcessByUserDescription".equals(element.getName()); - CdsDataProcessor.Generator generator = (path, element, isNull) -> description(); - CdsDataProcessor.create().addGenerator(filter, generator).process(entries, context.getTarget()); - } - - private String description() { - return userInfo.getAdditionalAttribute("given_name") - + " " - + userInfo.getAdditionalAttribute("family_name"); - } -} -``` - -::: tip -The attribute names `given_name` and `family_name` correspond to JWT token claims provided by your IdP. Adjust them to match the claims configured in your environment. -::: +[Learn how to show a custom user description in drafts.](../guides/uis/fiori#draft-user-description){.learn-more} ## Consuming Draft Services { #draftservices} From d2a2c0a381a22c8fb242857b8ce3902679c51335 Mon Sep 17 00:00:00 2001 From: Robin de Silva Jayasinghe Date: Fri, 6 Nov 2026 10:23:52 +0100 Subject: [PATCH 2/4] addressed review comments --- guides/uis/fiori.md | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/guides/uis/fiori.md b/guides/uis/fiori.md index 29a55db11c..695960bb1b 100644 --- a/guides/uis/fiori.md +++ b/guides/uis/fiori.md @@ -484,10 +484,6 @@ Can be disabled with cds.fiori.draft_messages: false. ### Showing a Custom User Description { #draft-user-description} -::: warning Only Java -This feature is currently supported only on the Java runtime. -::: - By default, the SAP Fiori draft UI displays the unique user name in fields such as *Locked by*. To show a human-readable name instead, enable the `draftUserDescription` CDS compiler option and populate the generated `InProcessByUserDescription` field via a custom handler. **1. Enable the compiler option** in your `.cdsrc.json`: @@ -502,7 +498,9 @@ By default, the SAP Fiori draft UI displays the unique user name in fields such The compiler now adds `InProcessByUserDescription`, `CreatedByUserDescription`, and `LastChangedByUserDescription` to the `DraftAdministrativeData` entity. -**2. Register a `@Before` handler** on `DRAFT_CREATE` across all draft services to populate the field: +**2. Register a handler** on draft events across all draft services to populate the field: + +This is how the handler could look for CAP Java: ```java @Component @@ -512,11 +510,8 @@ public class UserDescriptionHandler implements EventHandler { @Autowired private UserInfo userInfo; @Before - protected void addDraftFields(DraftCreateEventContext context, List entries) { - CdsDataProcessor.Filter filter = - (path, element, type) -> "InProcessByUserDescription".equals(element.getName()); - CdsDataProcessor.Generator generator = (path, element, isNull) -> description(); - CdsDataProcessor.create().addGenerator(filter, generator).process(entries, context.getTarget()); + protected void addDraftFields(DraftCreateEventContext context, List orders) { + orders.forEach(o -> o.setInProcessByUserDescription(description())); } private String description() { @@ -527,6 +522,15 @@ public class UserDescriptionHandler implements EventHandler { } ``` +This is the corresponding handler for CAP node.js: + +```javascript +srv.on('PATCH', Order, req => { + req.data.LastChangedByUserDescription = req.user.attr.firstName + ' ' + req.user.attr.lastName +}) +``` + + ::: tip The attribute names `given_name` and `family_name` correspond to JWT token claims provided by your IdP. Adjust them to match the claims configured in your environment. ::: From 15d1176c4609925d39781504015fa4d00f2669ea Mon Sep 17 00:00:00 2001 From: Robin de Silva Jayasinghe Date: Fri, 6 Nov 2026 15:12:23 +0100 Subject: [PATCH 3/4] addressed review comments --- guides/uis/fiori.md | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/guides/uis/fiori.md b/guides/uis/fiori.md index 695960bb1b..14f184fdd9 100644 --- a/guides/uis/fiori.md +++ b/guides/uis/fiori.md @@ -510,14 +510,9 @@ public class UserDescriptionHandler implements EventHandler { @Autowired private UserInfo userInfo; @Before - protected void addDraftFields(DraftCreateEventContext context, List orders) { - orders.forEach(o -> o.setInProcessByUserDescription(description())); - } - - private String description() { - return userInfo.getAdditionalAttribute("given_name") - + " " - + userInfo.getAdditionalAttribute("family_name"); + protected void addDraftFields(DraftPatchEventContext context, Order order) { + order.setInProcessByUserDescription(userInfo.getAdditionalAttribute("given_name") + " " + + userInfo.getAdditionalAttribute("family_name")description()); } } ``` @@ -526,7 +521,7 @@ This is the corresponding handler for CAP node.js: ```javascript srv.on('PATCH', Order, req => { - req.data.LastChangedByUserDescription = req.user.attr.firstName + ' ' + req.user.attr.lastName + req.data.LastChangedByUserDescription = req.user.attr.firstName + ' ' + req.user.attr.givenName }) ``` From 8317bf1b2d388892a28b73acb761b5f68a032ff6 Mon Sep 17 00:00:00 2001 From: Robin de Silva Jayasinghe Date: Fri, 6 Nov 2026 15:14:49 +0100 Subject: [PATCH 4/4] minor correction --- guides/uis/fiori.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/uis/fiori.md b/guides/uis/fiori.md index 14f184fdd9..239e0fd6d2 100644 --- a/guides/uis/fiori.md +++ b/guides/uis/fiori.md @@ -521,7 +521,7 @@ This is the corresponding handler for CAP node.js: ```javascript srv.on('PATCH', Order, req => { - req.data.LastChangedByUserDescription = req.user.attr.firstName + ' ' + req.user.attr.givenName + req.data.InProcessByUserDescription = req.user.attr.givenName + ' ' + req.user.attr.familyName }) ```