avatarJerry Wang

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

5139

Abstract

spSefYie8pF4Pw.png"><figcaption></figcaption></figure><p id="0bf1">In SAP S/4HANA, all Fiori apps created based on Fiori Elements share the same set of view templates and controller implementations, hence most messages are no longer defined by the applications themselves but are maintained by the framework.</p><p id="7c4b">For example, the following error message when maintaining S/4HANA material master data:</p><blockquote id="1cd5"><p>Product Type 03 is not valid</p></blockquote><p id="18e1">This message is maintained within the message class /BOFU/CODE_LISTS of the so-called Business Suite Foundation Reusable Components development package.</p><figure id="cbfc"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*ILfIMECkDHOfM_mtlna7lA.png"><figcaption></figcaption></figure><p id="95b7">Now, let’s analyze the customization request for message display in SAP Commerce Cloud mentioned at the beginning of this article.</p><figure id="6ae8"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*-PBFb4pPVlDgJ_DE6jLCtg.png"><figcaption></figcaption></figure><p id="52dc">The text ID for the “Thank you for your review” message is productReview.thankYouForReview, which is displayed on the UI through MessageService after ProductReviewEffects receives the POST_PRODUCT_REVIEW_SUCCESS Action.</p><figure id="8b29"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*soE9m2YoGoCjKNMrSreXpg.png"><figcaption></figcaption></figure><p id="c9b6">A conventional approach to secondary development is to inherit the standardly published ProductReviewEffects class of SAP Commerce Cloud UI and override the implementation code received after POST_PRODUCT_REVIEW_SUCCESS, removing the code that calls MessageService to throw out the thank-you review message.</p><p id="6b51">However, all Effects implementation classes released by SAP Commerce Cloud UI are non-extendable, making this approach unfeasible.</p><p id="87cc">The logic of Spartacus’s communication with the Commerce backend, as shown in the following figure:</p><figure id="0ee9"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*eqL1i8v1qb6VH4a12FnaTw.png"><figcaption></figcaption></figure><p id="f2ac">Communication between Spartacus and the Commerce system is completed through HTTP protocol calls to the OCC API. The Connector initiates HTTP calls, maintaining static configuration information, i.e., API endpoint.</p><p id="e9bd">For example, when reading product master data from the Commerce system, the list of fields to be read appears in the API endpoint as URL parameters. These field lists can be configured in the static configuration point of the Connector.</p><p id="7f69">The Connector does not interact directly with Commerce but forwards requests to the Adapter, which completes the specific communication, with the Connector only responsible for dispatching the Adapter. The Adapter released by Spartacus defaults to using the OCC Module, i.e., Commerce’s standard OCC Restful API, but customers can also implement their own Adapter to connect to backend systems other than Commerce.</p><p id="8a63">The Connector hands over the data retrieved by the Adapter to the NgRx Store structure for unified management, whose complexity is hidden by the Facade layer. Spartacus UI components only interact with the Facade layer for data binding and page display, reflecting the principle of separation of concerns.</p><p id="ef38">Returning to the customization request mentioned at the beginning of this article, to implement this requirement, we need to delve into the details of the interaction between the NgRx Store and the SAP Spartacus Connector highlighted in red in the following figure.</p><figure id="aaef"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*TQdf7jnchY5iZ6oFfSVJjQ.png"><figcaption></figcaption></figure><p id="3a42">NgRx is a reactive state management library for Angular based on RxJs, including the following core concepts, which I will illustrate with actual use cases of NgRx in SAP Commerce Cloud UI.</p><figure id="74fe"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*g2eal8oKWXckMgp-5MXicQ.png"><figcaption></figcaption></figure><p id="56e5">Action: Essentially, an alias for events in the programming domain. SAP Commerce Cloud UI components can respond to user operations and dispatch corresponding Actions through the component’s Service instance. The sender and receiver of the Action are decoupled from each other, unaware of each other’s existence.</p><p id="7918">The following figure shows the code of the Service class throwing out the PostProductReview Action after the Submit button on the SAP Commerce Cloud product detail page’s review section is clicked:</p><figure id="d1aa"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*aG94PAdrqo7v4_3Chve3Fw.png"><figcaption></figcaption></figure><p id="81a6">ProductActions.PostProductReview is a subclass of NgRx Action, with the type field being POST_PRODUCT_REVIEW. The constructor’s parameter payload defines the data structure needed to persist user reviews via the

