Skip to Content

In MVC architecture, model unit is responsible for data retention and is independent of the layout and program control units. Business Object Layer (BOL) together with the Generic Interaction Layer (GenIL) is an essential part of the web client architecture because it is responsible for the data management of the user interface components. The BOL is a standard interface to access an object model that consists of a defined quantity of GenIL components and their objects.

 

In this blog I am going to show the steps to create a custom GenIL model.

 

We have a custom table ZBOL_EMPL_MASTER containing the employee details. Here is the structure:

Table.JPG

Our object model will be based on this database table. To create the Object model we need to perform the following steps:

Step 1: Go to transaction SM34 and maintain the view CRMVC_GIL_APPDEF

Maintain View.JPG

     a) Double click on Component Definition and click on New Entries to define the custom component(say Z_EMPL). Maintain an implementation class,say ZCL_GENIL_EMPLOYEE

New Entry.JPG

     b) Double click on Component Set Definition and click on New Entries to define the custom component set(say ZSET_EMPL)

component set.JPG

     c) Assign the component to the component set

assign.JPG

Step 2: Create the following database structures and table types

STR1.JPG

TAB1.JPG

STR2.JPG

Search Attribute.JPG

Step 3: Go to transaction GENIL_MODEL_EDITOR to create the Object model. Give component name as Z_EMPL and click on Change

     a) Right Click on Root Object and select “Create Root Object”, give an object name and maintain the basic settings as shown below

Root Node.JPG

Root Node Basic.JPG

     b) Right click on Dynamic Query Objects and select “Create Dynamic Query Object”. Maintain the object name and the basic settings as shown below

dnamicquery.JPG

queryobject.JPG

Step 4: Create a custom class (ZCL_EMPL_MASTER_API) to hold the API methods to retrieve data from database. Create two public static methods SEARCH_EMPLOYEE and READ_EMPLOYEE with the following parameters

api class.JPG

SEARCH_EMPLOYEE gets the employee keys from the database. IV_STRING contains the where conditions based on which the database query is executed.

 

search employee.JPG

READ_EMPLOYEE accepts the employee key as input and returns employee attributes for the corresponding employee.

 

read employee.JPG

Add the following code:

*************************************************************************************************

method search_employee.
refresh et_results.
if iv_string is not initial.
select employee_id
from zbol_empl_master
up to iv_max_hits rows
into corresponding fields of table et_results
where (iv_string).
else.
select employee_id
from zbol_empl_master
up to iv_max_hits rows
into corresponding fields of table et_results.
endif.
endmethod.

*************************************************************************************************

method read_employee.
select single * from zbol_empl_master into corresponding fields of es_empl_att
where employee_id eq is_empl_key-employee_id.
endmethod.

*************************************************************************************************

You can take any other approach to read the table data, like using FMs.

 

Step 5: Go to transaction SE24 and create the custom class ZCL_GENIL_EMPLOYEE which was mentioned during component definition

·         Maintain CL_WCF_GENIL_ABSTR_COMPONENT as the superclass

Create Class.JPG

·         Redefine the method IF_GENIL_APPL_INTLAY~GET_DYNAMIC_QUERY_RESULT. Add the following code

*************************************************************************************************

method if_genil_appl_intlay~get_dynamic_query_result.
data: lr_msg_cont type ref to cl_crm_genil_global_mess_cont,
lv_num_hits type i,
lt_results type zbol_empl_master_key_tab,
lv_max_hits type char5,
lv_max_hits_tmp type int4,
lr_root_object type ref to if_genil_cont_root_object,
lt_request_obj type crmt_request_obj_tab.
field-symbols: <fs_results> type zbol_empl_master_key.
* Retrieve the message container to log eventual messages
lr_msg_cont = iv_root_list->get_global_message_container( ).
* When the max hits is set to 0.
if is_query_parameters-max_hits is initial.
lv_max_hits_tmp = 100. “100 when no max_hits is set
else.
lv_max_hits_tmp = is_query_parameters-max_hits.
endif.
* select the rigth query
case iv_query_name.
when ‘SearchEmployee’.
* Call the API and get the result.

