This program demonstrates basic CRUD operations on a sample Business Object (BO) called /BOPF/DEMO_CUSTOMER using the BOPF API. It defines a local class LCL_DEMO with methods to create, change, and display a customer record. The create_customer method builds the necessary data structures and uses the BOPF service manager and transaction manager to create a new customer record.
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
100%(1)100% found this document useful (1 vote)
412 views
BOPF Sample Code
This program demonstrates basic CRUD operations on a sample Business Object (BO) called /BOPF/DEMO_CUSTOMER using the BOPF API. It defines a local class LCL_DEMO with methods to create, change, and display a customer record. The create_customer method builds the necessary data structures and uses the BOPF service manager and transaction manager to create a new customer record.
*& Created By: James Wood (jwood@bowdark.com) * *& Created On: 01/16/2013 * *&---------------------------------------------------------------------* *& Description: This program demonstrates the BOPF API by showing how * *& to perform basic CRUD operations on a sample BO * *& called /BOBF/DEMO_CUSTOMER. * *&---------------------------------------------------------------------* REPORT zbopf_demo. *&---------------------------------------------------------------------* *& Selection Screen Definition * *&---------------------------------------------------------------------* PARAMETERS: p_custid TYPE /bobf/demo_customer_id. SELECTION-SCREEN SKIP. PARAMETERS: p_create TYPE c DEFAULT 'X' RADIOBUTTON GROUP mode, p_change TYPE c RADIOBUTTON GROUP mode, p_view TYPE c RADIOBUTTON GROUP mode. *&---------------------------------------------------------------------* *& Local Class Definitions * *&---------------------------------------------------------------------* CLASS lcl_demo DEFINITION CREATE PRIVATE. PUBLIC SECTION. CLASS-METHODS: create_customer IMPORTING iv_customer_id TYPE /bobf/demo_customer_id, change_customer IMPORTING iv_customer_id TYPE /bobf/demo_customer_id, display_customer IMPORTING iv_customer_id TYPE /bobf/demo_customer_id. PRIVATE SECTION. "Instance Attributes: DATA mo_txn_mngr TYPE REF TO /bobf/if_tra_transaction_mgr. DATA mo_svc_mngr TYPE REF TO /bobf/if_tra_service_manager. DATA mo_bo_conf TYPE REF TO /bobf/if_frw_configuration. "Instance Methods: METHODS: constructor RAISING /bobf/cx_frw, get_customer_for_id IMPORTING iv_customer_id TYPE /bobf/demo_customer_id RETURNING VALUE(rv_customer_key) TYPE /bobf/conf_key RAISING /bobf/cx_frw, get_node_table IMPORTING iv_key TYPE /bobf/conf_key iv_node_key TYPE /bobf/obm_node_key iv_edit_mode TYPE /bobf/conf_edit_mode DEFAULT /b obf/if_conf_c=>sc_edit_read_only RETURNING VALUE(rr_data) TYPE REF TO data RAISING /bobf/cx_frw, get_node_row IMPORTING iv_key TYPE /bobf/conf_key iv_node_key TYPE /bobf/obm_node_key iv_edit_mode TYPE /bobf/conf_edit_mode DEFAULT /bob f/if_conf_c=>sc_edit_read_only iv_index TYPE i DEFAULT 1 RETURNING VALUE(rr_data) TYPE REF TO data RAISING /bobf/cx_frw, get_node_table_by_assoc IMPORTING iv_key TYPE /bobf/conf_key iv_node_key TYPE /bobf/obm_node_key iv_assoc_key TYPE /bobf/obm_assoc_key iv_edit_mode TYPE /bobf/conf_edit_mode D EFAULT /bobf/if_conf_c=>sc_edit_read_only RETURNING VALUE(rr_data) TYPE REF TO data RAISING /bobf/cx_frw, get_node_row_by_assoc IMPORTING iv_key TYPE /bobf/conf_key iv_node_key TYPE /bobf/obm_node_key iv_assoc_key TYPE /bobf/obm_assoc_key iv_edit_mode TYPE /bobf/conf_edit_mode DEF AULT /bobf/if_conf_c=>sc_edit_read_only iv_index TYPE i DEFAULT 1 RETURNING VALUE(rr_data) TYPE REF TO data RAISING /bobf/cx_frw, display_messages IMPORTING io_message TYPE REF TO /bobf/if_frw_message. ENDCLASS. CLASS lcl_demo IMPLEMENTATION. METHOD constructor. "Obtain a reference to the BOPF transaction manager: me->mo_txn_mngr = /bobf/cl_tra_trans_mgr_factory=>get_transaction_manager( ). "Obtain a reference to the BOPF service manager: me->mo_svc_mngr = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( /bobf/if_demo_customer_c=>sc_bo_key ). "Access the metadata for the /BOBF/DEMO_CUSTOMER BO: me->mo_bo_conf = /bobf/cl_frw_factory=>get_configuration( /bobf/if_demo_customer_c=>sc_bo_key ). ENDMETHOD. " METHOD constructor METHOD create_customer. "Method-Local Data Declarations: DATA lo_driver TYPE REF TO lcl_demo. DATA lt_mod TYPE /bobf/t_frw_modification. DATA lo_change TYPE REF TO /bobf/if_tra_change. DATA lo_message TYPE REF TO /bobf/if_frw_message. DATA lv_rejected TYPE boole_d. DATA lx_bopf_ex TYPE REF TO /bobf/cx_frw. DATA lv_err_msg TYPE string. DATA lr_s_root TYPE REF TO /bobf/s_demo_customer_hdr_k. DATA lr_s_txt TYPE REF TO /bobf/s_demo_short_text_k. DATA lr_s_txt_hdr TYPE REF TO /bobf/s_demo_longtext_hdr_k. DATA lr_s_txt_cont TYPE REF TO /bobf/s_demo_longtext_item_k. FIELD-SYMBOLS: <ls_mod> LIKE LINE OF lt_mod. "Use the BOPF API to create a new customer record: TRY. "Instantiate the driver class: CREATE OBJECT lo_driver. "Build the ROOT node: CREATE DATA lr_s_root. lr_s_root->key = /bobf/cl_frw_factory=>get_new_key( ). lr_s_root->customer_id = iv_customer_id. lr_s_root->sales_org = 'AMER'. lr_s_root->cust_curr = 'USD'. lr_s_root->address_contry = 'US'. lr_s_root->address = '1234 Any Street'. APPEND INITIAL LINE TO lt_mod ASSIGNING <ls_mod>. <ls_mod>-node = /bobf/if_demo_customer_c=>sc_node-root. <ls_mod>-change_mode = /bobf/if_frw_c=>sc_modify_create. <ls_mod>-key = lr_s_root->key. <ls_mod>-data = lr_s_root. "Build the ROOT_TEXT node: CREATE DATA lr_s_txt. lr_s_txt->key = /bobf/cl_frw_factory=>get_new_key( ). lr_s_txt->text = 'Sample Customer Record'. lr_s_txt->language = sy-langu. APPEND INITIAL LINE TO lt_mod ASSIGNING <ls_mod>. <ls_mod>-node = /bobf/if_demo_customer_c=>sc_node-root_text. <ls_mod>-change_mode = /bobf/if_frw_c=>sc_modify_create. <ls_mod>-source_node = /bobf/if_demo_customer_c=>sc_node-root. <ls_mod>-association = /bobf/if_demo_customer_c=>sc_association-root-root_ text. <ls_mod>-source_key = lr_s_root->key. <ls_mod>-key = lr_s_txt->key. <ls_mod>-data = lr_s_txt. "Build the ROOT_LONG_TEXT node: "If you look at the node type for this node, you'll notice that "it's a "Delegated Node". In other words, it is defined in terms "of the /BOBF/DEMO_TEXT_COLLECTION business object. The following "code accounts for this indirection. CREATE DATA lr_s_txt_hdr. lr_s_txt_hdr->key = /bobf/cl_frw_factory=>get_new_key( ). APPEND INITIAL LINE TO lt_mod ASSIGNING <ls_mod>. <ls_mod>-node = /bobf/if_demo_customer_c=>sc_node-root_long_tex t. <ls_mod>-change_mode = /bobf/if_frw_c=>sc_modify_create. <ls_mod>-source_node = /bobf/if_demo_customer_c=>sc_node-root. <ls_mod>-association = /bobf/if_demo_customer_c=>sc_association-root-r oot_long_text. <ls_mod>-source_key = lr_s_root->key. <ls_mod>-key = lr_s_txt_hdr->key. <ls_mod>-data = lr_s_txt_hdr. "Create the CONTENT node: CREATE DATA lr_s_txt_cont. lr_s_txt_cont->key = /bobf/cl_frw_factory=>get_new_key( ). lr_s_txt_cont->language = sy-langu. lr_s_txt_cont->text_type = 'MEMO'. lr_s_txt_cont->text_content = 'Demo customer created via BOPF API.'. APPEND INITIAL LINE TO lt_mod ASSIGNING <ls_mod>. <ls_mod>-node = lo_driver->mo_bo_conf->query_node( iv_proxy_node_na me = 'ROOT_LONG_TXT.CONTENT' ). <ls_mod>-change_mode = /bobf/if_frw_c=>sc_modify_create. <ls_mod>-source_node = /bobf/if_demo_customer_c=>sc_node-root_long_text. <ls_mod>-source_key = lr_s_txt_hdr->key. <ls_mod>-key = lr_s_txt_cont->key. <ls_mod>-data = lr_s_txt_cont. <ls_mod>-association = lo_driver->mo_bo_conf->query_assoc( iv_node_key = /bobf/if_demo_customer_c=>sc_node-root_long_text iv_assoc_name = 'CONTENT' ). "Create the customer record: CALL METHOD lo_driver->mo_svc_mngr->modify EXPORTING it_modification = lt_mod IMPORTING eo_change = lo_change eo_message = lo_message. "Check for errors: IF lo_message IS BOUND. IF lo_message->check( ) EQ abap_true. lo_driver->display_messages( lo_message ). RETURN. ENDIF. ENDIF. "Apply the transactional changes: CALL METHOD lo_driver->mo_txn_mngr->save IMPORTING eo_message = lo_message ev_rejected = lv_rejected. IF lv_rejected EQ abap_true. lo_driver->display_messages( lo_message ). RETURN. ENDIF. "If we get to here, then the operation was successful: WRITE: / 'Customer', iv_customer_id, 'created successfully.'. CATCH /bobf/cx_frw INTO lx_bopf_ex. lv_err_msg = lx_bopf_ex->get_text( ). WRITE: / lv_err_msg. ENDTRY. ENDMETHOD. " METHOD create_customer METHOD change_customer. "Method-Local Data Declarations: DATA lo_driver TYPE REF TO lcl_demo. DATA lv_customer_key TYPE /bobf/conf_key. DATA lt_mod TYPE /bobf/t_frw_modification. DATA lo_change TYPE REF TO /bobf/if_tra_change. DATA lo_message TYPE REF TO /bobf/if_frw_message. DATA lv_rejected TYPE boole_d. DATA lx_bopf_ex TYPE REF TO /bobf/cx_frw. DATA lv_err_msg TYPE string. FIELD-SYMBOLS: <ls_mod> LIKE LINE OF lt_mod. DATA lr_s_root TYPE REF TO /bobf/s_demo_customer_hdr_k. "Try to change the address on the selected customer: TRY. "Instantiate the test driver class: CREATE OBJECT lo_driver. "Access the customer ROOT node: lv_customer_key = lo_driver->get_customer_for_id( iv_customer_id ). lr_s_root ?= lo_driver->get_node_row( iv_key = lv_customer_key iv_node_key = /bobf/if_demo_customer_c=>sc_node -root iv_edit_mode = /bobf/if_conf_c=>sc_edit_exclusi ve iv_index = 1 ). "Change the address string on the customer: lr_s_root->address = '1234 Boardwalk Ave.'. APPEND INITIAL LINE TO lt_mod ASSIGNING <ls_mod>. <ls_mod>-node = /bobf/if_demo_customer_c=>sc_node-root. <ls_mod>-change_mode = /bobf/if_frw_c=>sc_modify_update. <ls_mod>-key = lr_s_root->key. <ls_mod>-data = lr_s_root. "Create the customer record: CALL METHOD lo_driver->mo_svc_mngr->modify EXPORTING it_modification = lt_mod IMPORTING eo_change = lo_change eo_message = lo_message. "Check for errors: IF lo_message IS BOUND. IF lo_message->check( ) EQ abap_true. lo_driver->display_messages( lo_message ). RETURN. ENDIF. ENDIF. "Apply the transactional changes: CALL METHOD lo_driver->mo_txn_mngr->save IMPORTING eo_message = lo_message ev_rejected = lv_rejected. IF lv_rejected EQ abap_true. lo_driver->display_messages( lo_message ). RETURN. ENDIF. "If we get to here, then the operation was successful: WRITE: / 'Customer', iv_customer_id, 'updated successfully.'. CATCH /bobf/cx_frw INTO lx_bopf_ex. lv_err_msg = lx_bopf_ex->get_text( ). WRITE: / lv_err_msg. ENDTRY. ENDMETHOD. " METHOD change_customer METHOD display_customer. "Method-Local Data Declarations: DATA lo_driver TYPE REF TO lcl_demo. DATA lv_customer_key TYPE /bobf/conf_key. DATA lx_bopf_ex TYPE REF TO /bobf/cx_frw. DATA lv_err_msg TYPE string. DATA lr_s_root TYPE REF TO /bobf/s_demo_customer_hdr_k. DATA lr_s_text TYPE REF TO /bobf/s_demo_short_text_k. "Try to display the selected customer: TRY. "Instantiate the test driver class: CREATE OBJECT lo_driver. "Lookup the customer's key attribute using a query: lv_customer_key = lo_driver->get_customer_for_id( iv_customer_id ). "Display the header-level details for the customer: lr_s_root ?= lo_driver->get_node_row( iv_key = lv_customer_key iv_node_key = /bobf/if_demo_customer_c=>sc_node -root iv_index = 1 ). WRITE: / 'Display Customer', lr_s_root->customer_id. ULINE. WRITE: / 'Sales Organization:', lr_s_root->sales_org. WRITE: / 'Address:', lr_s_root->address. SKIP. "Traverse to the ROOT_TEXT node to display the customer short text: lr_s_text ?= lo_driver->get_node_row_by_assoc( iv_key = lv_customer_key iv_node_key = /bobf/if_demo_customer_c =>sc_node-root iv_assoc_key = /bobf/if_demo_customer_ c=>sc_association-root-root_text iv_index = 1 ). WRITE: / 'Short Text:', lr_s_text->text. CATCH /bobf/cx_frw INTO lx_bopf_ex. lv_err_msg = lx_bopf_ex->get_text( ). WRITE: / lv_err_msg. ENDTRY. ENDMETHOD. " METHOD display_customer METHOD get_customer_for_id. "Method-Local Data Declarations: DATA lo_driver TYPE REF TO lcl_demo. DATA lt_parameters TYPE /bobf/t_frw_query_selparam. DATA lt_customer_keys TYPE /bobf/t_frw_key. DATA lx_bopf_ex TYPE REF TO /bobf/cx_frw. DATA lv_err_msg TYPE string. FIELD-SYMBOLS <ls_parameter> LIKE LINE OF lt_parameters. FIELD-SYMBOLS <ls_customer_key> LIKE LINE OF lt_customer_keys. "Instantiate the test driver class: CREATE OBJECT lo_driver. "Though we could conceivably lookup the customer using an SQL query, "the preferred method of selection is a BOPF query: APPEND INITIAL LINE TO lt_parameters ASSIGNING <ls_parameter>. <ls_parameter>-attribute_name = /bobf/if_demo_customer_c=>sc_query_attribute -root-select_by_attributes-customer_id. <ls_parameter>-sign = 'I'. <ls_parameter>-option = 'EQ'. <ls_parameter>-low = iv_customer_id. CALL METHOD lo_driver->mo_svc_mngr->query EXPORTING iv_query_key = /bobf/if_demo_customer_c=>sc_query-root-select _by_attributes it_selection_parameters = lt_parameters IMPORTING et_key = lt_customer_keys. "Return the matching customer's KEY value: READ TABLE lt_customer_keys INDEX 1 ASSIGNING <ls_customer_key>. IF sy-subrc EQ 0. rv_customer_key = <ls_customer_key>-key. ENDIF. ENDMETHOD. " METHOD get_customer_for_id METHOD get_node_table. "Method-Local Data Declarations: DATA lt_key TYPE /bobf/t_frw_key. DATA ls_node_conf TYPE /bobf/s_confro_node. DATA lo_change TYPE REF TO /bobf/if_tra_change. DATA lo_message TYPE REF TO /bobf/if_frw_message. FIELD-SYMBOLS <ls_key> LIKE LINE OF lt_key. FIELD-SYMBOLS <lt_data> TYPE INDEX TABLE. "Lookup the node's configuration: CALL METHOD mo_bo_conf->get_node EXPORTING iv_node_key = iv_node_key IMPORTING es_node = ls_node_conf. "Use the node configuration metadata to create the result table: CREATE DATA rr_data TYPE (ls_node_conf-data_table_type). ASSIGN rr_data->* TO <lt_data>. "Retrieve the target node: APPEND INITIAL LINE TO lt_key ASSIGNING <ls_key>. <ls_key>-key = iv_key. CALL METHOD mo_svc_mngr->retrieve EXPORTING iv_node_key = iv_node_key it_key = lt_key IMPORTING eo_message = lo_message eo_change = lo_change et_data = <lt_data>. "Check the results: IF lo_message IS BOUND. IF lo_message->check( ) EQ abap_true. display_messages( lo_message ). RAISE EXCEPTION TYPE /bobf/cx_dac. ENDIF. ENDIF. ENDMETHOD. " METHOD get_node_table METHOD get_node_row. "Method-Local Data Declarations: DATA lr_t_data TYPE REF TO data. FIELD-SYMBOLS <lt_data> TYPE INDEX TABLE. FIELD-SYMBOLS <ls_row> TYPE ANY. "Lookup the node data: lr_t_data = get_node_table( iv_key = iv_key iv_node_key = iv_node_key iv_edit_mode = iv_edit_mode ). IF lr_t_data IS NOT BOUND. RAISE EXCEPTION TYPE /bobf/cx_dac. ENDIF. "Try to pull the record at the specified index: ASSIGN lr_t_data->* TO <lt_data>. READ TABLE <lt_data> INDEX iv_index ASSIGNING <ls_row>. IF sy-subrc EQ 0. GET REFERENCE OF <ls_row> INTO rr_data. ELSE. RAISE EXCEPTION TYPE /bobf/cx_dac. ENDIF. ENDMETHOD. " METHOD get_node_row METHOD get_node_table_by_assoc. "Method-Local Data Declarations: DATA lt_key TYPE /bobf/t_frw_key. DATA ls_node_conf TYPE /bobf/s_confro_node. DATA ls_association TYPE /bobf/s_confro_assoc. DATA lo_change TYPE REF TO /bobf/if_tra_change. DATA lo_message TYPE REF TO /bobf/if_frw_message. FIELD-SYMBOLS <ls_key> LIKE LINE OF lt_key. FIELD-SYMBOLS <lt_data> TYPE INDEX TABLE. "Lookup the association metadata to find out more "information about the target sub-node: CALL METHOD mo_bo_conf->get_assoc EXPORTING iv_assoc_key = iv_assoc_key iv_node_key = iv_node_key IMPORTING es_assoc = ls_association. IF ls_association-target_node IS NOT BOUND. RAISE EXCEPTION TYPE /bobf/cx_dac. ENDIF. ls_node_conf = ls_association-target_node->*. "Use the node configuration metadata to create the result table: CREATE DATA rr_data TYPE (ls_node_conf-data_table_type). ASSIGN rr_data->* TO <lt_data>. "Retrieve the target node: APPEND INITIAL LINE TO lt_key ASSIGNING <ls_key>. <ls_key>-key = iv_key. CALL METHOD mo_svc_mngr->retrieve_by_association EXPORTING iv_node_key = iv_node_key it_key = lt_key iv_association = iv_assoc_key iv_fill_data = abap_true IMPORTING eo_message = lo_message eo_change = lo_change et_data = <lt_data>. "Check the results: IF lo_message IS BOUND. IF lo_message->check( ) EQ abap_true. display_messages( lo_message ). RAISE EXCEPTION TYPE /bobf/cx_dac. ENDIF. ENDIF. ENDMETHOD. " METHOD get_node_table_by_assoc METHOD get_node_row_by_assoc. "Method-Local Data Declarations: DATA lr_t_data TYPE REF TO data. FIELD-SYMBOLS <lt_data> TYPE INDEX TABLE. FIELD-SYMBOLS <ls_row> TYPE ANY. "Lookup the node data: lr_t_data = get_node_table_by_assoc( iv_key = iv_key iv_node_key = iv_node_key iv_assoc_key = iv_assoc_key iv_edit_mode = iv_edit_mode ). IF lr_t_data IS NOT BOUND. RAISE EXCEPTION TYPE /bobf/cx_dac. ENDIF. "Try to pull the record at the specified index: ASSIGN lr_t_data->* TO <lt_data>. READ TABLE <lt_data> INDEX iv_index ASSIGNING <ls_row>. IF sy-subrc EQ 0. GET REFERENCE OF <ls_row> INTO rr_data. ELSE. RAISE EXCEPTION TYPE /bobf/cx_dac. ENDIF. ENDMETHOD. " METHOD get_node_row_by_assoc METHOD display_messages. "Method-Local Data Declarations: DATA lt_messages TYPE /bobf/t_frw_message_k. DATA lv_msg_text TYPE string. FIELD-SYMBOLS <ls_message> LIKE LINE OF lt_messages. "Sanity check: CHECK io_message IS BOUND. "Output each of the messages in the collection: io_message->get_messages( IMPORTING et_message = lt_messages ). LOOP AT lt_messages ASSIGNING <ls_message>. lv_msg_text = <ls_message>-message->get_text( ). WRITE: / lv_msg_text. ENDLOOP. ENDMETHOD. " METHOD display_messages ENDCLASS. *&---------------------------------------------------------------------* *& START-OF-SELECTION Event Module * *&---------------------------------------------------------------------* START-OF-SELECTION. "Run the demo program: IF p_create EQ abap_true. lcl_demo=>create_customer( iv_customer_id = p_custid ). ELSEIF p_change EQ abap_true. lcl_demo=>change_customer( iv_customer_id = p_custid ). ELSE. lcl_demo=>display_customer( iv_customer_id = p_custid ). ENDIF.