One thing I have learned over the years with HCM P&F is:
"When all else fails, use an Advanced Generic Service!"
...Sounds great, eh? However, one of the biggest hurdles was first learning how in the heck to even create a working Advanced Generic Service. It seemed like it was some great guarded secret by SAP. To make matters worse, in the "early days" of HCM P&F, there were no examples to even go by...just some very confusing documentation (that still exists today! haha). Thankfully, through the help of people like SAP's own Michael Bonrat (who headed up HCM P&F in its infancy) and fellow consultant, Derrick Banks, I was able to figure out Advanced Generic Services (AGS) and begin to use them to solve more complicated issues (for example, working around some of the early bugs in the HCM P&F framework and/or handling infotypes it could not handle correctly).
That was long ago for me. I thought that over the years SAP would roll out more examples and information about Advanced Generic Services and the "pain" I went through would not be suffered by others who came after myself and the early HCM P&F crowd. Sadly, I was mistaken. How to implement and use AGS is still something that comes up all the time. It still is not covered well by SAP in my opinion. Therefore, I am hoping this blog will help to end that for a LOT of people....so here we go....
First off, you should already know how and where to use regular "generic services". They are typically used for more of our "interactive-ness" of HCM P&F. We use them to manipulate form field values such as adding one day to a date, reading values from custom tables, handle user events in configuration, take care of any special business logic for form field validations for data coming back from the user, or anything else that can be repeated without much real harm.
However, when it comes to making actual backend updates (create, update, or delete) , this is where you will want (and need) to use Advanced Generic Services (AGS)...and then only when the SAP supplied services (SAP_PA, SAP_PT, or SAP_PD) do not meet your needs.
One more major thing to know before doing updates with your AGS....from SAP:
The SAP LUW is controlled solely by the framework. Therefore, it is not permitted to execute COMMIT WORK or ROLLBACK WORK in the FLUSH method or any other method. Similarly, you are not allowed to call external coding (function modules, classes, programs, and so on) that could possibly execute COMMIT WORK or ROLLBACK WORK.
So how do we use them correctly for updates? It really is as simple as a three step process:
- set an instanced "ID" attribute value in the "do operations" method of your service
- use the instanced "ID" value to retrieve your form scenario's step/stage's form container values (ie. get all the current form fields and their values) in the "flush" method of your service.
- code for you updates based on your form field values
Let us look at this in a bit more detail. I will show you two methods for doing this.
- using the "step GUID" (the "newer" way)
- using the "process reference number" (which is
the older way we had to do this before the framework set our "step
GUID" for us)
Using STEP GUID
There are a handful of fields that the HCM P&F framework will handle for you if you define them in your form scenario fields. One of these is STEP_OBJECT_ID. You can define it in your form fields like:
...defined as type ASR_GUID...
We can look at the ONE example from SAP of a AGS on how this is used. Look at the AGS implementation, HRMSSRCF_REQUISITION_ADVANCED. If we look at the class, CL_IM_HRRCF_REQUI_REQUEST, we can see how they defined "STEP_GUID".
This field is mapped in the process HR_MSSRCF_REQUISITION to the backend service (the AGS) as:
When the "do operations" of this service are triggered (during "check and send" for example), within the "do operations" method, we simply set the STEP_GUID attribute value:
Then in FLUSH.... IF_HRASR00GEN_SERVICE_ADVANCED~FLUSH...we simply use this "step guid" to go re-locate our form's data container. The SAP AGS does not show a good example of this (though it does show a good one for getting attachment data!). Therefore, here is an example of something we could do to get our form fields:
Using PROCESS REFERENCE NUMBER
We can also do something similar simply using our "process reference number". In our form scenario fields, this is always handled for us (ie. filled in) by the HCM P&F framework engine. We simply define this in our form fields:
...defined as type ASR_REFERENCE_NUMBER...
In our Advanced Generic Service, much like using the "step guid", we can define an attribute of our AGS class as:
Then in our "Do Operations", we simply "set" this attribute's value just like we did for "step GUID". For example,
*** Get the New Reference Number:
*** We execute this logic so once the new reference number is set, we can pass it to the Advanced Service method FLUSH.
LOOP AT service_datasets INTO sd_wa WHERE fieldname = 'REFERENCE_NUMBER'.
w_ref_num = sd_wa-fieldvalue.
IF NOT w_ref_num IS INITIAL.
me->att_reference_number = w_ref_num.
Then in our FLUSH method, we would simply use this process number to locate our container to retrieve all of our current form fields. You can make this a bit easier by creating a class to read your container based on the reference number/GUID passed.
For example, we could use this like:
wa_ref_num = me->att_reference_number. "<-- For Advanced Service
** Get the data container values for the Reference Number
CALL METHOD zcl_hr_process_and_forms_01=>get_form_container_data
in_refid = wa_ref_num
message_handler = message_handler
tbl_data_container = form_data_containers.
Then it is as easy as something like...
DATA wa_begda TYPE datum.
READ TABLE form_data_containers WITH KEY fieldname = 'EFFECTIVE_DATE'
READ TABLE form_data_container-fieldvalues
INTO field_value INDEX 1.
wa_begda = field_value.
...to read actual form field values.
Our class code for getting the container correctly would look something like:
From here, you can handle your updates however you like. For example, you could handle PA infotype updates that SAP_PA might not handle well/correctly or include additional business logic that you need.
In the "old" days of HCM P&F for PA related updates using the decoupled infotype framework, we had to duplicate a lot of code to make it happen like SAP_PA would do it. We had to handle the references to the master data "factory", handle our containers, handle getting our structure references, and much more. For example, say we wanted to just update infotype 0035, it would look something like:
Thankfully, we now have the nice little function, HR_CONTROL_INFTY_OPERATION, which handles everything for us and knows whether to use the newer decoupled way or the older "infotype operations" way of doing things. Funny enough, the comments in the function call this the "new infotype framework (NITF) " and the "old infotype framework (OITF)". haha
Similarly, you could handle updates to your own custom "Z" tables or really anything else you might need here in the FLUSH method.
So that is about it. Nothing really magical or secretive to it at all. Hope this helps! As always....till next time....enjoy!