call method search_employee
exporting
it_search_criteria = it_selection_parameters
iv_max_hits        = lv_max_hits_tmp
importing
et_results         = lt_results.

if lt_results is not initial.
* Log a message if search result exceed the max hit limit
describe table lt_results lines lv_num_hits.
if lv_num_hits > lv_max_hits_tmp.
lv_max_hits = lv_max_hits_tmp.
lr_msg_cont->add_message( iv_msg_type = ‘I’
iv_msg_id = ‘ZBOL_MSG’
iv_msg_number = ‘000’
iv_msg_v1 = lv_max_hits
iv_show_only_once = abap_true ).
endif.
* Loop through the results to build search result objects
loop at lt_results assigning <fs_results>.
try.
* Try to create a new result object
lr_root_object = iv_root_list->add_object(
iv_object_name = ‘EMPLOYEE’
is_object_key = <fs_results> ).
* Flag it as direct query result
lr_root_object->set_query_root( abap_true ).
catch cx_crm_genil_duplicate_rel cx_crm_genil_model_error.
* Since the given object name is correct this could not happen!
endtry.
endloop.
* Note: The request object restricts the attributes to read.
* If there is no request object entry or the attributes
* table is empty all attributes are requested.
* read the attributes and relation using the GET_OBJECTS
me->if_genil_appl_intlay~get_objects( it_request_objects = lt_request_obj
iv_root_list = iv_root_list ).
else.
lr_msg_cont->add_message( iv_msg_type = ‘W’
iv_msg_id = ‘ZBOL_MSG’
iv_msg_number = ‘001’
iv_show_only_once = abap_true ).
endif.
when others.
return.
endcase.
endmethod.

*************************************************************************************************

·         Redefine the method IF_GENIL_APPL_INTLAY~GET_OBJECTS

*************************************************************************************************

method if_genil_appl_intlay~get_objects.
data lv_root type ref to if_genil_cont_root_object.
data lv_empl_key type zbol_empl_master_key.
data lv_empl_att type zbol_empl_master_attr.
data lv_temp_att type zbol_empl_master_attr.
lv_root = iv_root_list->get_first( ).
while lv_root is bound.
lv_root->get_key( importing es_key = lv_empl_key ).
* Check if attributes should be read
if lv_root->check_attr_requested( ) = abap_true.
zcl_empl_master_api=>read_employee(
exporting is_empl_key = lv_empl_key
importing es_empl_att = lv_empl_att ).
* Return the object only if it still exists
if lv_empl_att is not initial.
* Put attributes to the container
lv_root->set_attributes( lv_empl_att ).
* You could set attribute properties like readonly.
endif.
endif.
** check if dependent objects should be read
*    IF lv_root->check_rels_requested( ) = abap_true.
** process the directly dependent objects
*      process_children( it_requested_objects = it_request_objects
*      iv_root = lv_root ).
*    ENDIF.
*    “process foreign relations
*    process_foreign( iv_root = lv_root ).
*    “continue with the loop
lv_root = iv_root_list->get_next( ).
endwhile.
endmethod.

*************************************************************************************************

·         Create a Public Instance method SEARCH_EMPLOYEE with the following parameters

search.JPG

Add the following code

*************************************************************************************************

