Technical Articles
Debug background steps using endless loop with User Profile parameter in MDG.
Purpose:
Debug Rule based workflow in MDG for Agent Determination and System Method Caller in real time using endless loop with the help of User Profile Parameter.
Introduction:
We all know that the most-often-used Agent Determination, System Method Caller and Material Enrichment BAdIs in MDG are called in the background step asynchronously. If anyone wants to debug them, it’s not possible in foreground. However, SAP has provided class CL_USMD_WF_SSW which can be used for debugging methods CALL_SYNCH_SYST_METHOD and FIND_PATH_PROCESSOR for system method caller and agent determination respectively after the CR is submitted. The only way to debug them during runtime is by adding an endless loop in the said BAdIs in the dev systems. But if we want to debug in runtime in a non-development environment (read Quality and Preprod), then it becomes kind of little difficult. So, here’s a way out to deal with this problem – add an endless loop that can be controlled using a User Profile Parameter.
How it’s achieved:
Pseudo Code:
Create a user parameter in table TPARA. Let’s name it as ZBGRND_DEBUG.
- Check if the Change Request number exists in table USMD120C. The table will always have CR number at the time of agent determination and/or CR submission.
- Get the user id of the person who created this CR and have ZBGRND_DEBUG set as X in the user profile parameter.
- Run endless loop.
- If CR number not found in step 1, get the user id from Governance API and/or Convenience API.
- Check if the instances of Governance and Convenience API exists.
- If an instance of Governance API exists and Convenience API not, then get the user id from GOV API else from CONV API.
- Else, use SY-UNAME.
- Run endless loop.
Here’s the code:
Importing Parameter: IM_CR_NUMBER OPTIONAL
METHOD background_debug.
IF im_cr_number IS NOT INITIAL.
DATA(lv_cr_number) = im_cr_number.
ELSE.
* Get CR Number from App Context.
lv_cr_number = cl_usmd_app_context=>get_context( )->mv_crequest_id.
ENDIF.
SELECT SINGLE @abap_true
FROM usmd120c
WHERE usmd_crequest = @lv_cr_number
INTO @DATA(lv_cr_exists).
* If the CR is found, check user parameter of the id who created this CR.
IF sy-subrc = 0 AND lv_cr_exists = abap_true.
DO.
SELECT SINGLE
a~usmd_created_by,
b~bname,
b~parid,
b~parva
FROM usmd120c AS a
JOIN usr05 AS b
ON b~bname = a~usmd_created_by
WHERE a~usmd_crequest = @lv_cr_number
AND b~parid = 'ZBGRND_DEBUG'
INTO @DATA(lst_cr_usr_param).
IF lst_cr_usr_param-parva = space.
EXIT.
ENDIF.
ENDDO.
* If the CR is not yet submitted, then get CR details from CONV API.
* This case occurs when Rule Service BAdI is called from DIF
ELSE.
* Get Model from App Context.
DATA(lv_model) = cl_usmd_app_context=>get_context( )->mv_usmd_model.
* Check if instance of governance API exists.
DATA(lv_flg_gov_api) = cl_usmd_gov_api=>check_instance_exists(
iv_model_name = lv_model ).
* Check if instance of convenience API exists.
DATA(lv_flg_conv_api) =
cl_usmd_conv_som_gov_api=>check_instance_exists(
iv_model_name = lv_model ).
TRY.
* If governance API exists and convenience API does not, then use GOV API.
IF lv_flg_gov_api = abap_true AND lv_flg_conv_api = abap_false.
DATA(lo_gov_api) = cl_usmd_gov_api=>get_instance(
iv_model_name = lv_model ).
IF lo_gov_api IS BOUND.
* Get the id who created Change Request.
DATA(lv_created_by) =
lo_gov_api->get_crequest_attributes(
iv_crequest_id = lv_cr_number )-usmd_created_by.
ENDIF.
* Else use convenience API
ELSE.
* Get the instance of Convenience API
DATA(lo_conv_api) = cl_usmd_conv_som_gov_api=>get_instance(
iv_model_name = lv_model ).
IF lo_conv_api IS BOUND.
* Set the change number in Convenience API
lo_conv_api->set_environment(
iv_crequest_id = lv_cr_number
).
* Get the id who created Change Request.
lv_created_by =
lo_conv_api->get_crequest_attributes( )-usmd_created_by.
ENDIF.
ENDIF.
CATCH cx_usmd_conv_som_gov_api .
CATCH cx_usmd_app_context_cons_error .
CATCH cx_usmd_conv_som_gov_api_env.
CATCH cx_usmd_gov_api .
* If any error, then use SY-UNAME for endless loop.
lv_created_by = sy-uname.
ENDTRY.
* Run endless loop.
DO.
SELECT SINGLE
bname,
parid,
parva
FROM usr05
WHERE bname = @lv_created_by
AND parid = 'ZBGRND_DEBUG'
INTO @DATA(lst_usr_param).
IF lst_usr_param-parva = space.
EXIT.
ENDIF.
ENDDO.
ENDIF.
ENDMETHOD.
Call this method in the implementation of BAdIs USMD_SSW_SYSTEM_METHOD_CALLER, USMD_SSW_DYNAMIC_AGENT_SELECT, USMD_SSW_RULE_CONTEXT_PREPARE, etc. as
zcl_mdg_utilities=>background_debug( lv_cr_id ).
Now set parameter ZBGRND_DEBUG = X in the user profile to enable background debugging.
Run NWBC and create a Change Request for Material/Customer/Vendor. You’ll see the CR is created but the workflow is still not completed. Execute transaction SM50 where you’ll see this class is waiting for your attention. Select the workprocess and start debugging.
Note: Don’t forget to switch it off when not required!
Caution: PLEASE DON’T SET THIS PARAMETER IN PRODUCTIVE ENVIRONMENT.
Conclusion:
As mentioned earlier, debugging the said asynchronous methods in MDG can be achieved using the standard SAP class CL_USMD_WF_SSW after the CR is submitted but a layer of flexibility can be added by using controlled endless loop which enables us to debug at runtime.
People might raise concerns about the usage of endless loop in productive environment, but don’t the Security folks there turn debugging off and add an array of authorization checks already? All in all, I’d say please use it judiciously.
Some places where this solution could be used:
- BAdIs in Enhancement Spot USMD_SSW_SERVICE_PROCESSOR.
- BAdIs in Enhancement Spot USMD_RULE_SERVICE when called from DIF.
- BAdI MDG_BS_MAT_API_ENRICH_BADI, etc.
NM: Another great blog post by Jerry Wang is worth spending time on!
Very Informative, Great Work Aasim !!