Skip to Content

In my previous two blog posts, we explored the BOPF API from a client point-of-view. Here, we learned how to perform basic CRUD operations, execute actions, and so on. Now that you have a feel for how the API operates, we’re ready to take a peek behind the curtain and see these services are implemented within the business objects themselves. For now, our emphasis will be on enhancing these services since SAP does not yet support the creation of new business objects. However, whether we’re enhancing existing business objects or creating new ones from scratch, the concepts remain the same.

What to Enhance?

Before we dive into the exploration of specific enhancement techniques, let’s first take a look at the kinds of entities we’re allowed to enhance in a business object. Aside from implicit enhancements applied to implementation classes using the Enhancement Framework, the types of entities that we can enhance within a business object are as follows:

  • Custom Attributes
    • For a given node, we might want to define a handful of additional custom attributes.These attributes could be persistent  (i.e., they get appended to the target database table which contains the node data) or transient in nature.
  • New Sub-Nodes
    • In some cases, we may need to do more than simply define a few new attributes on an existing node. Using the relational data model as our guide, we may determine that a new sub-node is needed to properly model some new dimension of data (e.g. 1-to-many relations, etc.). Depending on the requirement, the sub-node(s) might be persistent or transient in nature.
  • Determinations
    • If we add new custom attributes to a given node, it stands to reason that we might also want to create a custom determination to manage these attributes.
    • Or, we might have a standalone requirement which calls for some sort of “trigger” to be fired whenever a specific event occurs (e.g. fire an event to spawn a workflow, etc.).
  • Consistency Validations
    • If we are enhancing the data model of a business object, we might want to define a consistency validation to ensure that the new data points remain consistent.
    • A custom validation might also be used to graft in a new set of business rules or a custom security model.
  • Actions
    • If we have certain operations which need to be performed on a business object, we would prefer to encapsulate those operations as an action on the business object as opposed to some standalone function module or class.
  • Queries
    • In some cases, the set of defined queries for a business object might not be sufficient for our needs. In these situations, we might want to define custom queries to encapsulate the selection logic so that we can use the generic query services of the BOPF API as opposed to some custom selection method.

BOPFEnhancement.png

You can find a detailed treatment of supported enhancement options in the BOPF Enhancement Workbench Help documentation which is provided as a separate download in SAP Note #1457235. This document provides a wealth of information concerning the use of the BOPF Enhancement Workbench, enhancement strategies, and even the BOPF framework in general. Given the amount of detail provided there, I won’t attempt to re-invent the wheel in this blog post. Instead, I’ll simply hit on the high points and leave the nitty-gritty details to the help documentation.

Working with the Enhancement Workbench

When enhancing a business object, you’ll be spending quite a bit of time with the BOPF Enhancement Workbench which can be accessed using Transaction BOPF_EWB. Here, enhancement projects are organized into enhancement objects. From a conceptual point-of-view, enhancement objects bear a lot of similarities to sub-classes in the object-oriented programming (OOP) paradigm. This is to say that enhancement objects inherit all of the entities of their parent BO. With this foundation in place, we can begin defining custom entities in much the same way we might add new attributes/methods to a subclass in the ABAP Class Builder tool. However, as is the case with classes in the OOP world, we cannot extend BOs which are marked as final or that do not have the “Business Object can be enhanced” flag set (see below).

Settings.png

All of the BOs which are eligible for enhancement will show up in the Enhancement Browser perspective of the BOPF Enhancement Workbench shown below. To create an enhancement, simply right-click on the BO that you wish to enhance and select the Create Enhancement menu option (see below). From here, the BOPF Enhancement Workbench will guide you through a wizard process which allows you to select the name of the enhancement object, the constants interface for the enhancement object, and so on.

Creation.png

Once the enhancement is created, you will be able to edit your enhancement object in the workbench perspective of the BOPF Enhancement Workbench shown below. As you can see, it has a similar look-and-feel to that of the normal BO browser tool (Transaction /BOBF/CONF_UI). From here, we can begin adding custom entities by right-clicking on the target node and selecting from the available menu options. We’ll see how this works in the upcoming sections.

Enhancement.png

One final item I would draw your attention to with enhancement objects is the assigned constants interface (highlighted above). This constants interface can be used to access the enhancement object entities in the same way that the super BO’s constants interface is used for BOPF API calls, etc.

Enhancing the BO Data Model

Perhaps the most common type of enhancement to BOs in the BOPF is the addition of new fields. Here, we have the option of adding new fields to existing nodes or creating sub-nodes to model more complex relationships. In the former case, we sometimes don’t even need to create an enhancement object; just a simple append structure will suffice (see below).