Options

Commerce OCC API call:</p><figure id="89a4"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*X2vN4QyXpqcOzZFu2NcBuQ.png"><figcaption></figcaption></figure><p id="0dce">Effects: One of the receivers of SAP Commerce Cloud UI Action. The semantics of the following Effects code is to receive Actions of type POST_PRODUCT_REVIEW (line 46), call the previously introduced Connector to initiate OCC API calls to the Commerce backend (line 49), and depending on the API return results, dispatch either the review save success or failure Action:</p><p id="7d28">PostProductReviewSuccess (line 53) PostProductReviewFail (line 56)</p><figure id="3da4"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*vApvLSl1_FfffYcy981unw.png"><figcaption></figcaption></figure><p id="377f">Store: A storage structure maintained in memory by Angular applications, containing runtime data for all components of the SAP Commerce Cloud UI. Whenever Effects fetch new data from the Commerce OCC API, they invoke a Reducer to incorporate the incremental data into the Store.</p><p id="87d7">Reducer: Essentially a finite state machine that, upon receiving an Action indicating changes in data from the Commerce backend, drives the corresponding Reducer to adjust the data in the Store based on the payload contained in the new Action.</p><p id="d244">For example, when the product detail page is rendered for the first time, Effects need to retrieve all review data from the Commerce backend. Upon successful retrieval, a LOAD_PRODUCT_REVIEWS_SUCCESS Action is dispatched. The ProductReviewsReducer, upon receiving this Action, parses the actual review data from its payload and returns it. This returned data is then received by the NgRx framework and merged into the Store.</p><figure id="d23f"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*3jpKWSvCjb_4IGbQiywlZw.png"><figcaption></figcaption></figure><p id="15eb">Selector: Pure functions serving as the interface for the application to read the latest data from the NgRx Store.</p><p id="ba07">Understanding the details of state management using NgRx in the SAP Commerce Cloud UI facilitates the realization of client-specific requirements outlined at the beginning of the article.</p><p id="fb04">Given that the standard Effects illustrated in the SAP Commerce Cloud UI cannot be extended, we note that the Service layer of UI components is the starting point of all event flows. Therefore, we can implement a new Service to replace the standard Service of the SAP Commerce Cloud UI, and based on this customized Service, develop corresponding Effects and Action.</p><p id="cc0c">Thus, the standard logic flow related to user reviews, as illustrated in figures 1–2–3, will no longer be executed. Instead, our customized execution flow, as shown in figures A-B-C, where the blue legends represent the customized code to be developed by Partners, will take its place.</p><figure id="2928"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*Y7dsh-UmDHc_vSFZNX4q5w.png"><figcaption></figcaption></figure><p id="d55d">A brief introduction to this solution:</p><p id="51f1">(1) Create new Actions CustPostProductReview, CustPostProductReviewSuccess, and CustPostProductReviewFail. Essentially, this involves prefixing the standard implementation classes with “Cust.”</p><p id="4bcb">(2) Create a new CustProductReviewService, inheriting from the standard ProductReviewService. Override its add method to dispatch the new CustPostProductReview Action.</p><figure id="ee43"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*rquVVCiBMCqbMQkMFxiaIg.png"><figcaption></figcaption></figure><p id="919e">(3) Develop CustProductReviewsEffects, which receives the new Action CUST_POST_PRODUCT_REVIEW (line 25), still calls the Connector to persist user reviews to the Commerce backend (line 28), and then dispatches the new Action CustPostProductReviewSuccess.</p><figure id="2aa9"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*p6sOsxnNLQ5eCaIliSv3NQ.png"><figcaption></figcaption></figure><p id="2d7d">Upon receiving the new Action CUST_POST_PRODUCT_REVIEW_SUCCESS, the custom Effect can proceed with writing custom logic.</p><figure id="785e"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*qqH_gX67KKMqdH2lNFMQzQ.png"><figcaption></figcaption></figure><p id="df8a">(4) Implement the custom Effect and Service, configuring them into the corresponding Module through the Angular dependency injection framework.</p><figure id="ed50"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*AQn9--r9JjkOy7jBPAaUHg.png"><figcaption></figcaption></figure><p id="6bbd">This article delves into the design and implementation technical details of messaging mechanisms that I have been involved in across various product development projects at SAP. It is my hope that this will inspire fellow SAP practitioners. Thank you for reading.</p><figure id="d764"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*pR6ui_BclGhQfC7jPGSpEA.png"><figcaption></figcaption></figure></article></body>