method search_employee.
data: lv_max_hits type i,
lv_string type string,
lt_search_criteria type genilt_selection_parameter_tab,
lv_last_attr_name type name_komp.
field-symbols: <search_criteria> type genilt_selection_parameter.
* NOTE:
* This is a good place to implement Authority checks!!!
*
lv_max_hits = iv_max_hits.
if lv_max_hits eq 0.
lv_max_hits = 100.
endif.
lt_search_criteria = it_search_criteria.
sort lt_search_criteria by attr_name.
loop at lt_search_criteria assigning <search_criteria>.
* NOTE: * The current implementation takes care only of CP and EQ search criteria options.
if ( <search_criteria>-option eq ‘CP’ or <search_criteria>-option eq ‘EQ’ ).
if lv_string is not initial.
if <search_criteria>-attr_name ne lv_last_attr_name.
concatenate lv_string ‘) AND (‘ into lv_string separated by space.
else.
concatenate lv_string ‘OR’ into lv_string separated by space.
endif.
else.
lv_string = ‘(‘.
endif.
concatenate lv_string <search_criteria>-attr_name <search_criteria>-option into lv_string separated by space.
concatenate lv_string <search_criteria>-low into lv_string.
concatenate lv_string into lv_string.
endif.
lv_last_attr_name = <search_criteria>-attr_name.
endloop.
refresh et_results.
if lv_string is not initial.
concatenate lv_string ‘)’ into lv_string separated by space.
endif.
* retrieve data from the backend
call method zcl_empl_master_api=>search_employee(
exporting
iv_string   = lv_string
iv_max_hits = lv_max_hits
importing
et_results  = et_results ).
endmethod.

*************************************************************************************************

 

Our GenIL component is ready for test.

 

To test whether the Genil Object is working properly or not go to transaction GENIL_BOL_BROWSER, give component name Z_EMPL and execute. The dynamic query object ‘SearchEmployee’ will be present in Model Browser Search Objects window. Double click on it to get the search window, where you can enter search parameters and click on FIND.

Databse entries are shown in the List Browser window based on the query parameters. Double click on the individual object to see the details.

 

In my next blog I will use this GenIL component set to create a custom component with search view, result view and overview page.

To report this post you need to login first.

19 Comments

You must be Logged on to comment or reply to a post.

  1. Gokul Ragunathan

    Hi Sayan,

      I could not find the transaction code ‘GENIL_MODEL_EDITOR’ in my system(SAP CRM 7.0). Is there any alternative for this ?

    Thanks & Regards

    Gokul Ragunathan

    (0) 
    1. SAYAN SUBHRA JANA Post author

      Hi Gokul,

      You can also edit the model in transaction GENIL_MODEL_BROWSER. Open the custom component you created here in change mode.

      Regards,

      Sayan

      (0) 
      1. Gokul Ragunathan

        Hi Sayan,

          Thanks for you quick response… 🙂

          

           In GENIL_MODEL_BROWSER tode, i could no where find the change/edit option. I have Execute option. I checked toolbar options also. Is there any settings or configuration to be done to edit model using GENIL_MODEL_BROWSER

        Thanks & Regards

        Gokul Ragunathan

        (0) 
        1. SAYAN SUBHRA JANA Post author

          Hi Gokul,

          I am not sure why you are not getting the change option.

          In transaction GENIL_BOL_BROWSER we have an execute button, whereas in transaction GENIL_MODEL_BROWSER we have 3 buttons, Display, Change and Create.

          If you still can’t access the browser there is an alternative way to achieve my mentioning model and value tables in component definition.

          Follow the link: http://wiki.sdn.sap.com/wiki/display/CRM/Create+a+Z+BOL+Object+Part+1

          Regards,
          Sayan

          (0) 
  2. Juan Jose Cruz

    Hi Gokul,

    Are you on EHP1?? The GENIL_MODEL_EDITOR and the change option in transaction GENIL_MODEL_BROWSER are only available on EHP1 ( If I´m not wrong X-D)

    (0) 
  3. Suchita Phulkar

    Nice Document But with EHP1 AET table extensions, the same job can be done in few minutes with absolutely no coding required.

    Still, this document explains the basic and i appreciate your efforts.

    Good Job Gokul !!

    (0) 
    1. Nikhil Prateek Kulkarni

      Nice Document indeed.

      But one thing which is missing here is the clear seperation from BOL Modeling and Genil coding. It is although very informative but often puts lots of burden on any fresher who is starting SAP CRM WEBUI stuffs.

      THank and Regards,

      Nikhil Kulkarni

      (0) 
        1. Sumeet Gehlot

          Hi ,

          For this you need to debug standard code in get_query_defination method of cl_crm_bol_query_class and need to find out the database table.

          Regards,

          Sumeet

          (0) 

Leave a Reply