Skip to Content

Last year I set a learning path to catch up with SAP development tools and techniques that in spite of being around for a while now,  the comfort zone was just too comfortable to step out, until the breakthrough came in and I realized I didn’t want to be left behind. After one year things are starting to pay off now :), which is great.

In this opportunity, I want to talk about the Business Object Processing Framework (BOPF), which is yet another way of maintaining database records in an Object-Oriented way. Although this is a rather simplistic view, as it turns out that the framework is capable of doing many more things, such as dealing with authorizations, or even orchestrate the application business logic flow. It can be integrated with several UI technologies, say UI5 or Web Dynpro/FPM.

Following my last examples of modeling a Music Store inside SAP, I wanted to see how could I model this into a Business Object. So I ran my VM instance with the Developer Edition of SAP AS ABAP 751, opened Eclipse and created a new business object

Eclipse has this wizard ready to create BOs

 

I select the package and gave it a name. I’m taking a manual creation here, but we will see later on that is also possible to create BOs from ABAP CDS using some annotations, I’m curious on what is the end result, so I named this “MANUAL” and later on will compare this BO with one created from CDS to see the difference.

 

In the next screen, you are asked to define a persistent structure and a transient structure. The Persistent structure will be the definition of the database table, the transient structure are just fields that can be calculated at runtime, like master data details that you don’t wanna have duplicated in your database tables. For the sake of simplicity, I choose to create only a Persistent structure.

 

 

One very nice thing about ABAP 7.50 is that now we can define structures, data elements and domains from within Eclipse itself, bye bye SE11!

So my structure looks like this:

@EndUserText.label : 'Structure'
@AbapCatalog.enhancementCategory : #NOT_EXTENSIBLE
define type zinstruments_ps {
  @EndUserText.label : 'Serial number of the instrument'
  serialnumber  : abap.char(10);
  @EndUserText.label : 'Company name of the instrument'
  builder       : abap.char(35);
  @EndUserText.label : 'Type of instrument'
  type          : abap.char(30);
  @EndUserText.label : 'Image of instrument'
  picture_url   : abap.char(255);
  @EndUserText.label : 'Price of the instrument'
  @Semantics.amount.currencyCode : 'zinstruments_ps.currency_code'
  price         : abap.curr(15,3);
  @EndUserText.label : 'Currency code'
  currency_code : abap.cuky;
}

You don’t need to remember all of these annotations, there is code completion for each one of them.

The last step is to create a so-called Constants Interface. This is an auto-generated ABAP interface created by the framework, since as we will see shortly, the framework generates 32 characters (256 bits) hexadecimal identifiers, rather than plain number ranges or incremented integers. This interface makes easy to identify the BO

By clicking on the link Go to the ROOT node, an overview window displays what we can achieve with this BO

Here we can see the persistent structure defined in the wizard, also a combined structure, which is autogenerated by combining the persistent and transient structure. We also see a table type for this structure, and finally the database table that will be generated upon the activation of the BO. So by clicking the activate button, the database table will look like this:

Note that we didn’t define any DB_KEY field in the structure, it was inserted by the framework, every database table created via the BOPF will have this field marked as part of the key.

Now, going back to the BO overview -not the rote node overview, we can navigate to the nodes.

Business objects are organized in a hierarchical fashion through these nodes. At design time, we can think of a parent node and a child node as a relationship between Header and Item tables, for example. At runtime, nodes behave like internal tables grouping these instances together, and for which we can perform operations. In this case, I created a second BO, with a separate database table for managing the descriptions of my main instruments table.

 

OK, now that we have modeled our BOs, it’s time to play around with them through some ABAP code. We can manipulate the business objects through the BOPF API, that is composed of mainly 3 interfaces: The Service manager, that allow us to communicate with node elements, so we can execute queries, navigate through the hierarchy, perform actions, etc. There’s also the Transaction Manager, we use this interface to commit changes to the database, or even rollback changes. Then there is the configuration interface, which at this point I’m not entirely sure how to use it, but it seems that it is used to get the metadata from a BO -If anyone knows how to use it, I’m all ears.

 

  data: root_node_combined_structure type ref to zinstruments_cs,
        texts_combined_structured    type ref to zbo_s_instruments_texts.

  data modifications type /bobf/t_frw_modification.

  try.
      data(transaction_manager) = /bobf/cl_tra_trans_mgr_factory=>get_transaction_manager( ).
      data(service_manager) = /bobf/cl_tra_serv_mgr_factory=>get_service_manager( zif_bo_instruments_manual_c=>sc_bo_key ).
      data(object_configuration) = /bobf/cl_frw_factory=>get_configuration( zif_bo_instruments_manual_c=>sc_bo_key ).
    catch /bobf/cx_frw.
      "Are you sure the Business Object is active?
  endtry.

  "Create order root node
  create data root_node_combined_structure.
  root_node_combined_structure->key = /bobf/cl_frw_factory=>get_new_key( ).
  root_node_combined_structure->builder   = 'Fender'.
  root_node_combined_structure->serialnumber = 'FOO123'.
  root_node_combined_structure->currency_code = 'EUR'.
  root_node_combined_structure->price = '100'.
  root_node_combined_structure->type = 'electric'.

 

