HCM Processes & Forms: The Secrets of Search Helps and OADP….REVEALED! – part 5
This is the continuation of the previous blog (part 4) where we covered using Search Helps in our forms.
OADP “engine” Component
So we covered how the pop-up window is triggered and how the selected values return to the form, but how does all the “magic” in the middle happen….the display of our data based on our searches?
The “Search Help” WDA component actually contains another WDA component called OBJECTDATAPROVIDER. This is the actual “workhorse” of the Search Help.
(*note, you can test this component using SE80 and running the WDA examples OADP_EXAMPLE and OADP_TEST. You may need to refer to SAP note 1109215 if these do not exist in your SICF.)
Our Search Help WDA calls this component first in it’s method CALL_POPUP.
CALL METHOD lr_oadp->init_data_from_orgviewgroup(
cache_maxage = 1 “update data once a day
data_begda = sy–datum
data_dest = ‘NONE’ “read the data from own system
data_endda = sy–datum
hide_dropdown_for_single_views = abap_true
initial_ui_settings = lr_ui_settings
instance_id = ‘SEARCH_ORGUNIT’
objects_begda = sy–datum
objects_endda = sy–datum
orgviewgroup = l_orgviewgroup
user = sy–uname ).
This is where it tells the OADP component which OADP “Structural Org Group View” from configuration that we wish to use. For our example, this is l_orgviewgroup value is “ASR_ORG_SEARCH”.
Once the window is up and the user makes selections (which again, came from our HR_SELECTIONS “sel_id” value), the user clicks”start” to execute their search. This fires the method ONACTIONSTART_SEARCH in view NAVIGATIONVIEW which in turn calls the Component Controller’s method EXECUTE_OBJECT_SEARCH. This method inspects our search fields and their values. It also calculates the number of “hits” (l_total_hits), the starting point in our paging (l_start_index) and the numberof hits shown at once in the ALV table(l_package_size). From this is constructs our results message (for example, “ 1116 Hits Found Hits 1 to 10 Are Displayed “)
Then, this code executes the actual “search”:
* execute search
call method wd_this->model->execute_object_search
exporting paging_direction = paging_direction
importing error_msg = l_error_msg.
Executing the Search
This calls the class CL_OADP_MODEL method EXECUTE_OBJECT_SEARCH which fires:
* execute the search
update_objects( importing error_msg = error_msg ).
This in turn calls function hrwpc_rfc_oadp_exec_objsearch of function group HRWPC_OADP_UI.
CALL FUNCTION ‘HRWPC_RFC_OADP_EXEC_OBJSEARCH’ destination m_data_dest
OBJSEL = m_objsel
XADVANCEDSEARCH = m_adv_search_on
BEGDA = m_objects_begda
ENDDA = m_objects_endda
USER = m_user
* LANGU = SY-LANGU
CACHEMAXAGE = m_cache_maxage
HITPACKAGESIZE = m_search_package_size
HITPACKAGESTARTINDEX = m_search_start_index
TOTALHITS = m_search_total_hits
* READDATE =
* READTIME =
T_PARAMVALUES = mt_application_params
T_SEARCHVALUES = mt_search_values
T_SEARCHOBJECTS = mt_objects
OBJSEL_NOT_FOUND = 1
OBJECTSELECTION_INVALID = 2
OTHERS = 3
This function finds our “Search Class” based on the “OADP Structural View Group” ID we passed (ie. ASR_ORG_SEARCH). It also reads our application parameters and checks to see if we are doing the same search as a previous one (checks cache) to avoid doing it again. If the search is not cached, it fires our search.
So this function knows our search class and what application parameters we want to use but how does the ACTUAL search happen?
Calling our Search Class
Keep in mind, because our “Search Class” CL_HRWPC_SEARCH_VIA_SELID implements the interface IF_HRWPC_OADP_OBJECTSEARCH , this code simply calls the method which in turn calls the method IF_HRWPC_OADP_OBJECTSEARCH~EXECUTE_SIMPLE_SEARCH as implemented in our class.
Remember, we passed it a parameter called “SIMPLE_SEARCH_SELID” with a value “ASR_ORG_SEARCH”. Inside that class, it takes this value as a “selection ID” (ie. SEL_ID).
DATA: l_selid TYPE hr_selid.
DATA: ls_paramvalue TYPE hrwpc_s_oadp_paramvalue.
* clear result
* get sel_id from search params
READ TABLE t_paramvalues INTO ls_paramvalue
WITH KEY paramname = ‘SIMPLE_SEARCH_SELID’.
IF sy–subrc <> 0.
l_selid = ls_paramvalue–paramvalue.
CALL METHOD cl_hrwpc_search_via_selid=>get_searchfields_from_selid
sel_id = l_selid
langu = langu
t_searchfields = t_searchfields.
Remember that the “Selection ID” is used not only to tell our “OADP” WDA component how to build our “search options” in the NAVIGATIONVIEW but it also is used here in order to determine our “search fields” and values as well.
We can see this SELECTION ID (aka. SIMPLE_SEARCH_SELID, aka. SEL_ID) in action as configured. Go to transaction SM34 and enter “HR_SELECTIONS”.
We can see what fields are selected under “Table”:
This is what lays out our “Search Field” in the “OADP” OBJECTDATAPROVIDER WDA component’s NAVIGATIONVIEW view. As we see…
After the user clicks the “Start” button, this executes the search in the Search Class’ method IF_HRWPC_OADP_OBJECTSEARCH~EXECUTE_SIMPLE_SEARCH as mentioned above. This then calls method EXECUTE_SELID which calls function HR_COMBINED_SELECTION that does the work of looking it up in HRP1000:
CALL FUNCTION ‘HR_COMBINED_SELECTION’
The results are just our OBJIDs that match the selection:
The data is looped and “enriched” into table T_RESULT_OBJECTS. This appears as:
Some code is in place to check if the “user” is to be excluded from the result set (in the case of a manger for instance).
The “results” are then run through another function to generate “object keys” (ie. give each row a unique “index” number”. This is the first column shown as “OBJ_KEY”.
As explained earlier, after the “search” is handled and model is set (class CL_OADP_MODEL), control returns to the OBJECTDATAPROVIDER WDA component’s Component Controller method EXECUTE_OBJECT_SEARCH. Here, some other bits of code follow to calculate “hits” and number of results to display per “package size” (ie. 10 rows in table at a time). Lastly, the timestamp is calculated. This is all passed back to the “wrapper”/engine WebDynpro ABAP.
But how is the results table display determined? How does it know what data to show in what column and how to name them?
Merging the Data with our OADP Columns
Look at WDA component OBJECTDATAPROVIDER. In controller method EXECUTE_OBJECT_SEARCH, look at call to method change_dataview. It builds our columns and fills them with data:
* create the new column context
* fill new data in column context
First, it sets our “model” (class CL_OADP_MODEL) with the call to method UPDATE_DATAVIEW. This calls function HRWPC_RFC_OADP_EVAL_DATAVIEW which calls function HRWPC_OADP_CHECK_DATAVWCACHE to determine our column metadata and contents.What happens in here is a LOT of write/reads/extracts from memory…..not for the timid (and actually not really much we need to be concerned with).
This looks at:
…and the content for each “column”…
But how does it know of all this data WHAT to put into each column shown?
FM for Column Contents
Remember our column configuration…..
If you look, you can see that we defined our content for the column to be determined by function HRWPC_FILL_STANDARD_COLUMNS(FM for Column Contents).
From SAP documentation:
“If the column content is to be determined in the backend system, enter a function module that is to get the column content. To create a function
module of your own, use the function module HRWPC_CB_CONTENT in the standard system as a template. You must use this as a template since your function module must have the same interface as the function module in the standard system.”
The function HRWPC_FILL_STANDARD_COLUMNSlooks at our “column name” and then determines what field this maps to in our data.
For example, our column name “ORG_STEXT_JS” maps over to STEXT. Actually, it looks to see if STEXT is empty or not and will try to map it to SHORT if STEXT is not available.
if KEY_OBJECTS–STEXT is initial.
column_content–content = KEY_OBJECTS–SHORT.
column_content–content = KEY_OBJECTS–STEXT.
Likewise, our other column name, “ORG_OBJID_2” similarly maps to field REALO.
With our columns defined (“how” to display to users) and the content for those columns defined (“what” to display for users), we finally get:
In Part 6, we wrap this all up….this series comes to an end!…