NewFields.png

For more complex data requirements, we typically need to define sub-nodes. This can be achieved by right-clicking on the parent node and selecting the Create Subnode menu option. This kicks off a wizard process in which you can select the sub-node’s name, its persistent and/or transient structures, and the rest of the auto-generated dictionary types which go along with a node definition (e.g. combined structure/table type, database table, etc.). Most of this is pretty standard stuff, but I would draw your attention to the step which creates the persistent and/or transient structures. Note that these structures must exist in the database before you move on from the Attributes step in the wizard process. And, in the case of the persistent structure, you must include the /BOBF/S_ADMIN structure as the first component.

SubNode2.png

After the custom sub-node is created, you can fill out its attributes by adding components to the persistent/transient structures defined by the sub-node. If the sub-node is a persistent node, then we can create, modify, and retrieve node instances using the BOPF API as per usual. However, in the case of transient nodes, we need determinations to pre-fetch the data for us. We’ll see how to define such determinations next.

Defining Determinations

According to the help documentation, determinations encapsulate internal changing business logic on a business object. Unlike the logic encapsulated in actions which can be triggered at any time, the business logic contained within determinations is triggered as specific times within the BO life cycle (e.g. right before a node is saved, etc.). So, in a way, it is appropriate to think of determinations as being a little bit like user exits/BAdIs/enhancement spots in that they provide a place to hang custom logic at particular points within the process flow.

Once we determine (no pun intended) that we want to create a determination for a given node, we can do so by simply right-clicking on that node and selecting the Create Determination menu option. This will spawn a wizard which guides us through the process. Here, there are two main properties that we must account for:

  1. Implementing Class:
    • We must create or assign an ABAP Objects class that implements the /BOBF/IF_FRW_DETERMINATION interface.
  2. Determination Pattern:
    • This property defines the event which triggers the determination. As you can see below, the set of available patterns will vary depending on the type of node you’re enhancing, its location in the node hierarchy, and so on.
    • Once a pattern is selected, you may be presented with additional options for refining when an event is triggered. For example, if we select the pattern “Derive dependent data immediately after modification”, we will have the opportunity to specify if the dependent data should be created/modified after any modification, only when the node is created the first time, etc.

DetPattern.png

Because determinations can be used for a lot of different things, they can be implemented in a lot of different ways. Here, it is very important that you pay close attention to selecting the right pattern for the right job. The aforementioned help documentation provides a good set of guidelines to assist here. Other valuable resources include the interface documentation for the /BOBF/IF_FRW_DETERMINATION interface in the Class Builder tool and SAP standard-delivered determinations implementations available in the system you’re working on.

Defining Consistency Validations

The process of defining a custom consistency validation is quite similar to the one used to define determinations. Walking through the wizard process, there are three main properties that we must account for:

  1. Implementing Class:
    • Here, we must create/assign an ABAP Objects class which implements the /BOBF/IF_FRW_VALIDATION interface.
  2. Request Nodes:
    • This property allows us to specify which node operations should force a validation to occur (e.g. during creates, updates, etc.)
  3. Impact:
    • With this property, we can specify the behavior of the BOPF framework in cases where the validation fails. For example, should we simply return an error message, prevent the requested operation from proceeding, or both?

From an implementation perspective, the /BOBF/IF_FRW_VALIDATION interface provides us with everything we need to perform the validation check: the context of the validation, the current data within the node instance being validated, and so on. For more information about how to implement the validation class, I would highly recommend that you read through the interface documentation for the /BOBF/IF_FRW_VALIDATION interface in the Class Builder tool. It can also be helpful to look at various standard-delivered classes which already implement this interface to see common patterns/idioms used by SAP.

Working with Actions

When it comes to the customization of actions, we have a couple of options:

  • We can create a brand new action definition for a given node (standard or custom).
  • We can enhance existing actions with pre/post action enhancements.

The first case is pretty straightforward. Basically, we simply follow along with the wizard process up to the point that we reach the Settings step shown below. Here, we must define three main properties for the action:

  • Implementing Class:
    • This property is used to specify the ABAP Objects class which encapsulates the action logic. The class must implement the /BOBF/IF_FRW_ACTION interface.
  • Action Cardinality:
    • The action cardinality property defines the scope of the action. This is somewhat analogous to the way we have the option of defining class methods or instance methods within a regular ABAP Objects class. In this case however, we also have the third option of defining a sort of “mass-processing” action which works on multiple node instances at once.
  • Parameter Structure:
    • If we wish to pass parameters to the action, we can plug in an ABAP Dictionary structure here to encapsulate the parameters.

