[[{“value”:”
Hello everyone,
Before we get started, feel free to catch up on the earlier parts of the series for better context
SAP MDG + Azure AD – Part 1: The Why, The Gap, and… – SAP Community
SAP MDG + Azure AD – Part 2: Connecting SAP to Azu… – SAP Community
1.Business Scenario
SAP Master Data Governance determines how to govern a master record through the process of using change requests and workflow.
A Third-Party Enrichment Service like Azure in this case is used to verify the existence of a customer in the Azure System in this manner we can link the Customer Master Record with the Customer details in the Azure. It also reduces effort of going back to check the Customer Record in Azure system and then coming back to the MDG Screen.
This blog helps in building a link between Azure and SAP MDG and how the Enrichment services can be embedded as a part of SAP MDG in Manage Customer Governance, in Azure the customer details like First Name, Last Name and Email remain unique so by using these details we are going to search for the required customer mail id in the MDG screen but the data is being fetched from Azure System in real-time. This helps the user to have complete information before submitting the customer change request.
We can also use the Enrichment Spot Creation as mentioned by SAP: Create an Enrichment Spot with User Interaction in Master Data Governance
Navigate to the Customer Details Section in Customer Governance Screen
If you know the Mail ID of the Customer from Azure system proceed to enter it
But if you wish to search for customer mail id based on first name and last name, use the F4 help
Click on ‘Go’ button to fetch all details of existing Customers in Azure Systems
Select required entry and the result is fetched in Customer Details UIBB
Users navigate to Customer Details UIBB on Customer Governance Screen-> Clicks on F4 help -> Search with a combination of First Name and Last Name ->If record exists in Azure System entry is displayed and Mail ID is stored in the UI Section Under Customer Details
2.Understanding the Configuration
Users click f4->feeder class fires->passes the entry in search field to Azure(with the help of a wrapper class)->JSON Response->field mapped back to cs_data->uibb displays data.
3.HTTP Integration with Azure
3.1 Wrapper Class
This is already explained in the previous blogs. In this blog the creation of wrapper class and how it is used in the feeder of External Customer Details from Azure UIBB.
The wrapper class is used to
- Go to the Azure Active Directory and get an entry pass (Bearer Token)
- Use this pass to walk into Microsoft Graph and bring the list of users
Create a class (ZCL_MDG_AZURE_AD_USERS) and a method(get_all_users)
Method Declaration:
public section.
types:
BEGIN OF ty_azure_ad_user,
id TYPE string,
display_name TYPE string,
given_name TYPE string,
surname TYPE string,
user_principal_name TYPE string,
mail TYPE string,
job_title TYPE string,
mobile_phone TYPE string,
office_location TYPE string,
preferred_language TYPE string,
business_phones TYPE string,
END OF ty_azure_ad_user .
types:
tt_azure_ad_users TYPE STANDARD TABLE OF ty_azure_ad_user
WITH DEFAULT KEY .
methods GET_ALL_USERS
importing
!IV_AAD_INTERFACE type STRING
!IV_GRAPH_INTERFACE type STRING
value(IV_CLIENT_ID) type STRING optional
exporting
value(ET_USERS) type TT_AZURE_AD_USERS
value(EV_HTTP_STATUS) type I
value(EV_ERROR_MESSAGE) type STRING .
Setup and Validation:
METHOD get_all_users.
DATA: lv_aad_token TYPE string,
lv_aad_response TYPE string,
lv_http_status TYPE i,
lv_json TYPE string,
lv_filter TYPE zbusinessid,
ls_user TYPE ty_azure_ad_user,
oref_aad TYPE REF TO zcl_adf_service_aad,
oref_graph TYPE REF TO zcl_adf_service_graph,
oref TYPE REF TO zcl_adf_service.
FIELD-SYMBOLS: <ls_graph_user> TYPE any,
<fv> TYPE any.
CLEAR: et_users, ev_http_status, ev_error_message.
DATA: lv_aad_iface TYPE zinterface_id,
lv_graph_iface TYPE zinterface_id,
lv_client_id TYPE string.
lv_aad_iface = iv_aad_interface.
lv_graph_iface = iv_graph_interface.
IF iv_client_id IS NOT INITIAL.
lv_client_id = iv_client_id.
ELSE.
lv_client_id = me->get_client_id_from_rfc( lv_aad_iface ).
IF lv_client_id IS INITIAL.
ev_error_message = ‘Client ID not provided and not found’.
ev_http_status = 400.
RETURN.
ENDIF.
ENDIF.
- The interface IDs are keys in SDK Table which determine Azure endpoint, credentials, SM59 destination. These are already configured during the setup of SDK.
- If the caller did not pass a client ID then it reads from SM59 Config automatically and if still cannot find one HTTP 400 error is thrown and process gets halted.
Getting the Bearer Token (AAD)
TRY.
oref = zcl_adf_service_factory=>create(
iv_interface_id = lv_aad_iface
iv_business_identifier = lv_filter ).
oref_aad ?= oref.
oref_aad->get_aad_token(
EXPORTING
iv_client_id = lv_client_id
iv_resource = ‘https://graph.microsoft.com’
IMPORTING
ev_aad_token = lv_aad_token
ev_response = lv_aad_response ).
- The factory class creates a service object using an interface id and business identifier.
- Then it calls get_aad_token on the AAD service class by passing the Client ID and resource URL (Microsoft Graph) and then receives a Bearer Token.
Using Microsoft Graph to Get Users
oref = zcl_adf_service_factory=>create(
iv_interface_id = lv_graph_iface
iv_business_identifier = lv_filter ).
oref_graph ?= oref.
DATA(lt_graph_users) = oref_graph->zif_adf_service_graph~get_users(
EXPORTING
iv_aad_token = lv_aad_token
IMPORTING
ev_http_status = lv_http_status ).
ev_http_status = lv_http_status.
lv_json = /ui2/cl_json=>serialize(
data = lt_graph_users
pretty_name = /ui2/cl_json=>pretty_mode-camel_case ).
- The Graph Service class uses the Bearer Token to call the Graph API endpoint and returns the result in lt_graph_users which has user records from your Azure AD tenant.
Mapping the Result
IF lt_graph_users IS NOT INITIAL.
LOOP AT lt_graph_users ASSIGNING <ls_graph_user>.
CLEAR ls_user.
ASSIGN COMPONENT ‘DISPLAYNAME’ OF STRUCTURE <ls_graph_user> TO <fv>.
IF sy-subrc = 0. ls_user-display_name = <fv>. ENDIF.
ASSIGN COMPONENT ‘DISPLAY_NAME’ OF STRUCTURE <ls_graph_user> TO <fv>.
IF sy-subrc = 0. ls_user-display_name = <fv>. ENDIF.
ASSIGN COMPONENT ‘GIVEN_NAME’ OF STRUCTURE <ls_graph_user> TO <fv>.
IF sy-subrc = 0. ls_user-given_name = <fv>. ENDIF.
ASSIGN COMPONENT ‘SURNAME’ OF STRUCTURE <ls_graph_user> TO <fv>.
IF sy-subrc = 0. ls_user-surname = <fv>. ENDIF.
ASSIGN COMPONENT ‘MAIL’ OF STRUCTURE <ls_graph_user> TO <fv>.
IF sy-subrc = 0. ls_user-mail = <fv>. ENDIF.
APPEND ls_user TO et_users.
ENDLOOP.
ENDIF.
CATCH zcx_interace_config_missing INTO DATA(cx_config).
ev_error_message = cx_config->get_text( ).
ev_http_status = 500.
CATCH zcx_http_client_failed INTO DATA(cx_http).
ev_error_message = cx_http->get_text( ).
ev_http_status = 500.
CATCH zcx_adf_service INTO DATA(cx_adf).
ev_error_message = cx_adf->get_text( ).
ev_http_status = 500.
CATCH cx_sy_move_cast_error INTO DATA(cx_cast).
ev_error_message = |Cast error: Check Interface Type in ZADF_CONFIG. | &&
|AAD interface must be “Azure Active Directory”. | &&
|Graph interface must be “Microsoft Graph”.|.
ev_http_status = 500.
ENDTRY.
- Each mapped user is appended to et_users as this is the final output table.
The SDK handles all the HTTP complexity like SM59 destination, SSL, retry logic, so this code only needs to focus on what to call and what to do with the result.
3.2 Data Model Design
Step-1: Create a custom entity type in BP Data Model
T-Code: MDGIMG
Path: ->Classic Mode in SAP MDG->Central Governance->General Settings->Data Modeling->Edit Data Model.
Open BP Data Model->Entity Types->New Entries
Entity Type: ZCUS_MAIL
Storage Use Type: 4 – Changeable via Other Entity Type; Generated Database Tables
Active Area: MDG
As there is only one field present in the UI section
Add Attribute: MAIL_ID
Step-2: Create a custom relation for custom entity type with BP_HEADER entity type
From Entity Type: BP_HEADER
Relationship: BP2CUMAIL
To Entity Type: ZCUS_MAIL
Relation Type: LEADING
Cardinality: 1:1
Then, Save the data model, activate and adjust staging area.
STEP-3: Create structures for custom entity type
Classic Mode in SAP MDG->Central Governance->General Settings->Data Modeling->Generate Data Model-Specific Structures
Click on Generate Selected Structures.
STEP-4: Create an Enhancement in GENIL_MODEL_BROWSER transaction
Enter Super enhancement: BUPA_CUSP
Before we create a dependent object, we need a key and attribute structure.
For attribute structure we can use the PP structure generated in the above step
Create a key structure:
In the Genil Model enhancement
Go to: Model->Dependent Object->Create Dependent Object
Enter Dependent Object Name
Enter the above details and click save.
In order to establish relationship with BP_Root
Navigate to Model->Root Object->Root Object BP_Root->Relations->Create Relation
Enter Relation Name and fill the details as shown below
Maintain the cardinality with respect to the relationship cardinality in the data model.
Save the enhancement.
STEP-5: Register the new dependent object in view cluster
Go to SM34 transaction
Open VC_MDG_BS_GENIL_C->BUPA->Node Customizing
Create a new entry
Component Name: BUPA
External Object Name: ZMDG_DO_CUST_MAIL
Entity Type: ZCUS_MAIL
Save the view cluster.
3.3 UI Configuration
In MDG, FPM(Floorplan Manager) is used for UI Configuration. Feeder classes are used as part of the process. For our requirement we will be creating a Form UIBB.
Prerequisites of Form UIBB Creation:
Since the data for the F4 help needs to be retrieved from Azure, a custom feeder class must be created. Otherwise, the standard Form UIBB feeder class can be used.
Go to SE24->Enter Object Name: ZMDG_CL_FEEDER_CUST_MAIL, enter a description and click on Create.
Under Properties provide Superclass: CL_BS_BP_GUIBB_FORM
Save and activate the class.
Further details for F4 help functionality will be discussed as we move forward as of now, we can set up the UI Section. Once the UI section looks as desired then we can work on the F4 help configuration.
STEP-1: Create a form uibb
Go to SE80-> Web Dynpro Components/Interfaces -> FPM_FORM_UIBB_GL2
Click on display
FPM_FORM_UIBB_GL2->Component Configuration->Create
This will navigate to a screen in web browser
Enter Configuration ID: ZMDG_CID_CUST_MAIL and click on Create
Provide a Description
Enter a feeder class: ZMDG_CL_FEEDER_CUST_MAIL.
Enter Feeder Class Parameters:
Component: BUPA
Object Name: ZMDG_DO_CUST_MAIL(from genil dependent object)
Now set the UI Section as you wish this is what I have done in my case:
Save the Configuration
Step-2: Wiring new form uibb with Customer Governance Screen
T-Code: MDGIMG
Path: ->Classic Mode in SAP MDG->Central Governance->General Settings->UI Modeling->Manage UI Configurations.
Search for Application Configuration: BS_OVP_CU and click on Display.
Go to OVP and create an enhancement under other functions
Navigate to Overview Page Schema
Add the name of form uibb configuration id: ZMDG_CID_CUST_MAIL we have created earlier
Now go to Wire Schema and click on + Wire to add a new wire
Connector Class: CL_BS_BP_CONNECTOR_BOL_REL
Fill the details as mentioned above. The Relation Name will be automatically fetched once the Source Config ID and Config ID are defined to have relationship exactly as mentioned during Genil Model Creation.
Save the configuration
3.4 OVS Configuration in Feeder Class
Open feeder class of the form uibb in se24 and redefine the following methods:
IF_FPM_GUIBB_FORM~GET_DEFINITION
IF_FPM_GUIBB_OVS~HANDLE_PHASE_0
IF_FPM_GUIBB_OVS~HANDLE_PHASE_1
IF_FPM_GUIBB_OVS~HANDLE_PHASE_2
IF_FPM_GUIBB_OVS~HANDLE_PHASE_3
GET_DEFINITION METHOD:
This method is redefined to get the fields that are available on the ui screen and assigning a ovs name for required field
Code for reference:
READ TABLE et_field_description
ASSIGNING FIELD-SYMBOL(<lv_field>)
WITH KEY name = ‘MAIL_ID’.
IF sy-subrc = 0.
<lv_field>-read_only = abap_false.
<lv_field>-ovs_name = ‘ZMDG_CL_FEEDER_CUST_MAIL’.
ENDIF.
HANDLE_PHASE_0 METHOD:
This method is used to configure how F4 must look and contain which fields, title of the F4
DATA: lt_column_text TYPE wdr_name_value_list.
APPEND INITIAL LINE TO lt_column_text ASSIGNING FIELD-SYMBOL(<fs_column_text>).
<fs_column_text>-name = ‘FIRST_NAME’.
<fs_column_text>-value = ‘First Name’.
APPEND INITIAL LINE TO lt_column_text ASSIGNING <fs_column_text>.
<fs_column_text>-name = ‘LAST_NAME’.
<fs_column_text>-value = ‘Last Name’.
APPEND INITIAL LINE TO lt_column_text ASSIGNING <fs_column_text>.
<fs_column_text>-name = ‘MAIL_ID’.
<fs_column_text>-value = ‘Mail ID’.
As I need only first name, last name and mail id in the F4 help I have used these 3
Then we will call io_ovs_callback and set configuration method to display search window title, header text of table and column heading text
io_ovs_callback->set_configuration(
window_title = ‘Customer Search’
table_header = ‘Customer Search List from
column_texts = lt_column_text
).
HANDLE_PHASE_1 METHOD:
This method is used to fetch the input parameter if incase the user has entered any value in the ui screen and wants that value to be search in the F4 help
Reference Code:
io_ovs_callback->context_element->get_attribute(
EXPORTING
name = io_ovs_callback->context_attribute ” NAME
IMPORTING
value = ls_input-mail_id ” DATA
).
io_ovs_callback->set_input_structure(
input = ls_input ” The input data
).
HANDLE_PHASE_2 METHOD:
This is the main method for fetching data from Azure System in real time by calling the wrapper class. The output table of F4 search gets filled with data with the help of this method.
Reference Code:
IF iv_field_name = ‘MAIL_ID’.
TRY.
DATA(obj) = NEW zcl_mdg_azure_ad_users( ).
obj->get_all_users(
EXPORTING
iv_aad_interface = ‘DEMO_AZ_AD’
iv_graph_interface = ‘AZ_GRAPH’
IMPORTING
et_users = lt_azure
).
CATCH cx_static_check.
RETURN.
ENDTRY.
LOOP AT lt_azure INTO DATA(ls_azure).
IF ls_azure-mail IS INITIAL.
DATA(lv_azure_user) = ls_azure-user_principal_name.
SPLIT lv_azure_user AT ‘#’ INTO lv_azure_user data(lv_ext).
ls_azure-mail = lv_azure_user.
ENDIF.
APPEND VALUE zmdg_s_cus_mail_dets(
first_name = ls_azure-display_name
last_name = ls_azure-surname
mail_id = ls_azure-mail
) TO lt_result.
ENDLOOP.
lt_final = lt_result.
io_ovs_callback->set_output_table(
output = lt_final ” The output table
).
ENDIF.
HANDLE_PHASE_3 METHOD:
In this method we will make sure that if any entry is selected in the F4 search then that value must be stored in the mail id field of the ui screen.
FIELD-SYMBOLS: <fs_select> TYPE zmdg_s_cus_mail_dets.
ASSIGN io_ovs_callback->selection->* TO <fs_select>.
io_ovs_callback->context_element->set_attribute(
value = <fs_select>-mail_id ” Attribute Value
name = iv_wd_context_attr_name ” Web Dynpro: Name of Context Element
).
Save & activate your feeder class and test the UI for functionality.
Conclusion:
In this blog we walked through each step in detail from retrieving data via a wrapper class all the way to reflecting it on the MDG UI screen. This kind of integration directly reduces the back and forth a user goes through every time they need to verify a master data record against an external system, bringing everything they need onto a single screen within the Change Request itself.
I hope this gives you a clear picture of how an external service like Azure Active Directory can be embedded into SAP MDG governance. Try it out, and if you have questions or feedback feel free to drop them in the comments below.
“}]]
Read More Technology Blog Posts by Members articles
#abap