Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
jwood_bowdark
Active Participant
41,827

In my previous blog james.wood/blog/2013/01/16/navigating-the-bopf-part-3--working-with-the-bopf-api, I introduced the BOPF API and demonstrated how the API could be used to perform routine CRUD operations on a business object. With this basic introduction out of the way, we're now ready to tackle more advanced API features such as consistency checks, the execution of actions, and transaction management. So, without further ado, let's get started.

Performing Consistency Checks & Validations

In keeping with the object-oriented paradigm, business objects (BOs) are designed to combine business data and business functions together into one tidy capsule (hence the term encapsulation). One of the primary benefits of combining these entities is to ensure that updates to business data are reliably filtered through a set of business rules. To put this concept into perspective, imagine a BO which defines a header-level status field (e.g. 01 = Initial, 02 = In Process, 03 = Closed). Now, from a pure data perspective, there's nothing stopping us from updating the status field using the MODIFY() method of the /BOBF/IF_TRA_SERVICE_MANAGER interface (or heck, even via an SQL UPDATE statement). However, from a business perspective, there are probably some rules which define when, where, and how we should change the status field. For example, it might be that the BO cannot be closed until any open line items are closed out, etc.

Whatever the business rules might be, the point is that we want to ensure that a BO is consistent throughout each checkpoint in its object lifecycle. As we learned in part 2 of this blog series, the BOPF allows us to define these consistency checks in the form of validations. For example, in the screenshot below, you can see how SAP has created a validation called CHECK_ROOT for the ROOT node of the /BOBF/DEMO_SALES_ORDER demo BO. This validation is used to perform a consistency check on the sales order header-level fields to make sure that they are valid before an update is committed to the database.

One of the nice things about validations like CHECK_ROOT is that they are automatically called by the BOPF framework at specific points within the transaction lifecycle. However, sometimes we might want to trigger such validations interactively. For example, when building a UI on top of a BO, we might want to provide a check function which validates user input before they save their changes. This is demonstrated in the /BOBF/DEMO_SALES_ORDER Web Dynpro ABAP application shown below.

From a code perspective, the heavy lifting for the check operation is driven by the CHECK_CONSISTENCY() method of the /BOBF/IF_TRA_SERVICE_MANAGER interface as shown in the code excerpt below. Here, we simply provide the service manager with the target node key and the BO instance key and the framework will take care of calling the various validations on our behalf. We can then check the results of the validation by looking at the /BOBF/IF_FRW_MESSAGE instance which was introduced in the previous blog.

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.

TRY.

  APPEND INITIAL LINE TO lt_key ASSIGNING <ls_key>.

  <ls_key>-key = iv_key.     "<== Sales Order BO Key

  CALL METHOD mo_svc_mngr->check_consistency

    EXPORTING

      iv_node_key    = /bobf/if_demo_sales_order_c=>sc_node-root

      it_key         = lt_key

      iv_check_scope = '1'

    IMPORTING

      eo_message     = lo_message.

    ...

CATCH /bobf/cx_frw INTO lx_frw.

  ...

ENDTRY.

I'll show you how to implement validations within a BO in an upcoming blog entry.

Triggering Actions

The behaviors of a business object within the BOPF are defined as actions. From a conceptual point-of-view, actions are analogous to methods/functions in the object-oriented paradigm. The following code excerpt demonstrates how actions are called using the BOPF API. Here, we're calling the DELIVER action defined in the ROOT node of the /BOBF/DEMO_SALES_ORDER demo BO. As you can see, the code reads like a dynamic function/method call since we have generically pass the name of the action along with its parameters to the DO_ACTION() method of the /BOBF/IF_TRA_SERVICE_MANAGER interface. Other than that, it's pretty much business as usual.

DATA lt_key TYPE /bobf/t_frw_key.

FIELD-SYMBOLS <ls_key> LIKE LINE OF lt_key.

DATA ls_parameters     TYPE /bobf/s_demo_sales_order_hdr_d.

DATA lr_s_parameters   TYPE REF TO data.

DATA lo_change         TYPE REF TO /bobf/if_tra_change.

DATA lo_message        TYPE REF TO /bobf/if_frw_message.

DATA lt_failed_key     TYPE /bobf/t_frw_key.

DATA lt_failed_act_key TYPE /bobf/t_frw_key.


TRY.

  "Set the BO instance key:

  APPEND INITIAL LINE TO lt_key ASSIGNING <ls_key>.

  <ls_key>-key = iv_key.     "<== Sales Order BO Key


  "Populate the parameter structure that contains parameters passed

  "to the action:

  ls_parameters-item_no = '001'.

  GET REFERENCE OF ls_parameters INTO lr_s_parameters.


  "Call the DELIVER action defined on the ROOT node:

  CALL METHOD mo_svc_mngr->do_action

    EXPORTING

      iv_act_key           = /bobf/if_demo_sales_order_c=>sc_action-root-deliver

      it_key               = lt_key

      is_parameters        = lr_s_parameters

    IMPORTING

      eo_change            = lo_change

      eo_message           = lo_message

      et_failed_key        = lt_failed_key

      et_failed_action_key = lt_failed_act_key.


    ...

