step by step to enable your Genil component with AET – Part Two
in part1 we discuss about:
1. How to enhance your genil component ( create a new Dependent object and corresponding DDIC structure ) to support AET
2. how to create a new UI object type
3. Create necessary EEW include structure and respective DB table to store FE transaction data.
In this part2 I will show you how to enhance the Genil component implementation class.
step1: support read access. If there is transaction data stored in DB table ZCRM_SOC_FE, it must be fetched and displayed in UI accordingly.
The read access is done in genil implementation class method IF_GENIL_APPL_INTLAY~GET_OBJECTS.
The original code before enhancement is using handler style. Every node has its corresponding handler class to do the job.
The handler class for SocialPost is ZCL_CRM_SOC_POST, which means in order to support read access of extension fields, we need to enhance ZCL_CRM_SOC_POST->READ_OBJECT.
lr_object = go_handler_factory->get_handler( iv_object_name = lv_name ). TRY. lr_post ?= lr_object. CATCH:cx_sy_move_cast_error. EXIT. ENDTRY. CHECK lr_post IS NOT INITIAL. CALL METHOD lr_post->read_object EXPORTING it_request_objects = it_request_objects iv_ref = iv_root_list CHANGING ct_bapireturn = lt_bapireturn.
This blog will not go deep into the Genil component implementation itself, but just focus what needs to be enhanced in Genil component implementation.
as you see, I just add the code surrounded with red to read the extension field data. I pass the reference of container object into method get_fe_data.
After that method is executed, the extension field data will be fetched and filled into the container object lo_post.
method GET_FE_DATA. data: lv_guid TYPE crmt_genil_object_guid, lv_attr TYPE ZCRM_EXT_SMC_DYNP_SV, lv_convert_guid TYPE socialdata-socialdatauuid, lv_post_id TYPE socialdata-internal_id. data(lv_children) = iv_container->GET_CHILDREN( IV_AS_COPY = ABAP_TRUE ). data(lv_child) = LV_CHILDREN->GET_FIRST( ). ASSERT lv_child IS BOUND. iv_container->get_key( IMPORTING es_key = lv_guid ). lv_convert_guid = lv_guid. lv_attr = zcl_crm_soc_fe_buffer_access=>get( lv_convert_guid ). lv_child->set_attributes( lv_attr ). DATA(lv_attr_props) = lv_child->get_attr_props_obj( ). lv_attr_props->set_all_properties( if_genil_obj_attr_properties=>changeable ). SELECT SINGLE internal_id INTO lv_post_id FROM socialdata WHERE socialdatauuid = lv_convert_guid ASSERT sy-subrc = 0. data(ls_key) = VALUE ZCRM_EXT_SMC_KEY( client = sy-mandt post_id = lv_post_id ). lv_child->set_key( ls_key ). endmethod.
in get_fe_data, there is nothing special logic inside. The real data is returned via zcl_crm_soc_fe_buffer_access, which encapsulate the buffer handling of extension field data in current session.
so let’s have a look at the buffer class zcl_crm_soc_fe_buffer_access’s get method:
method GET. DATA: ls_data TYPE ZCRM_SOC_FE, ls_attr TYPE ZCRM_EXT_SMC_DYNP_SV. READ TABLE st_buffer ASSIGNING FIELD-SYMBOL(<buffer>) WITH KEY uuid = iv_guid. IF sy-subrc = 0. rs_data = <buffer>-data. RETURN. ENDIF. SELECT SINGLE * INTO CORRESPONDING FIELDS OF ls_data FROM ( ZCRM_SOC_FE AS A INNER JOIN socialdata AS B ON B~internal_id = A~post_id ) WHERE B~SOCIALDATAUUID = iv_guid. CHECK ls_data IS NOT INITIAL. MOVE-CORRESPONDING ls_data TO ls_attr. DATA(ls_entry) = VALUE ty_buffer( uuid = iv_guid data = ls_attr ). APPEND ls_entry TO st_buffer. rs_data = ls_attr. endmethod.
first check in the buffer table whether there is already an entry there for the current social post. If buffer hits, the bufferred data is directly returned.
If not, just load it from DB table. Why I use inner join is the type of buffer table has uuid as key, not internal id. And the uuid is the key field of hosting table of Social post, that is SOCIALDATA.
After the data is loaded from DB, never forget to insert it into buffer table.
types: BEGIN OF ty_buffer, uuid TYPE socialdata-socialdatauuid, data TYPE ZCRM_EXT_SMC_DYNP_SV, END OF ty_buffer . types: tt_buffer TYPE STANDARD TABLE OF ty_buffer WITH KEY uuid .
now the read access of extension fields are done.
step2: write access.
After we type some value in UI fields and click enter key, IF_GENIL_APPL_INTLAY~MODIFY_OBJECTS will be called. Just the same logic as step1, the call will be delegated to handler class ZCL_CRM_SOC_POST. In method MODIFY_OBJECT, I only add one more line to handle with extension fields by creating a new method process_children.
for simplicity reasons I only react on the change mode. Again I pass the call to zcl_crm_soc_fe_api.
in set_fe_data I just put the list of changed attribute ( lt_changed_attr ) and the latest data typed by user ( ls_attributes ) to buffer class.
in set method of buffer class, again the similiar logic as done in read case. First check in the buffer table whether there exists an entry for current social post.
If buffer hits, I just to update the buffer with latest extension fields data. I loop the internal table it_changed_attr to make sure all changed attributes are handled.
if there is no entry in the buffer, the situation should be that such post has not any extension fields stored in DB table at the begining of this transaction.
The iv_new_data would come from the manual input typed by user in UI. In this case all I need is just to append the latest extension field data into the buffer table.
step3: save case.
No doubt the method SAVE_OBJECT of ZCL_CRM_SOC_POST must now take care the saving of both SocialPost itself and extension fields data as well.
I just add two more lines to original code.
I first save the extension field( done by zcl_crm_soc_fe_api=>save_fe_data), then the SocialPost itself ( via function module SOC_POST_SAVE ).
The condition “no value changed” is enhanced that only the situation neither Socialpost nor its extension fields are changed could be regarded as no value changed. If the line 18 is missing, you will receive message in UI “No value changed”, even you have already modified some extension field but not touch standard field in social post itself.
The method save_fe_data is also very simple: just fetch the extension field buffer from buffer table and then modify database table.
DATA: ls_change TYPE ZCRM_SOC_FE.
DATA(ls_buffer) = zcl_crm_soc_fe_buffer_access=>get( iv_guid ).
CHECK ls_buffer IS NOT INITIAL.
MOVE-CORRESPONDING ls_buffer TO ls_change.
MODIFY zcrm_soc_fe FROM ls_change.
rv_fe_changed = abap_true.
The genil component implementation is enhanced regarding following three parts:
1. enhance IF_GENIL_APPL_ALTERNATIVE_DSIL~SAVE_OBJECTS to support extension field save.
2. enhance IF_GENIL_APPL_ALTERNATIVE_DSIL~MODIFY_OBJECTS to support extension field change.
3. enhance IF_GENIL_APPL_ALTERNATIVE_DSIL~GET_OBJECTS to support extension field change.
Now it’s time to enjoy our labour! Just create three extension fields to test. The three extension fields has type Quantity and sub type PRESS ( built-in type provided by SAP), so AET framework automatically creates two seperate fields for you, one for quantity value and the other for unit.
Those features like F4 help and validation logic for respective data type are automaitcally handled by AET framework. You do not need to code by yourself 🙂
Now have a look at the EEW structure created in part4. All extension fields are attached here.
And extension fields data are stored in DB.
Hi Jerry Wang,
Thanks for a lot for sharing knowledge. Very good article and amazing...Keep rocking..
I am glad you like it 🙂