Action.png

Once the action is created, we simply need to plug in the relevant logic in the defined implementation class. You can find implementation details for this in the interface documentation and/or sample action classes in the system.

In order to create a pre/post action enhancement, the target action definition in the super BO must have its “Action Can Be Enhanced” flag set (see below). Assuming that the flag is set, then we can proceed through the corresponding wizard process in much the same way we would if we were creating a custom action from scratch. Indeed, as is the case with regular actions, the implementation class(es) for pre/post action enhancements must implement the /BOBF/IF_FRW_ACTION interface.

EnhAction.png

Before you go to implement a pre/post action enhancement, I would definitely recommend that you read through the help documentation so that you understand what you can and cannot do within an action enhancement. Most of the rules are intuitive, but you can definitely get into trouble if you abuse these enhancements by using them for things they weren’t designed for.

Defining Custom Queries

Compared to the various enhancement options we’ve seen thus far, custom queries are perhaps the easiest entities to create within an enhancement object. Indeed, if all we want is a simple node attribute query, we can zip through the wizard and have a working model up and running in a matter of minutes. If we want something a little more custom/sophisticated, our job is only marginally more difficult (at least from a configuration perspective) in that we must assign an implementing class and an optional data type which serves as the parameter structure passed into the query from the client side (see below).

Query1.png

From an implementation perspective, all of the query logic for a custom query gets encapsulated in the implementation class (which must implement the /BOBF/IF_FRW_QUERY interface). For the most part, you’ll find that the framework doesn’t really get in the way with regards to how we go about implementing the query. Basically, it passes in the query parameters up front and it’s up to us to figure out how to find all of the node instances which match the given parameters. Here, we must pay careful attention to the SQL statements that we use since the query may be used extensively by a number of different clients.

Next Steps

Hopefully by now you have a general feel for how BOs are enhanced and the basic steps required to achieve these enhancements. As is the case with most programming-related subjects, the best way to really drive these concepts home is to look at live examples and experiment for yourself. I would also highly recommend that you read through the aforementioned help documentation as it devotes quite a bit of time to understanding when and where to apply specific enhancement techniques.

In my next and final blog post in this series, I’ll demonstrate another useful tool within the BOPF toolset: the BO test tool. This tool can be used to experiment with BOs and perform ad hoc unit tests, etc.

To report this post you need to login first.