So I start by getting some instances from the BOPF API factory class, note that for the Service Manager and object configuration, I pass the bo key that the framework generated for me in the constants interface, it feels nicer to refer to it as ZIF_BO=>SC_BO_KEY rather than 0800279DF3981ED7B18B0BBFE6C68691.

Then I create my root node structure, get a new key from the API factory, and populate my fields.

append initial line to modifications assigning field-symbol(<modification>).
  <modification>-node = zif_bo_instruments_manual_c=>sc_node-root.
  <modification>-change_mode = /bobf/if_frw_c=>sc_modify_create.
  <modification>-key = root_node_combined_structure->key.
  <modification>-data = root_node_combined_structure.

Here I just say that I’m going to perform a new modification of type MODIFY_CREATE, and pass the attributes created before.

 "Create Instrument texts
  create data texts_combined_structured.
  texts_combined_structured->key = /bobf/cl_frw_factory=>get_new_key( ).
  texts_combined_structured->language_code = sy-langu.
  texts_combined_structured->name = |Instrument { root_node_combined_structure->serialnumber }|.

Here I do the same thing but with the child node -Remember that I set a separate BO to store the texts.

  append initial line to modifications assigning <modification>.
  <modification>-node = zif_bo_instruments_manual_c=>sc_node-instruments_texts.
  <modification>-change_mode = /bobf/if_frw_c=>sc_modify_create.
  <modification>-source_node = zif_bo_instruments_manual_c=>sc_node-root.
  <modification>-association = zif_bo_instruments_manual_c=>sc_association-root-instruments_texts.
  <modification>-source_key  = root_node_combined_structure->key.
  <modification>-key = texts_combined_structured->key.
  <modification>-data = texts_combined_structured.

This next step is to append the child node to the modifications table, and create an association between them. So when I save, I will have a record in the Instrument table and another one in the texts table.

Now it’s time to save these changes in the memory, prior to commit the changes in the database.

  service_manager->modify( exporting it_modification = modifications    " Changes
                           importing eo_change       = data(change_object)     " Interface of Change Object
                                     eo_message      = data(message) ).   " Interface of Message Object

The last step is to commit our changes to the database, if there were no errors.

  "Check results
  if change_object->has_failed_changes( ) = abap_false.
    transaction_manager->save( importing eo_message  = data(messages)
                               ev_rejected = data(change_rejected) ).
  endif.

 

And that’s it! I’ve got a record in the texts table

And another one in the Instruments table.

Next time I will be working through the process of querying these tables through the API.

 

Happy coding!

 

 

To report this post you need to login first.

8 Comments

You must be Logged on to comment or reply to a post.

  1. Prasenjit Singh Bist

    Thank you so much for sharing, the new capabilities with 7.5 it seems ABAP is on fire now. I recently got chance to write a small application on BOPF in Solman and I really enjoyed it. May be because of lack of quality documentation people are scred to use it but it’s the easiest framework.

    Thanks to experts like you for sharing and helping us learn.

    regards,

    Prasenjit

     

    (1) 
    1. Marco Hernandez Post author

      Hi Prasenjit,

      Well I’m far for being an expert in the matter. These posts respond to the fact that I’m just learning the technologies, and this process of doing and explaining what I’m trying to achieve really helps in the overall understanding on the subject. I also read a lot in this community, so there’s also a retribution aspect involved.  Thank you for taking the time to read, stay tuned!

      (0) 
  2. Thomas Fiedler

    Nice blog. Thanks for sharing your experiences. You should definitly have a look on CDS. Because BOPF + CDS + Eclipse is the future of modern ABAP development. You are on the right track.

     

    Regards,

    Thomas.

    (2) 
    1. Marco Hernandez Post author

      Oh yeah, I saw there is a way of generating BOs by using some annotations within CDS. Will get to that as soon as I become familiar with the manual settings and the API. Thanks for pointing it out!

      (0) 
  3. Paul Hardy

    Hello!

    One thing I would note is that this technology is evolving very quickly i.e. with every new release of SAP there are somewhat radical changes to the BOPF.

    Some people have a right go at me for having a “model class” where I have all my business logic, and then the actions / validations and so on in the BOPF business object outsource the function to my re-usable class. I also use that self same class in SEGW Gateway functions (DPC Class). Did you know thus very day I was told by someone within SAP to stop using the term “Gateway” as it was old fashioned? I should say rather “Frontend UI5 server” or some such, and then the name iwll change again next week.

    The point is that these frameworks change so fast I feel I need another layer of abstraction as – amazingly – the underlying technology changes faster than the business requirements! That is backwards to what you might expect.

    Moreover from what I saw at Teched the other day SAP has some sort of plan to use a “business definition language” to define BOPF behavior in the same way a CDS view can define database access behavior in an abstract way.

     

    (2) 
    1. Marco Hernandez Post author

      Lol, I wonder if they have people whose jobs are to come up with new terminology, just to confuse things a little more.

      Since it is possible create BOs from within CDS, it makes sense to invest more in the definition language itself and provide that kind of functionality.

      (0) 
  4. Roberto Vacca

    Nice blog.

    What I really like more of all those new stuff in ABAP and all other programming languages, is that behind all there will always be pure machine code .

    A car can be more attractive with all the stuff and optionals we see nowdays, but how many people can repair a gasoline injection withouth a mechanic? Only if you know the machine code you can do it.

    After all the present and future will always be 0 and 1.

    Regards,

    (0) 

Leave a Reply