Introduction:
I tried searching the web regarding “node class” of BOPF framework, I found very little information. Hence, I explored it and thought to share my findings in the community, which will help someone who is new to the framework. So in this blog post, we will see the use of “Node Class” in a BOPF Node. We will discuss its functionality, the required API, and all related information. Below is the screenshot where the node class is maintained.
Image depicting the place to mention node class for a node
Uses of the Node Class:
The use of the node class is to default the values in the attribute of the node. For example, let’s say for the BO “Purchase Order”, we want to default the document date as “System Date”. Or, for example, in the risk assessment, we want to default the status as ’01′(New). In this case, we should use the “Node Class”.
Node Class API:
A node class should implement the interface “/BOBF/IF_FRW_NODE”. It contains 2 methods.
◉ RETRIEVE_DEFAULT_VALUES
◉ SET_NODE_CATEGORY -> This method is obsolete now
The logic for the default value should be written in the method “RETRIEVE_DEFAULT_VALUES” method.
Important Parameter of method “RETRIEVE_DEFAULT_VALUES”
Parameter Name |
Description |
IS_CTX |
Details about the BO and Node for which node class is being called. This parameter is a structure.
Some important attributes of the parameter are:
BO_KEY – BO Key of the node
ROOT_NODE_KEY – Node key of the BO. Please note, the key is not the node instance key, rather it’s the node key. We can use this key to compare the node key of the BO using <constant_interface>=>SC_NODE-ROOT
NODE_KEY – This is the node key of the BO. Please note, this is also not the instance of the node, rather the node key of the BO
|
IT_KEY |
These are the node instances for which the node class is being called. This values can be used to retrieve the data using IO_READ parameter. |
IO_READ |
Used to retrieve the data. Please use the above link for the example usage |
IO_MODIFY |
Used to modify the node data. In our case, we will use it to default the value in the node instance. |
Creating the node class:
In this section, we will create and implement the logic of “Node class”. I have already a BO “ZRISK_ASSESSMENT”. In the BO, we have a node “ROOT”. I will use this node and will specify the node class for it and will populate the “Title Field” of the root through the node class. If you want to populate default value for document date in the Purchase order, then in the node class, you have to populate the document date.
Step 1:
The class can be created directly in SE24 by implementing the interface /BOBF/IF_FRW_NODE manually or it can be created from the BO by double-clicking the class name. The system will ask to create the class on double click if the class is not existing. I will go through the second option.
(Above screenshot is from BOBX)
Step 2:
Double click on the node class name been provide by you. If the class is not existing, you will get below pop-up, click on yes.
Step 3:
Once you click on “yes”, the specified class will be created and you can see the interface is already implemented and you can see both the method available
(We can see the required interface is implemented)
(Both the method from the interface can be seen)
Fun fact:
Actually, if we will see with attention, we can found out the created class didn’t implement the interface “/BOBF/IF_FRW_NODE” directly. Rather it inherited the class “/BOBF/CL_LIB_N_SUPERCLASS” which implements the required interface.
Step 4:
Redefine the method “RETRIEVE_DEFAULT_VALUES” of the class.
(redefinition of method RETRIEVE_DEFAULT_VALUES)
Step 5:
Implement the logic. I have not read the data using IO_READ, I know the value which needs to default.
(logic implemented to default the value of the attribute)
DATA:
ls_root TYPE zras_d_root.
LOOP AT it_key INTO DATA(ls_key).
"Default values
ls_root-title = |Title Defaulted in Node Class|.
"Update default values
io_modify->update(
EXPORTING
iv_node = is_ctx-node_key " Node
iv_key = ls_key-key " Key
is_data = REF #( ls_root ) " Data
it_changed_fields = VALUE #( ( |TITLE| ) ) " List of Names (e.g. Fieldnames)
).
ENDLOOP.
You can see, I have looped for all the node instances and set the value in the ls_root work area. Then I have updated the node instance using the parameter io_modfiy, which will default the title of my risk assessment.
So, we have successfully created a node class and implemented the logic. But, the next big question is, who calls the class? Is the BOPF framework making a call?
So, the answer is, the BOPF framework does not call the “node class” to default the values. It is the work of the consumer layer(for example FBI, SAP Gateway, generic consumer, etc or an ENA class(Easy node access class) to call the node API and default the value before the field is diplayed on the UI.
So, the obvious next question is – How to call the node class?
The service manager interface “/BOBF/IF_TRA_SERVICE_MANAGER” has a method “RETRIEVE_DEFAULT_NODE_VALUES”. So, this method should be called, which will ultimately call the respective node class based on the Node_KEY been provided and defaults the value.
(Image depicting the service manager interface which is used to call the node class)
So, if you are using FBI(FPM-BOPF Integration), the feeder class for FBI will have a call to this method, so no need to call it explicitly. But, for demonstration, I will use a report program to show how to call in the subsequent section.
Calling the node class to default the value in the node:
Please refer to below screenshot. The object “MO_SMNGR_RAS” is the service manager of the BO “Risk Assessment”, which is used to call the method “RETRIEVE_DEFAULT_NODE_VALUES”, which will provide the defaulted values based on the logic written in node class(discussed earlier in this blog post).
Note:
◉ Please note, the CT_DATA parameter expects the table type of the combined struture
◉ If the table CT_DATA is blank, it will not return the default value. It better to generate the UUID and append it to the CT_DATA(i did the same in below example).
Complete Report Source code:
*&---------------------------------------------------------------------*
*& Report ZRAS_DATA_NODE_CLASS
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zras_call_node_class.
CLASS lcl_ras_data DEFINITION.
PUBLIC SECTION.
METHODS:
constructor,
create_new_root
IMPORTING im_s_root TYPE zras_s_root_d
RETURNING VALUE(rt_o_message) TYPE REF TO /bobf/if_frw_message.
PRIVATE SECTION.
DATA:
mo_smngr_ras TYPE REF TO /bobf/if_tra_service_manager,
mo_tmngr TYPE REF TO /bobf/if_tra_transaction_mgr.
ENDCLASS.
START-OF-SELECTION.
"Create object of local class
DATA(lo_ras_data) = NEW lcl_ras_data( ).
"Fill the node
DATA(lo_message) = lo_ras_data->create_new_root(
im_s_root = VALUE #(
status = '01'
type = 'WA_RAS'
is_simulated = abap_false
)
).
IF lo_message IS BOUND.
IF lo_message->check( ) EQ abap_true.
MESSAGE 'Creation failed' TYPE 'S' DISPLAY LIKE 'E'.
ELSE.
MESSAGE 'Creation successful' TYPE 'S'.
ENDIF.
ELSE.
MESSAGE 'Creation successful' TYPE 'S'.
ENDIF.
CLASS lcl_ras_data IMPLEMENTATION.
METHOD constructor.
"Get reference of the service manager
mo_smngr_ras = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( zif_risk_assessment_c=>sc_bo_key ).
"Get reference of transactional manager
mo_tmngr = /bobf/cl_tra_trans_mgr_factory=>get_transaction_manager( ).
ENDMETHOD.
METHOD create_new_root.
FREE rt_o_message.
DATA:
lt_root TYPE zras_t_root.
"Move corresponding values
DATA(ls_ras_root) = CORRESPONDING zras_d_root( im_s_root ).
"Get new UUID
ls_ras_root-db_key = /bobf/cl_frw_factory=>get_new_key( ).
APPEND CONV zras_s_root(
CORRESPONDING #(
ls_ras_root
MAPPING key = db_key
)
) TO lt_root.
"Retrive default value --> Point to keep in mind, here LT_ROOT is the table type of the COMBINED Structure
mo_smngr_ras->retrieve_default_node_values(
EXPORTING
iv_node_key = zif_risk_assessment_c=>sc_node-root " Node
CHANGING
ct_data = lt_root
).
LOOP AT lt_root INTO DATA(ls_root_dt).
ls_ras_root = CORRESPONDING #( ls_root_dt MAPPING db_key = key ).
"Assign value to modificationt table
DATA(lt_modif) = VALUE /bobf/t_frw_modification(
( node = zif_risk_assessment_c=>sc_node-root
change_mode = /bobf/if_frw_c=>sc_modify_create
key = ls_ras_root-db_key
data = REF #( ls_ras_root ) )
).
ENDLOOP.
"Modify the data
mo_smngr_ras->modify(
EXPORTING
it_modification = lt_modif " Changes
IMPORTING
eo_change = DATA(lo_change) " Interface of Change Object
eo_message = rt_o_message " Interface of Message Object
).
IF rt_o_message IS BOUND.
IF rt_o_message->check( ) EQ abap_true.
RETURN.
ENDIF.
ENDIF.
"Save data to data base
mo_tmngr->save(
IMPORTING
eo_message = rt_o_message
).
ENDMETHOD.
ENDCLASS.
Data in the database:
Source: sap.com
No comments:
Post a Comment