15 Comments

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

    1. Former Member Post author

      Hi Werner,

      It actually uses its own mechanisms which are in many respects more sophisticated (e.g. buffering/caching, etc.).

      Thanks,

      James

      (0) 
  1. Former Member

    Hi James,

    Is it possible to hide FPM button( in module MOC ) via BOPF?

    I tried by enhancing FPM configurations by unchecking enable  and setting visible property to not visible.

    Still I couldn’t achieve it.

    Please let me know if there are differnet ways to achieve the above.

    Thanks in advance.

    Regards,

    Bob.

    (0) 
  2. aparna trivedi

    Hi James,

    These BOPF blogs are truly an insight. Thanks for publishing them.

    I want to implement an enhancement on Location BO (EHSM) for that i have created a freestyle Webdynpro component . Now as per the SAP help portal it says i can use the freestyle helper class /BOFU/CL_FREESTYLE_BOPF_HELPER to use BOPF functionality in my Webdynpro component.

    Please advice how to use this class in the freestyle Webdynpro component.

    Thanks in Advance.

    Regards,

    Aparna

    (0) 
    1. Former Member Post author

      Hi Aparna,

      If it were me, I’d use this class as follows:

      1. Create a subclass of /BOFU/CL_FREESTYLE_BOPF_HELPER and designate that subclass as the assistance class for your WDA component.
      2. Implement the IF_FPM_UIBB_MODEL WDA component interface in your freestyle UIBB (just like you did with IF_FPM_UI_BUILDING_BLOCK).
      3. Implement the GET_MODEL_API() method by returning an instance of your assistance class (e.g. WD_ASSIST).
      4. Enhance the regular callback methods from IF_FPM_UI_BUILDING_BLOCK by calling the HANDLE_*() methods of the assistance class. Of particular importance here is probably the HANDLE_FLUSH() method.
      5. Use the FPM wire model to connect your freestyle UIBB as the source/target of wire connections as per usual. Here, the pre-built implementations for methods from the IF_FPM_FEEDER_MODEL interface in /BOFU/CL_FREESTYLE_BOPF_HELPER should allow you to use your freestyle UIBB just like you would GUIBBs, etc.

      Hope this helps.

      Thanks,

      James

      (0) 
      1. aparna trivedi

        Hi James,

        Thank you for your reply.

        I am able to relate and understand all  the steps except no. 5.

        When i see the enhanced standard component configuration wiring model it doesn’t show this freestyle component in the Wiring model to connect with the existing LIST and FORM UIBB’s.

        Regards,

        Aparna

        (0) 
        1. Former Member Post author

          Hi Aparna,

          Have you already performed steps 1-4? Without step #2 in particular, the component’s not really wire-model enabled, so I expect FLUID wouldn’t detect it in the wire editor. I’d recommend stubbing this out and trying again to see if that helps.

          Thanks,

          James

          (0) 
          1. aparna trivedi

            Hi James,

            Thanks again for your time.

            The freestyle WD component has both the interfaces implemented IF_FPM_UIBB_MODEL WDA  and  IF_FPM_UI_BUILDING_BLOCK.

            But in the component configuration i can see there is an Error saying ‘Error at instantiation of component ZWDXXXX with config ID ZCC_XXX’. This error disappears the moment i save my Comp Config enhancement.

            Do you think this can be a reason my  component is not appearing in FPM wiring model.

            Please see an image of how i am configuring my freestyle component.Comp Config.PNG

            (0) 
            1. Former Member Post author

              Hi Aparna,

              It’s kind of hard to speculate without looking at your component, but I’d look very closely at the initialization methods in your WDA component’s component controller to see if that’s the culprit here. Bear in mind that FLUID will instantiate your component in order to pull in relevant metadata at design time. Normally, I see this error whenever developers attempt to perform initialization routines which reference runtime-related data that’s not there at design time (e.g., application parameters, shared data from an application controller, etc.). I’d set some external breakpoints and see if that’s the issue.

              Thanks,

              James

              (0) 
              1. aparna trivedi

                Hi James,

                I am able to use my freestyle webdynpro component now to enhance the standard location object.

                But i am stuck with a strange issue here. In the WDC i have a table to add some fields and update them in location BO. After saving the fields for first time it gets saved in BO but the SAVE button is disabled due to which i am not able to add more entries.

                Have you faced this kind of issue before or any suggestions how we can get rid of this.

                Thanks for your time.

                Regards,

                Aparna

                (0) 
                1. Former Member Post author

                  Hi Aparna,

                  How are you synchronizing your table entries with the BOPF? Normally the FBI application controller class will check to see if save is required/enabled based on whether or not there are changes queued up in the BOPF. I’d look over your implementation there and also check your application controller settings around transaction management to see if the pattern is set to change the edit mode after a save.

                  Thanks,

                  James

                  (0) 
  3. Former Member

    Hi James,

    I have a query on the enhancement technique in BOBF.

    There is an option to create Business Object Enhancement from transaction BOBX where I can provide my Super Business Object. In this case I can use the enhanced BO for my custom actions and other custom functionality.

    Now if we try to create a BO in the transaction /BOBF/CONF_UI, then it provides an option to enter a Super Business Object. In this case too I will be able to create my custom functionality.

    But in the second case it doesn’t show as Enhancement object. What is the difference between these two? When can we use the first option and when the second one.

    Thanks

    Arun

    (0) 
  4. Former Member

    Hello James,

    Explain pls how to enhance existing BO.

    In this article enhancement means subclassing but whether after subclassing existing software which use superclass BO will use my enhancements? or subclassed BO can only be used with new business code?

    I need to add validations to existing business object and want it will take effect on existing code. Should I follow actions in this article or my case is different?

    Thanks,

    Vladimir

    (0) 
    1. Former Member Post author

      Hi Vladimir,

      The inheritance/subclassing metaphor was meant mostly to describe the structural relationship between an enhancement BO and its parent/base BO. However, while this metaphor is sufficient for describing the design time relationship(s), it does break down at runtime since the BOPF does not allow one to address/instantiate enhancement BOs separately. In effect, any enhancement elements you define (e.g. determinations, validations, etc.) become grafted into the overall runtime model for the parent BO (though at a somewhat lower precedence level in that they generally run after the standard elements). Thus, any custom validations you define would take effect immediately without any modifications to the code that uses the parent BO.

      So, to answer your question, yes – any validations you add will take effect on existing code. And yes, the steps outlined in this article would apply for your use case.

      Hope this helps.

      Thanks,

      James

      (0) 

Leave a Reply