CATCH /bobf/cx_frw INTO lx_frw.

  ...

ENDTRY.

We can verify if a BOPF action call was successful by querying the EO_MESSAGE object reference and/or the ET_FAILED_KEY table parameters returned by the DO_ACTION() method. Refer back to my previous james.wood/blog/2013/01/16/navigating-the-bopf-part-3--working-with-the-bopf-api for an example of the former technique. As always, remember to commit the transaction using the

SAVE() method defined by the /BOBF/IF_TRA_TRANSACTION_MGR interface.

Action Validations

In part james.wood/blog/2013/01/04/navigating-the-bopf-part-2--business-object-overview of this blog series, I mentioned that there are technically two different types of validations: the consistency check validations discussed earlier in this blog and action validations which are used to determine whether or not an action can be executed at runtime. Since the BOPF framework invokes action validations automatically whenever actions are invoked, it is rare that you will have a need to invoke them directly. However, the /BOBF/IF_TRA_SERVICE_MANAGER interface does provide the DO_ACTION() method if you wish to do so (see the code excerpt below).

DATA lt_key TYPE /bobf/t_frw_key.

FIELD-SYMBOLS <ls_key> LIKE LINE OF lt_key.

DATA ls_parameters     TYPE /bobf/s_demo_sales_order_hdr_d.

DATA lr_s_parameters   TYPE REF TO data.

DATA lo_message        TYPE REF TO /bobf/if_frw_message.

DATA lt_failed_key     TYPE /bobf/t_frw_key.

DATA lt_failed_act_key TYPE /bobf/t_frw_key.


TRY.

  "Set the BO instance key:

  APPEND INITIAL LINE TO lt_key ASSIGNING <ls_key>.

  <ls_key>-key = iv_key.     "<== Sales Order BO Key


  "Populate the parameter structure that contains parameters passed

  "to the action:

  ls_parameters-item_no = '001'.

  GET REFERENCE OF ls_parameters INTO lr_s_parameters.


  "Check to see if the DELIVER action can be invoked:

  CALL METHOD mo_svc_mngr->check_action

    EXPORTING

      iv_act_key           = /bobf/if_demo_sales_order_c=>sc_action-root-deliver

      it_key               = lt_key

      is_parameters        = lr_s_parameters

    IMPORTING

      eo_message           = lo_message

      et_failed_key        = lt_failed_key

      et_failed_action_key = lt_failed_act_key.


    ...

CATCH /bobf/cx_frw INTO lx_frw.

  ...

ENDTRY.

Transaction Management

Another element of the BOPF API that we have glossed over up to now is the transaction manager interface /BOBF/IF_TRA_TRANSACTION_MGR. This interface provides us with a simplified access point into a highly sophisticated transaction management framework. While the details of this framework are beyond the scope of this blog series, suffice it to say that the BOPF transaction manager does more here than simply provide basic object-relational persistence. It also handles caching, transactional locking, and more. You can see how some of these features are implemented by looking at the Transactional Behavior settings of a business object definition in Transaction /BOBF/CONF_UI (see below).

So far, we have seen a bit of the /BOBF/IF_TRA_TRANSACTION_MGR on display whenever we looked at how to insert/update records. Here, as you may recall, we used SAVE() method of the /BOBF/IF_TRA_TRANSACTION_MGR interface to save these records. In many respects, the SAVE() method is analogous to the COMMIT WORK statement in ABAP in that it commits the transactional changes to the database. Here, as is the case with the COMMIT WORK statement, we could be committing multiple updates as one logical unit of work (LUW) - e.g. an insert followed by a series of updates.

Once a transaction is committed, we can reset the transaction manager by calling the CLEANUP() method. Or, alternatively, we can also use this method to abandon an in-flight transaction once an error condition has been detected. In the latter case, this is analogous to using the ROLLBACK WORK statement in ABAP to rollback a transaction.

During the course of a transaction, the BOPF transaction manager tracks the changes that are made to individual business objects internally so that it can determine what needs to be committed and/or rolled back. If desired, we can get a peek of the queued up changes by calling the GET_TRANSACTIONAL_CHANGES() method of the /BOBF/IF_TRA_TRANSACTION_MGR interface. This method will return an object reference of type /BOBF/IF_TRA_CHANGE that can be used to query the change list, modify it in certain cases, and so on.

Next Steps

At this point, we have hit on most of the high points when it comes to interacting with the BOPF API from a client perspective. In my next blog, we'll shift gears and begin looking at ways of enhancing BOs using the BOPF toolset.

17 Comments
Labels in this area