Design and Technical Implementation Details of Message Display Mechanism in Various SAP Products

My working experience sharing in SAP Labs China Development Team

The inspiration for this article comes from a customization request for the SAP Commerce Cloud Spartacus UI on the StackOverflow community by Partner.

The context of this requirement is that customers can leave their reviews on the product detail page of the SAP Commerce Cloud and submit them by clicking the Submit button.

After submission, a prompt message saying “Thank you for your review” is displayed.

The customer’s customization request is to bypass the default logic of displaying this message. Instead of showing the message, they want to execute alternative logic, such as sending SMS or email notifications.

Let’s first briefly review the UI message display mechanism of other SAP products.

Messages are an important channel for providing feedback to users during the execution process of an application, usually triggered directly by a user action and displayed on the product interface. Of course, application background jobs can also trigger message displays when certain conditions are met at specific stages. Concise, clear, and accurate messages can help users understand the current status of the program and guide their next steps.

The text of messages displayed in SAP product UIs is reviewed and published by a professional Knowledge Management (KM) team.

For SAP developers, the context in which these messages are displayed is of greater concern; in other words, upon seeing a message displayed on the UI, they aim to efficiently locate the exact code position that threw the message in the shortest possible time.

As shown in the following figure, in the classic SAPGUI SE38 ABAP program editor, entering a non-existent report name will display a message:

Program XX does not exist.

Where XX is a placeholder that will be replaced by the report name actually entered by the user.

All SAP products implemented with ABAP, such as SAP CRM, SAP SRM, SAP S/4HANA, and SAP Cloud for Customer, have a corresponding message record in the ABAP backend for each message displayed on the UI, maintained in transaction code SE91.

Taking the above message as an example, its code is DS017, where DS is the message class and 017 is the message number, uniquely identifying a message record.

In the SAP CRM WebClient UI, every message seen on the browser, like the following “Data Contains errors and cannot be saved”, still uniquely corresponds to a backend message record CRM_BUPA_BOL/036:

This message is maintained by the Business Partner application.

In SAP Cloud for Customer, although Partners cannot log in to the ABAP backend directly, they can still obtain the message class and message number of the UI message corresponding to the ABAP backend message record through Chrome developer tools:

In SAP Cloud for Customer, Partners can create new UI messages through the Cloud Application Studio:

In the ABSL code, the message is displayed on the UI using the raise statement:

raise delivery_message.Create("S", this.OutboundDeliveryID);

At runtime, the &1 in the message text defined by delivery_message will be replaced by the value of the this.outboundDeliveryID field.

In SAP S/4HANA, all Fiori apps created based on Fiori Elements share the same set of view templates and controller implementations, hence most messages are no longer defined by the applications themselves but are maintained by the framework.

For example, the following error message when maintaining S/4HANA material master data:

Product Type 03 is not valid

This message is maintained within the message class /BOFU/CODE_LISTS of the so-called Business Suite Foundation Reusable Components development package.

Now, let’s analyze the customization request for message display in SAP Commerce Cloud mentioned at the beginning of this article.

The text ID for the “Thank you for your review” message is productReview.thankYouForReview, which is displayed on the UI through MessageService after ProductReviewEffects receives the POST_PRODUCT_REVIEW_SUCCESS Action.

A conventional approach to secondary development is to inherit the standardly published ProductReviewEffects class of SAP Commerce Cloud UI and override the implementation code received after POST_PRODUCT_REVIEW_SUCCESS, removing the code that calls MessageService to throw out the thank-you review message.

However, all Effects implementation classes released by SAP Commerce Cloud UI are non-extendable, making this approach unfeasible.

The logic of Spartacus’s communication with the Commerce backend, as shown in the following figure:

Communication between Spartacus and the Commerce system is completed through HTTP protocol calls to the OCC API. The Connector initiates HTTP calls, maintaining static configuration information, i.e., API endpoint.

For example, when reading product master data from the Commerce system, the list of fields to be read appears in the API endpoint as URL parameters. These field lists can be configured in the static configuration point of the Connector.

The Connector does not interact directly with Commerce but forwards requests to the Adapter, which completes the specific communication, with the Connector only responsible for dispatching the Adapter. The Adapter released by Spartacus defaults to using the OCC Module, i.e., Commerce’s standard OCC Restful API, but customers can also implement their own Adapter to connect to backend systems other than Commerce.

