Using Business Object Processing Framework (BOPF)

    • Structure
      • Node
        • Association 
    • Behavior
      • Get service manager ( singleton )
      • Get transaction manager ( singleton )
      • Create ( main and sub nodes )
      • Retrieve sub nodes by association  
      • Retrieve by key 
      • Convert to technical key
      • Retrieve sub nodes by association  
      • Query by elements 
      • Query by key
      • Updating and Deleting BO Node Rows
      • Execute action
      • Determine
      • Validate 
      • Lock
      • Save
    • Performance
    • Debugging 
    • Change documents
    • BOPF archiving 
    • Status management

    BOPF is the framework to model, create, and manage standard and customer-specific business objects. Instead of expending effort for developing an application infrastructure, the developer can focus on the individual business logic.  

    Anatomy of a Business object

    What is the Business Object Processing Framework (BOPF)?

    BOPF (Business Object Processing Framework) is a framework for working with the BO (Business Objects). This framework provides tools and services for the entire BO life cycle.
    1. BOBX: This transaction is used for launching the BOPF Enhancement workbench. This transaction is used for enhancing the standard business objects and for creating new business objects.
    2. BOBT This transaction is used as a test environment. This transaction would help the consultant (Either it is functional or technical) to see the data of a particular BO.

    What is a Business Object (BO) ? 

    BO is a representation of a type of uniquely identifiable business entity described by a structural model, an internal process model, and one or more service interfaces. In other words, BO should have a structured component model and have a well-defined process model which governs the BO lifecycle, behaviors.

    Working with the BOPF

    Structure

    Nodes / Knoten 

    Each node/node row within a BO instance defines one or more attributes. At design time, nodes are used to model the data and behavior of an individual aspect of a business object. At runtime, nodes are containers (think internal tables) which group together object like instances called node rows. 

    Depending on the design-time definition of a node, we can perform operations on individual node rows or the node collection as a whole.

    From a data modeling perspective, nodes and node attributes are organized into two distinct categories: persistent nodes/attributes and transient nodes/attributes.
    • The DATA STRUCTURE field points to an ABAP Dictionary structure which contains all of the persistent attributes defined within the node. 
    • The (optional) TRANSIENT STRUCTURE field points to an ABAP Dictionary structure which contains all of the transient attributes defined within the node.
    • This combined structure collects persistent and transient attributes in a singular structure. 
    Types:
    • Delegierter Knoten: Ein delegierter Knoten ist ein Knoten, der auf einem anderen (separat existierenden) Geschäftsobjekt basiert und in Abhängigkeit zu dem Oberknoten steht.Dies entspricht einer Komposition in der Objektorientierung.
    • Darstellungsknoten für Geschäftsobjekt: Ein Darstellungsknoten basiert ebenfalls auf einem anderen Geschäftsobjekt, steht aber in keiner Abhängigkeit zu dem Oberknoten.

    Assosiation / Assoziationen

    Associations are connections between two nodes that can be used to navigate from the first node to the second (and back, if necessary). In BOPF business objectsthere are two types of associations:
    • Associations between nodes of a business object. These are created by the framework automatically as soon as you add subnodes.
    • Associations of a connection to nodes of foreign business objects. These associations are introduced in this chapter. So if you create a representation node, an association is not automatically created.

    Das Auflösen einer Assoziation, d. h. das Beschaffen der dazugehörigen Instanzen
    eines zweiten Knotens zu der Instanz des ersten Knotens, geschieht über die
    Methode RETRIEVE_BY_ASSOCIATION. Mit dieser Methode können Sie z. B. zu einer
    Instanz eines Kunden A die Instanzen (und damit die Daten) aller diesem Kunden
    zugeordneten Aufträge ermitteln.

    => Kompositionen

    Das Framework löst im Hintergrund die Verbindung der Knoten über eine Fremdschlüsselbeziehung
    zwischen den beiden dahinterliegenden Datenbanken über die Felder KEY (des Oberknotens) und PARENT_KEY (des Unterknotens) auf.

    ===> Normale Assoziation
    Im einfachsten Fall geschieht eine Verknüpfung innerhalb eines Geschäftsobjekts über eine normale Assoziation zwischen einem Knoten und einem direkt darunter angeordneten Unterknoten.
    Example: /BOBF/DEMO_CUSTOMER

    ===> Assoziation zu einem delegierten Objekt
    Example: /BOBF/DEMO_TEXT_COLLECTION

    ===>Spezialisierungsassoziation
    Eine Spezialisierungsassoziation wirkt wie eine normale Assoziation, mit dem Unterschied,
    dass die Knoteninstanzen des zweiten Knotens nicht nur anhand ihres Primärschlüssels
    (PARENT_KEY = KEY) selektiert werden, sondern diese Auswahl mit
    zusätzlichen weiteren Kriterien eingeschränkt werden kann

    => Allgemeine Assoziationen
    Assoziationen, die zu den allgemeinen Assoziationen zählen, definieren eine Beziehung zwischen einem Quell- und einem Zielknoten für die komplette Knotenhierarchie eines Geschäftsobjekts. Das bedeutet, dass entgegen der Komposition aus dem vorherigen Abschnitt hier auch Knoten miteinander in Beziehung stehen können, die nicht nur direkt untereinander in einer Abhängigkeit (Ober- und Unterknoten) innerhalb einer Knotenhierarchie liegen.

    ===> Fremdschlüsselassoziation
    Eine Fremdschlüsselassoziation ist eine Verknüpfung von zwei beliebigen Knoten über einen frei wählbaren Fremdschlüssel. Das bedeutet, dass Sie die zu verknüpfenden Felder hier frei wählen können, statt dass das Framework automatisch die Felder KEY und PARENT_KEY nimmt (wie bei einer normalen Assoziation).

    Example: EHHSS_INCIDENT, Durch die eingestellte Fremdschlüsselassoziation lässt sich dennoch von dem Knoten Personenrolle (PERSON_ROLE) zum Knoten Fahrzeug (VEHICLE) navigieren.

    ===> Umgekehrte Fremdschlüsselassoziation
    Bei einer umgekehrten Fremdschlüsselassoziation sind die Fremdschlüssel vertauscht: Der Primärschlüssel befindet sich in Tabelle A und der Fremdschlüssel in Tabelle B. Das bedeutet, dass die Kardinalität nicht mehr wie bei einer normaleFremdschlüsselbeziehung »1 zu 0..1« ist, sondern »1 zu 0..n« sein kann. Aus diesem Grund muss das Framework die Beziehung anders auflösen: Das Framework muss den Primärschlüssel aus der Tabelle A nehmen und mehrere Einträge über den Fremdschlüssel aus Tabelle B auslesen (Auflösen nach Zielknoten), anstatt den Fremdschlüssel aus Tabelle A zu nehmen und damit auf Tabelle B den dazugehörigen Eintrag auszulesen (Auflösen nach Quellknoten).

    ===> Geschäftsobjektübergreifende Assoziation
    Neben der Assoziation zu einem delegierten Objekt haben Sie auch die Möglichkeit, Geschäftsobjekte in Beziehung zueinander zu setzen, die dennoch komplett unabhängig voneinander agieren können. Das heißt, dass das eine Geschäftsobjekt auch ohne das andere Geschäftsobjekt existieren kann.

    Example: EHHSS_RISK, Unterknoten das Geschäftsobjekt EHFND_LOCATION.

    Behavior

    In order to use BOPF API we need to gain knowledge of three main object types: 
    • /BOBF/IF_TRA_SERVICE_MANAGER 
    • /BOBF/IF_TRA_TRANSACTION_MGR 
    • /BOBF/IF_FRW_CONFIGURATION 
    The factory methods of the /BOBF/CL_TRA_SERV_MGR_FACTORY and /BOBF/CL_FRW_FACTORY classes expect to receive a BO key

    #Attribtutes

    • SERVICE_MANAGER type ref to /BOBF/IF_TRA_SERVICE_MANAGER
    • TRANSACTION_MANAGER type ref to /BOBF/IF_TRA_TRANSACTION_MGR

    #Methods

    Get service manager ( singleton )

    Returning RO_SERVICE_MANAGER type  /BOBF/IF_TRA_SERVICE_MANAGER
        IF service_manager IS BOUND.
          ro_service_manager = service_manager.
        ELSE.
          ro_service_manager = service_manager = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( iv_bo_key = <<?>>=>sc_bo_key ).
        ENDIF.

    Get transaction manager ( singleton )

    Returning RO_TRANSACTION_MANAGER type  /BOBF/IF_TRA_TRANSACTION_MGR
        IF transaction_manager IS BOUND.
          ro_transaction_manager = transaction_manager.
        ELSE.
          ro_transaction_manager = transaction_manager = /bobf/cl_tra_trans_mgr_factory=>get_transaction_manager( ).
        ENDIF.

    Query by key

    DATA: lt_sel_param TYPE
    DATA: lt_filter_key TYPE /bobf/t_frw_key,

    ls_filter_key TYPE /bobf/s_frw_key.
    ls_filter_key-key = '000C294A1BC91ED78FA9BE1AD6C520E0'.

    APPEND ls_filter_key TO lt_filter_key.
    lo_serv_mgr->query( EXPORTING
    • iv_query_key = /bobf/if_demo_customer_c=>sc_query-root-select_all
    •  iv_fill_data = abap_true
    • it_filter_key = lt_filter_key
    IMPORTING 
    • et_data = lt_data et_key = lt_keys).

    Query by elements 

    DATA: lt_sel_param TYPE /bobf/t_frw_query_selparam.

    IF iv_freight_order IS NOT INITIAL .
    INSERT VALUE /bobf/s_frw_query_selparam(  attribute_name = <<?>>=>sc_query_attribute-root-select_by_elements-tor_id low = 'XX' option = 'EQ' sign = 'I' ) INTO TABLE lt_sel_param.

    get_service_manager( )->query(  
    EXPORTING 
    • iv_query_key = <<?>>=>sc_query-root-select_by_elements
    • iv_fill_data = abap_true
    • it_selection_parameters = lt_sel_param
    IMPORTING 
    • et_key = et_key ).

    Retrieve by key 

    Vorteil dieser Methode ist, dass Sie über den Parameter IV_INVALIDATE_CACHE die Möglichkeit haben, den Puffer zurückzusetzen und, falls Sie dies benötigen, Sperren auf die Knoteninstanzen zu setzen. Alle fehlerhaften Schlüssel würden dagegen im Rückgabeparameter ET_FAILED_KEY zurückgegeben werden.


    DATA: 
    lt_keys TYPE /bobf/t_frw_key,
    ls_key TYPE /bobf/s_frw_key,
    lt_failed_keys TYPE /bobf/t_frw_key.

    ls_key-key = '005056XXXXXXx'.
    APPEND ls_key TO lt_keys.

    lo_serv_mgr->retrieve(  EXPORTING
    • iv_node_key = /bobf/if_demo_customer_c=>sc_noderoot
    • it_key = lt_keys
    • iv_fill_data = abap_true
    • iv_invalidate_cache = abap_true
    IMPORTING
    • et_data = lt_data
    • et_failed_key = lt_failed_keys ).

    Retrieve sub nodes by association  

    DATA: 
    • lt_data TYPE /bobf/t_demo_short_text_k,
    • lt_key TYPE /bobf/t_frw_key,
    • ls_key TYPE /bobf/s_frw_key.
    ls_key-key = '0050568F72901ED79EA63B400C91A0FF'.
    APPEND ls_key TO lt_key.

    lo_serv_mgr->retrieve_by_association( EXPORTING
    • iv_node_key = /bobf/if_demo_customer_c=>sc_node-root
    • it_key = lt_key
    • iv_association = /bobf/if_demo_customer_c=>sc_association-root-root_text
    • iv_fill_data = abap_true
    IMPORTING
    • et_data = lt_data ).

    Convert to technical key

    Internally, the BOPF works with automatically generated technical keys. In many cases, e.g. application development or the definition of associations (for linking) (for linking), technical keys are still needed that are comprehensible to the user.  In order to meet this requirement, the BOPF allows you to allows the creation of alternative keys for the Nodes.

    In addition to executing business object queries on the alternative keys the method CONVERT_ALTERN_KEY is the most important method for dealing with the alternative keys.

    Ways to convert the key: 
    • Sie führen mit dem alternativen Schlüssel eine Abfrage über SELECT_BY_ATTRIBUTES aus 
    • Sie verwenden die Methode CONVERT_ALTERN_KEY des Service-Managers undübergeben dort den alternativen Schlüssel
    Bei erfolgreicher Ausführung erhalten Sie die zugehörigen Schlüssel in der Rückgabetabelle ET_KEY.


    DATA: 
    • lt_alt_keys TYPE TABLE OF /bobf/demo_customer_id,
    • ls_alt_keys TYPE /bobf/demo_customer_id,
    • lt_keys TYPE /bobf/t_frw_key.
    ls_alt_keys = '123456'. APPEND ls_alt_keys TO lt_alt_keys.

    lo_mgr->convert_altern_key( EXPORTING
    • iv_node_key = /bobf/if_demo_customer_c=>sc_node-root
    • iv_altkey_key = /bobf/if_demo_customer_c=>sc_alternative_key-root-customer_id
    • it_key = lt_alt_keys
    IMPORTING
    • et_key = lt_keys).

    Create ( main and sub nodes )

    DATA: 
    • lt_modi TYPE /bobf/t_frw_modification,
    • lo_message TYPE REF TO /bobf/if_frw_message,
    • lt_messages TYPE /bobf/t_frw_message_k,
    • lv_rejected TYPE flag,
    • lt_rejected_keys TYPE /bobf/t_frw_key2.
    • lr_tm_tcd TYPE REF TO <<?>>,
    • lr_tm_tcd_item TYPE REF TO  <<?>>,
    • lr_tm_tcd_element TYPE REF TO  <<?>>.
    TRY .
    LOOP AT it_freight_costs ASSIGNING FIELD-SYMBOL(<ls_freight_costs>).
    * Create ROOT node
    CREATE DATA lr_tm_tcd.

    lr_tm_tcd->* = CORRESPONDING #( <ls_freight_costs> ).
    lr_tm_tcd->key = get_service_manager( )->get_new_key( ).

    INSERT VALUE #( 
    • data = lr_tm_tcd 
    • node =<<?>>=>sc_node-root
    • change_mode = /bobf/if_frw_c=>sc_modify_create k
    • ey = lr_tm_tcd->key ) INTO TABLE lt_modi.
    LOOP AT <ls_freight_costs>-distr_items ASSIGNING FIELD-SYMBOL(<ls_items>).

    CREATE DATA lr_tm_tcd_item.
    lr_tm_tcd_item->* = CORRESPONDING #( <ls_items> ).
    lr_tm_tcd_item->key = get_service_manager( )->get_new_key( ).

    DATA(ls_tm_tcd_item) = lr_tm_tcd_item.

    INSERT VALUE #( 
    • node = <<?>>=>sc_node-distributionitem
    • change_mode = /bobf/if_frw_c=>sc_modify_create
    • source_node = <<?>>=>sc_node-root
    • association = <<?>>=>sc_association-root-distributionitem
    • source_key = lr_tm_tcd->key
    • key = lr_tm_tcd_item->key
    • data = ls_tm_tcd_item ) INTO TABLE lt_modi.
    LOOP AT <ls_items>-elements ASSIGNING FIELD-SYMBOL(<ls_element>).

    CREATE DATA lr_tm_tcd_element.

    lr_tm_tcd_element->* = CORRESPONDING #( <ls_element> ).
    lr_tm_tcd_element->key = get_service_manager( )->get_new_key( ).
    DATA(ls_tm_tcd_element) = lr_tm_tcd_element.

    INSERT VALUE #( 
    • node = <<?>>=>sc_node-distributionelement
    • change_mode = /bobf/if_frw_c=>sc_modify_create
    • source_node = <<?>>=>sc_node-distributionitem
    • association = <<?>>=>sc_association-distributionitem-distributionelement
    • source_key = lr_tm_tcd_item->key
    • key = lr_tm_tcd_element->key
    • data = ls_tm_tcd_element ) INTO TABLE lt_modi.
    ENDLOOP. ENDLOOP. ENDLOOP.

    get_service_manager( )->modify( EXPORTING it_modification = lt_modi IMPORTING eo_message = lo_message ).

    IF lo_message IS BOUND.
    IF lo_message->check( ) EQ abap_true.
    lo_message->get_messages( IMPORTING et_message = lt_messages ).
    ELSE.
    get_transaction_manager( )->save( IMPORTING ev_rejected = lv_rejected eo_message = lo_message ).

    IF lv_rejected IS NOT INITIAL.
    IF lo_message IS BOUND.
    IF lo_message->check( ) EQ abap_true.
    lo_message->get_messages( IMPORTING et_message = lt_messages ).
    ENDIF. ENDIF.
    get_transaction_manager( )->cleanup( ).
    ENDIF. ENDIF. ENDIF.
    CATCH /bobf/cx_frw_contrct_violation INTO DATA(lx_exception).
    ENDTRY.

    Updating and Deleting BO Node Rows

    DATA lo_svc_mngr TYPE REF TO /bobf/if_tra_service_manager.
    DATA lr_s_root TYPE REF TO /bobf/s_demo_sales_order_hdr_k. 
    DATA lt_mod TYPE /bobf/t_frw_modification. 

    FIELD-SYMBOLS <ls_mod> LIKE LINE OF lt_mod. 

    DATA lo_message TYPE REF TO /bobf/if_frw_message.

    READ TABLE lt_root INDEX 1 REFERENCE INTO lr_s_root. 
    IF sy-subrc EQ 0. lr_s_root->amount = lr_s_root->amount + '20.00'. 
    APPEND INITIAL LINE TO lt_mod ASSIGNING <ls_mod>. 
    <ls_mod>-node = /bobf/if_demo_sales_order_c=>sc_node-root. 
    <ls_mod>-change_mode = /bobf/if_frw_c=>sc_modify_update. "/BOBF/IF_FRW_C=>SC_MODIFY_DELETE
    <ls_mod>-key = lr_s_root->key. 
    <ls_mod>-data = lr_s_root. 
    APPEND 'AMOUNT' TO <ls_mod>-changed_fields. 
    ENDIF. 

    IF lines( lt_mod ) GT 0. 
    lo_svc_mngr->modify( EXPORTING it_modification = lt_mod IMPORTING eo_message =lo_message ).
    ENDIF.

    As is the case with the creation operation, all of the updates/deletes we perform using the modify() method are merely staged in shared memory until we either commit the transaction or roll it back.

     Execute action

    Eine Aktion entspricht im weiteren Sinne den Methoden eines objektorientiert modellierten Geschäftsobjekts und bildet die Geschäftslogik ab. Dies ist notwendig, da Sie neben den durch das Framework automatisch generierten Grundaktionen Anlegen, Ändern, Löschen, Sperren, Entsperren und Speichern) auch die eigentliche Geschäftslogik für das Geschäftsobjekt abbilden wollen.

    Kardinalität einer Aktion: Die Kardinalität einer Aktion steuert, ob eine Aktion entweder statisch oder auf eine oder mehrere Knoteninstanzen ausgeführt werden kann.

    Rückgabeparameter einer Aktion: Wie bei einer normalen Methode einer Klasse können Sie auch für Aktionen Rückgabeparameter definieren. Die Implementierung der Aktionen geschieht über das Interface /BOBF/IF_FRW_ACTION. Es ist jedoch auch möglich, Aktionen manuell über den Aufruf der Methode DO_ACTION des Service-Managers aufzurufen.


    DATA lo_svc_mngr TYPE REF TO /bobf/if_tra_service_manager. 
    DATA lt_key TYPE /bobf/t_frw_key. 

    FIELD-SYMBOLS <ls_key> LIKE LINE OF lt_key. 

    DATA lo_message TYPE REF TO /bobf/if_frw_message. 
    DATA lt_failed_key TYPE /bobf/t_frw_key. 

    "Call the DELIVER action
    lo_svc_mngr->do_action( EXPORTING iv_act_key = /bobf/if_demo_sales_order_c=>sc_action-root-deliver it_key = lt_key IMPORTING eo_message = lo_message et_failed_key = lt_failed_key ). 

    "Check the results
    IF lines( et_failed_key ) GT 0. ENDIF.

    Zur Arbeit mit Aktionen bietet der Service-Manager drei Methoden an:
    • die Methode DO_ACTION zum Aufrufen einer Aktion
    • die Methode RETRIEVE_DEFAULT_ACTION_PARAM zur Ermittlung von Standard- Aktionsparametern für den Aufruf der Aktion mit DO_ACTION
    • die Methode CHECK_ACTION zur Überprüfung, ob eine Aktion auf bestimmte Knoteninstanzen ausgeführt werden kann
    DATA:
    lt_keys TYPE /bobf/t_frw_key,
    ls_key TYPE /bobf/s_frw_key,
    lt_failed_keys TYPE /bobf/t_frw_key,
    lt_failed_action TYPE /bobf/t_frw_key,
    lo_message TYPE REF TO /bobf/if_frw_message.
    ls_key-key = '0050568F72901ED7A5949F1AA5B940FF'.
    APPEND ls_key TO lt_keys.

    lo_serv_mgr->do_action( EXPORTING
    • iv_act_key = /bobf/if_demo_sales_order_c=>sc_action-root-archive
    • it_key = lt_keys
    IMPORTING
    • eo_message = lo_message
    • et_failed_key = lt_failed_keys
    • et_failed_action_key = lt_failed_action
    • * et_data = "falls Aktion eine Rückgabe-Struktur hat ).
    "Erzeugung der Import-Struktur für die Aktion
    DATA: lr_del_import TYPE REF TO /bobf/s_demo_sales_order_hdr_d.
    CREATE DATA lr_del_import.
    lr_del_import->item_no = '010'.

    lo_serv_mgr->do_action( EXPORTING
    • iv_act_key = /bobf/if_demo_sales_order_c=>sc_
    • action-root-deliver
    • it_key = lt_keys
    • is_parameters = lr_del_import
    IMPORTING
    • eo_message = lo_message
    • et_failed_key = lt_failed_keys
    • et_failed_action_key = lt_failed_action
    • * et_data = "falls Aktion eine Rückgabe-Struktur hat ).
    Standardparameter für Aktionen auslesen
    Für eine Aktion können Standardparameter hinterlegt worden sein. Diese können Sie über die Methode RETRIEVE_DEFAULT_ACTION_PARAM auslesen.

    DATA: ls_param TYPE REF TO data.
    CREATE DATA ls_param TYPE /bobf/s_demo_sales_order_hdr_d.
    lo_serv_mgr->retrieve_default_action_param( EXPORTING
    • iv_act_key = /bobf/if_demo_sales_order_c=>sc_
    • action-root-deliver
    • it_key = lt_keys
    CHANGING cs_parameters = ls_param ).

    One more example..

    FIELD-SYMBOLS: <s_parameters> TYPE zss_task_setprogress_s.
    ASSIGN is_parameters->* TO <s_parameters>.
    DATA: lr_task TYPE REF TO zss_task_cs,
    lt_changed_fields TYPE /bobf/t_frw_name,
    ls_key TYPE /bobf/s_frw_key.
    CREATE DATA lr_task.
    lr_task->progress = <s_parameters>-newprogress.
    APPEND 'PROGRESS' TO lt_changed_fields.

    LOOP AT it_key INTO ls_key.
    • io_modify->update( EXPORTING
    • iv_node = is_ctx-node_key
    • iv_key = ls_key-key
    • is_data = lr_task
    • it_changed_fields = lt_changed_fields ).
    ENDLOOP.

    Determination

    Ermittlungen sind Funktionen, die automatisch ausgeführt werden, sobald bei der Arbeit mit einer Knoteninstanz (z. B. einer Änderung) die bei der Ermittlung hinterlegten Auslösebedingungen und Auswertungszeitpunkte zutreffen.
    • Persistente Ermittlungen: Es wird bei der Ermittlung mindestens ein persistentes Attribut geändert.
    • Transiente Ermittlungen: Es werden bei der Ermittlung nur transiente Felder geändert. Zusätzliche Daten sollen erst zur Laufzeit ermittelt werden, d. h., die Daten werden nicht persistent in der Datenbanktabelle gespeichert. Über diese transienten Ermittlungen können Sie transiente Knoten und transiente Attribute befüllen.
    • Verwaltungsdaten: Zeigt an, dass bei der Ermittlung Verwaltungsdaten des Systems gesetzt werden.
    • Berechtigungsprüfung: Zeigt an, dass die Ermittlung eine Berechtigungsprüfung durchführt.
    Auslösebedingungen und Auswertungszeitpunkte legen die Bedingung für die Ausführung
    einer Ermittlung fest. Erst wenn diese Bedingung vollständig zutrifft, wird eine Ermittlung ausgeführt. Bei einer Auslösebedingung wird festgelegt, bei welcher Grundaktion (Anlegen, Aktualisieren, Löschen, Laden oder Ermitteln) eine Ermittlung ausgeführt werden soll.

    Wollen Sie eine Ermittlung manuell aufrufen, können Sie dies über den Service-Manager mit der Methode CHECK_AND_DETERMINE tun.

    • Lokal: Bei Angabe der Konstante /BOBF/IF_FRW_C=>SC_SCOPE_LOCAL wird nur die aktuelle Knotenebene überprüft.
    • Teilstruktur: Bei Angabe von /BOBF/IF_FRW_C=>SC_SCOPE_SUBSTRUCTURE werden auch alle Unterknoten überprüft.
    Eine explizite Methode zur reinen Ausführung von Ermittlungen steht Ihnen als Anwender nicht
    zur Verfügung (nur als private Methode DO_DETERMINATIONS der Klasse /BOBF/CL_ FRW).

    DATA: lt_keys TYPE /bobf/t_frw_key,
    ls_key TYPE /bobf/s_frw_key,
    lo_message TYPE REF TO /bobf/if_frw_message.

    ls_key-key = '0050568F72901ED79EA326CDC37C60FF'.
    APPEND ls_key TO lt_keys.

    lo_serv_mgr->check_and_determine( EXPORTING
    • iv_node_key = /bobf/if_demo_customer_c=>sc_node-root
    • it_key = lt_keys
    • iv_check_scope = /bobf/if_frw_c=>sc_scope_local
    IMPORTING eo_message = lo_message).

    Standardwerte für Knoten auslesen

    Zu jedem Knoten kann eine Knotenklasse angelegt werden, die das Interface /BOBF/ IF_FRW_NODE mit der Methode RETRIEVE_DEFAULT_VALUES implementiert.

    => Standardwerte für Oberknoten auslesen
    Sind für einen Hauptknoten Standardwerte definiert worden, können Sie diese über die Methode RETRIEVE_DEFAULT_NODE_VALUES des Service-Managers wie hier beschrieben auslesen.

    DATA: lr_cust_root TYPE REF TO /bobf/s_demo_customer_hdr_k.
    CREATE DATA lr_cust_root.

    FIELD-SYMBOLS: <s_root_text> TYPE /bobf/s_demo_short_text_k.
    CREATE DATA lr_root_text.

    lr_root_text->key = /bobf/cl_frw_factory=>get_new_key( ).

    ASSIGN lr_root_text->* TO <s_root_text>.
    APPEND <s_root_text> TO lt_root_text.

    lo_mgr->retrieve_default_node_values( EXPORTING
    • iv_node_key = /bobf/if_demo_sales_order_c=>sc_node-root_text
    • iv_source_key = '0050568F72901ED7A5949F1AA5B940FF'
    • iv_assoc_key = /bobf/if_demo_sales_order_c=>sc_associationroot-
    • root_text CHANGING ct_data = lt_root_text ).

    Validate

    • Validation Name: This attribute defines the validation name, which is an identifier maintained internally within the BOPF.
    • Validation Category: 
      • The CONSISTENCY CHECK option classifies the validation as an entity used to perform consistency checks before a node instance is saved, etc. 
      • The ACTION CHECK option can be used as a means to ensure that a node instance is ready to have an action performed against it. 
    • Class/Interface: This attribute defines the validation implementation class, which is a plain ABAP Objects class that implements the /BOBF/IF_FRW_VALIDATION interface.

    Eine Validierung kann eine bestimmte Menge von Knoteninstanzen auf verschiedene
    Kriterien überprüfen. Das Framework stellt dafür zwei Arten von Validierungen bereit:
    • Konsistenz-Validierungen: Überprüft, ob Knoteninstanzen in sich konsistent sind, d. h. keine falsche Werte enthalten
      • Bestimmte Felder müssen gefüllt werden.
      • Es muss geprüft werden, ob diese Felder mit richtigen Werten gefüllt wurden.
    • Aktions-Validierungen: Überprüft, ob eine Aktion auf eine Knoteninstanz ausgeführt werden kann
      • Eine Aktions-Validierung überprüft für eine Aktion, ob diese auf eine Menge von Knoteninstanzen ausgeführt werden kann. Dies hat für Sie insbesondere immer dann einen Nutzen, wenn Sie beispielsweise vor Aufruf einer SET-Methode (z. B. SET_ CLOSED) prüfen wollen, ob die aktuelle Knoteninstanz überhaupt auf den Status »geschlossen« gesetzt werden darf.

    Zur Ausführung von Validierungen bietet der Service-Manager drei Methoden an:
    • die Methode CHECK_CONSISTENCY zur Durchführung von Konsistenz-Validierungen für Knoteninstanzen
    • die Methode CHECK_AND_DETERMINE zur Durchführung von Konsistenz-Validierungen und die dazugehörigen Ermittlungen für Knoteninstanzen
    • die Methode CHECK_ACTION für die Validierung von Aktionen

    Konsistenz-Validierungen

    DATA: lt_keys TYPE /bobf/t_frw_key,
    ls_key TYPE /bobf/s_frw_key,
    lo_message TYPE REF TO /bobf/if_frw_message.
    "Beispielhafter Schlüssel
    ls_key-key = '0050568F72901ED7A5949F1AA5B940FF'.
    APPEND ls_key TO lt_keys.
    lo_serv_mgr->check_consistency(
    EXPORTING
    iv_node_key = /bobf/if_demo_sales_order_c=>sc_node-root
    it_key = lt_keys
    iv_check_scope = /bobf/if_frw_c=>sc_scope_local
    IMPORTING
    eo_message = lo_message
    ).

    Der Rückgabeparameter EO_MESSAGE enthält nach der Ausführung die Diagnose zu
    den übergebenen Knoteninstanzen

    Aktions-Validierungen
    Je nach Erfolg der Ausführung sind die Rückgabeparameter unterschiedlich gefüllt:
    • Schlägt die Ausführung der Aktion fehl, ist die Rückgabetabelle ET_FAILED_ACTION_ KEY mit dem Schlüssel der Aktion gefüllt, während die Rückgabetabelle ET_ FAILED_KEY die fehlgeschlagenen Schlüssel der Knoteninstanzen enthält.
    • War die Durchführung der Aktion erfolgreich, ist die Rückgabetabelle ET_FAILED_ ACTION_KEY leer.
    lo_serv_mgr->check_action( EXPORTING
    • iv_act_key = /bobf/if_demo_sales_order_c=>sc_
    • action-root-archive
    • it_key = lt_keys
    IMPORTING
    • eo_message = lo_message
    • et_failed_key = lt_failed_keys
    • et_failed_action_key = lt_failed_action).

    Lock

    In bestimmten Fällen kann es dennoch vorkommen, dass Sie eine Sperre setzen wollen, ohne direkt eine Änderung mit der Methode MODIFY durchzuführen.

    Um ein solches Geschäftsobjekt für zukünftige Änderungen zu sperren, können Sie die Methode RETRIEVE benutzen.
    • für die exklusive Sperre die Konstante /BOBF/IF_CONF_C=>SC_EDIT_EXCLUSIVE 
      • In diesem Standardfall darf nur der Benutzer, der die Sperre setzt, das Geschäftsobjekt bearbeiten. Alle anderen Sperranfragen werden abgewiesen, 
    • für die optimistische Sperre die Konstante /BOBF/IF_CONF_C=>SC_EDIT_ OPTIMISTIC

    DATA: 
    • lt_keys TYPE /bobf/t_frw_key,
    • ls_key TYPE /bobf/s_frw_key.
    ls_key-key = '0050568F72901ED79EA326CDC37C60FF'.
    APPEND ls_key TO lt_keys.

    lo_serv_mgr->retrieve( 
    • iv_node_key = /bobf/if_demo_customer_c=>sc_node-root
    • it_key = lt_keys
    • iv_edit_mode = /bobf/if_conf_c=>sc_edit_exclusive
    • iv_fill_data = abap_false ).
    Die Instanzen werden immer nur dann entsperrt, wenn Sie die Methoden SAVE oder CLEANUP des Transaktions-Managers aufrufen.

    Entsperren
    lo_trans_mgr->save( ).
    "Oder (in der Regel bei Misserfolg von SAVE):
    lo_trans_mgr->cleanup( ).

    Get Parent node

    DATA: lt_key_link TYPE /bobf/t_frw_key_link,
    lt_failed_key TYPE /bobf/t_frw_key,
    lt_target_key TYPE /bobf/t_frw_key.
    DATA: lt_data TYPE /bobf/t_demo_short_text_k,
    lt_key TYPE /bobf/t_frw_key,
    ls_key TYPE /bobf/s_frw_key.
    DATA: lo_customer TYPE REF TO /bobf/if_frw_service_layer.
    lo_customer = /bobf/cl_frw_factory=>get_bopf(
    EXPORTING
    iv_bo_key = /bobf/if_demo_customer_c=>sc_bo_key
    ).
    ls_key-key = '0050568F72901ED79EB7C7DA5BFA00FF'.
    APPEND ls_key TO lt_key.
    lo_customer->get_root_key(
    EXPORTING
    iv_node_key = /bobf/if_demo_customer_c=>sc_node-root_text
    it_key = lt_key
    IMPORTING
    et_key_link = lt_key_link
    et_failed_key = lt_failed_key
    et_target_key = lt_target_key
    ).


    Save

    DATA: 
    • lt_modi TYPE /bobf/t_frw_modification,
    • lo_message TYPE REF TO /bobf/if_frw_message,
    • lt_messages TYPE /bobf/t_frw_message_k,
    • lv_rejected TYPE flag,
    • lt_rejected_keys TYPE /bobf/t_frw_key2,
    • lt_sel_param TYPE /bobf/t_frw_query_selparam,
    • lt_changed_fields TYPE /bobf/t_frw_name,
    • lt_data_sub_nodes TYPE /bobf/t_frw_key_link,
    • lr_tm_tcd TYPE REF TO ,
    • lr_tm_tcd_item TYPE REF TO ,
    • lr_tm_tcd_element TYPE REF TO .

    IF lo_message IS BOUND.
    IF lo_message->check( ) EQ abap_true.
    lo_message->get_messages( IMPORTING et_message = lt_messages ).
    ELSE.
    get_transaction_manager( )->save( IMPORTING ev_rejected = lv_rejected eo_message = lo_message ).

    IF lv_rejected IS NOT INITIAL.
    IF lo_message IS BOUND.
    IF lo_message->check( ) EQ abap_true.
    lo_message->get_messages( IMPORTING et_message = lt_messages ).
    INSERT VALUE #( type = 'E' id = '/JES/TM_TCD' number = '002' message_v1 = <ls_parameters>-tor_id ) INTO TABLE et_logs.

    LOOP AT lt_messages ASSIGNING FIELD-SYMBOL(<ls_message>).
    INSERT VALUE #( type = 'I' id = '/JES/TM_TCD' message = <ls_message>-message->get_text( ) ) INTO TABLE et_logs.
    ENDLOOP.
    ENDIF. ENDIF.
    get_transaction_manager( )->cleanup( ).
    ENDIF. ENDIF. ENDIF.

    Debugging 

    Nachrichten von EO_MESSAGE

    Damit Sie diese Navigation und Konstruktion nicht für jede Nachricht wiederholen müssen, stellt SAP auch hierfür ein Debugging-Skript namens /BOBF/ TOOL_DEBUGGER_SCRIPT_F bereit, das die Nachrichten für EO_MESSAGE automatisch ausliest und Ihnen in einer Tabelle aufbereitet präsentiert.


    Tragen Sie in diesem Eingabefeld Ihre Variable ein, die den Rückgabeparameter EO_ MESSAGE entgegengenommen hat (hier LO_MESSAGE), und klicken Sie anschließend auf den Button Start. 

    Change-Log von EO_CHANGE

    Wie beim Parameter EO_MESSAGE funktioniert das dazugehörige Debugging-Skript /BOBF/TOOL_DEBBUGER_SCRIPT_F auch für den Parameter EO_CHANGE.

    Eigenschaften von EO_PROPERTY

    Dazu müssen Sie das Skript laden, die Variable von EO_PROPERTY im Eingabefeld BOPF Framework Object eintragen und anschließend auf den Button Start klicken.

    Änderungstabelle IT_MODIFICATION

    Debugging-Skript /BOBF/TOOL_DEBUGGER_SCRIPT_M


    Change documents

    BOPF uses SAP NetWeaver’s change documents for recording business object changes. 

    A change document solution contains the following objects: 
    • Application business object This is the BO for which the changes are recorded when the transaction is saved. 
    • Change document object This is a configuration object used to define the relevant tables for tracking the changes (here, the business objects’ node tables). 
    • Change document business object Reusing the application business object allows the change documents to be displayed for any application business object. 
    Guide: 
    • Start transaction SCDO and choose “ Create”.
    • Specify a name for the change documents object. 
    • Define all node tables of your application business object: -
      • Root node table: Select checkbox “Doc.for individual fields at delete” 
      • All other node tables: Select checkbox “Copy as internal tab.” 
    •  Choose “Insert Entries” and “Save”.
    • Choose “Menu > Utilities > Generate Update pgm
    • Choose “Activate” and “Generation Info” to see the generation results.
    If you want to record only certain instances of your application business object, create a new
    class inheriting from callback class /BOFU/CL_CDO_BO_GENERICCALLBACK, and redefine
    method /BOFU/IF_CDO_CREATION~IS_CDO_CREATION_ACTIVE().
    y You can use IO_READ->RETRIEVE( IT_ROOT_KEY) to get the current and previous
    state of an instance to make an instance-based decision.
    y If you do not create your own callback class, all transactional changes of all instances of the
    application business object are recorded by default.


    Register the application BO, its change document, and callback class using transaction SPRO

    Create a representation node

    To integrate the change documents into your application business object, create a special cross-BO association with the change document BO.

    Performance

    1. It is important that core services, that query data from the database, are used in a mass-enabled fashion
    2. All methods of the service manager and the io_read are mass-enabled. Fetch all data in an internal table and loop afterwards over the entries. 
    3. The reading access via alternative key and the navigation to child nodes are very slow and need to be accelerated.
      • A database index improves the performance of reading data from a database table. In principle it is a (sorted) selection of database columns. If the data is changed, the corresponding index will be automatically updated which costs additional performance. There are two different kinds of an index
      • A new alternative key is created on a node. It is recommended to create a secondary index for that alternative key.
    4. Instead of executing the determination immediately after each modification, configure it to the finalize determination time. It will only be executed during the save and thus it will be less often executed than before.
    5. By default, BOPF locks instances automatically while editing them. As transient node instances are always isolated to the current session scope, it is not needed to lock them. 
    6. Queries fetch data from a business object. If the size of data of a business object increases, the query usage can slow down the scenario performance.
    7.  A consumer using a query should specify the information request as fine grained as possible. Thereto the IS_QUERY_OPTIONS parameter should be used: 
      • Use the MAXIMUM_ROWS component in order to restrict the query result 
      • Use the SORTING_OPTIONS in order to get an already sorted result instead of sorting it on ABAP level 
      • Use paging (PAGING_ACTIVE) and hand over the START_ROW or the START_KEY of the desired page

    BOPF archiving 

    Status management

    • Define the status adapter class /BOFU/CL_LIB_STATUS_ADAPTER as a “Status Class” and “Status Derivator” in your business object configuration.

    Comments