The Connector hands over the data retrieved by the Adapter to the NgRx Store structure for unified management, whose complexity is hidden by the Facade layer. Spartacus UI components only interact with the Facade layer for data binding and page display, reflecting the principle of separation of concerns.

Returning to the customization request mentioned at the beginning of this article, to implement this requirement, we need to delve into the details of the interaction between the NgRx Store and the SAP Spartacus Connector highlighted in red in the following figure.

NgRx is a reactive state management library for Angular based on RxJs, including the following core concepts, which I will illustrate with actual use cases of NgRx in SAP Commerce Cloud UI.

Action: Essentially, an alias for events in the programming domain. SAP Commerce Cloud UI components can respond to user operations and dispatch corresponding Actions through the component’s Service instance. The sender and receiver of the Action are decoupled from each other, unaware of each other’s existence.

The following figure shows the code of the Service class throwing out the PostProductReview Action after the Submit button on the SAP Commerce Cloud product detail page’s review section is clicked:

ProductActions.PostProductReview is a subclass of NgRx Action, with the type field being POST_PRODUCT_REVIEW. The constructor’s parameter payload defines the data structure needed to persist user reviews via the Commerce OCC API call:

Effects: One of the receivers of SAP Commerce Cloud UI Action. The semantics of the following Effects code is to receive Actions of type POST_PRODUCT_REVIEW (line 46), call the previously introduced Connector to initiate OCC API calls to the Commerce backend (line 49), and depending on the API return results, dispatch either the review save success or failure Action:

PostProductReviewSuccess (line 53) PostProductReviewFail (line 56)

Store: A storage structure maintained in memory by Angular applications, containing runtime data for all components of the SAP Commerce Cloud UI. Whenever Effects fetch new data from the Commerce OCC API, they invoke a Reducer to incorporate the incremental data into the Store.

Reducer: Essentially a finite state machine that, upon receiving an Action indicating changes in data from the Commerce backend, drives the corresponding Reducer to adjust the data in the Store based on the payload contained in the new Action.

For example, when the product detail page is rendered for the first time, Effects need to retrieve all review data from the Commerce backend. Upon successful retrieval, a LOAD_PRODUCT_REVIEWS_SUCCESS Action is dispatched. The ProductReviewsReducer, upon receiving this Action, parses the actual review data from its payload and returns it. This returned data is then received by the NgRx framework and merged into the Store.

Selector: Pure functions serving as the interface for the application to read the latest data from the NgRx Store.

Understanding the details of state management using NgRx in the SAP Commerce Cloud UI facilitates the realization of client-specific requirements outlined at the beginning of the article.

Given that the standard Effects illustrated in the SAP Commerce Cloud UI cannot be extended, we note that the Service layer of UI components is the starting point of all event flows. Therefore, we can implement a new Service to replace the standard Service of the SAP Commerce Cloud UI, and based on this customized Service, develop corresponding Effects and Action.

Thus, the standard logic flow related to user reviews, as illustrated in figures 1–2–3, will no longer be executed. Instead, our customized execution flow, as shown in figures A-B-C, where the blue legends represent the customized code to be developed by Partners, will take its place.

A brief introduction to this solution:

(1) Create new Actions CustPostProductReview, CustPostProductReviewSuccess, and CustPostProductReviewFail. Essentially, this involves prefixing the standard implementation classes with “Cust.”

(2) Create a new CustProductReviewService, inheriting from the standard ProductReviewService. Override its add method to dispatch the new CustPostProductReview Action.

(3) Develop CustProductReviewsEffects, which receives the new Action CUST_POST_PRODUCT_REVIEW (line 25), still calls the Connector to persist user reviews to the Commerce backend (line 28), and then dispatches the new Action CustPostProductReviewSuccess.

Upon receiving the new Action CUST_POST_PRODUCT_REVIEW_SUCCESS, the custom Effect can proceed with writing custom logic.

(4) Implement the custom Effect and Service, configuring them into the corresponding Module through the Angular dependency injection framework.

This article delves into the design and implementation technical details of messaging mechanisms that I have been involved in across various product development projects at SAP. It is my hope that this will inspire fellow SAP practitioners. Thank you for reading.

Sap
Abap
Erp
Software
Programming
Recommended from ReadMedium