Skip to Content

A Short Glimpse at BRFplus

One strength of the ABAP Application Server is that it contains powerful APIs for business programming: The SAP Webflow, the Business Partner Application, a Parallelization Framework to mention a few. SAP did some backports of wellestablished frameworks from industrial solutions, too. A prominent example is the Business Rule Framework that is heavily used in the Claims-Management solution FS-CM and was moved to SAP_ABA at release 6.20.

Frameworks for business rules are a cornerstone in business programming – Carsten Ziegler explained this fact in one of his blogs. But I never liked the BRF: it was much too slow and to weak for my purposes. One reasonfor the lack of speed have been long derivation hirarchies (up to 12 levels) which slowed it down. Then Carsten Ziegler announced the new BRFplus-Framework in his blogs – and believe me: it is really cool stuff.

You’ll find more information about it on the wiki. And on TechEd Carsten gave a challeging lecture about further aspects, the integration with SAP BRM.

How to start with BRFplus?

Fortunately SAP did a great job and created a lot demo reports so that you find a lot of examples within the system. So just start SE80 within you NSP system 7.01 and watch out for package SFTD. Within this package you’ll find the package SFDT_DEMO_REPORTS.

One example is a decision table: Report FDT_TUTORIAL_DDIC_DECTABLE that calculates shipping costs. The selection screen is


The report calculates the shipping costs by calling an external function. The result is:


The logic of the decision table is described within the report. Perhaps you’ll ask what’s so cool about it because you can code this functionality faster. But what happens if your customer wants to change the rule without modifying your code?  To cope with these requirements you’ll need a framework like BRFplus. And last but not least hard coded business logic buried in function modules is far from being transparent.

The report FDT_TUTORIAL_DDIC_DECTABLE is somewhat complicated because he creates this function dynamically by generating an expression DDIC_TAB_DDIC_TEST. So at first we should have a look at the generated objects. So at first call transaction SICF and switch on the FDT* nodes of the web dynpro applications and stadt transaction FDT_WORKBENCH. On th eleft side you see under the TMP-tree node a lot of generated stuff – data objects, expressions and functions:


Of course we need only to look at the last function – the rest was generated from experiments I did earlier. If we doubleclick on this function the function details are shown:


In this weblog I will mention only two things: Please remember the ID DDB7332BF… generated by report FDT_TUTORIAL_DDIC_DECTABLE (I guess on your system it may differ). The second is the Top expression DDIC_TAB_DDIC_TEST. If we navigate to it we see the decison table I mentioned earlier:


This is in fact a classical decision table containing logical conditions. I suggest that you’ll explore it on your own. I suggest to create your own decision tables, formulas and even decision trees.

But how do you call them from ABAP? This is easy by changing the report FDT_TUTORIAL_DDIC_TABLE:

REPORT  zfdt_tutorial_ddic_dectable.

      lo_function       TYPE REF TO if_fdt_function,
      lo_factory        TYPE REF TO IF_FDT_FACTORY,
      ls_struct         TYPE fdt_stru_demo_courier,
      lt_struct         TYPE STANDARD TABLE OF fdt_stru_demo_courier,
      lt_message        TYPE if_fdt_types=>t_message,
      lo_context        TYPE REF TO if_fdt_context,
      lo_result         TYPE REF TO if_fdt_result,
      lv_name           type if_fdt_types=>name,
      lx_fdt            TYPE REF TO cx_fdt.

PARAMETERS: pv_t1 TYPE fdt_demo_dtel_region,
            pv_t2 TYPE fdt_demo_dtel_category,
            pv_t3 TYPE fdt_demo_dtel_wt_range.

FIELD-SYMBOLS <ls_message> LIKE LINE OF lt_message.

lo_factory  = cl_fdt_factory=>if_fdt_factory~get_instance( ).
lo_function = lo_factory->get_function( 'DDB732BF26C105F1A405AABD5595E6A3' ).
lo_context  = lo_function->get_process_context( ).
lo_context  = lo_function->get_process_context( ).

lo_context->set_value( iv_name = 'REGION'   ia_value = pv_t1 ).   "#EC NOTEXT
lo_context->set_value( iv_name = 'CATEGORY'
ia_value = pv_t2 ).   "#EC NOTEXT

lo_context->set_value( iv_name = 'WEIGHT'   ia_value = pv_t3 ).   "#EC NOTEXT

    lo_function->process( EXPORTING io_context = lo_context
                          IMPORTING eo_result = lo_result ).
  CATCH cx_fdt INTO lx_fdt.
*   error handling
    LOOP AT lx_fdt->mt_message ASSIGNING <ls_message>.
      WRITE / <ls_message>-text.

*Display output:

CLEAR ls_struct.

DATA: lv_total TYPE
lo_result->get_value( IMPORTING ea_value = ls_struct ).
WRITE:/ 'Basic charge in $: ', ls_struct-basic_charge.      "#EC NOTEXT
WRITE:/ 'Additional Charge in $: ', ls_struct-additional_charge. "#EC NOTEXT
lv_total = ls_struct-basic_charge + ls_struct-additional_charge.
WRITE:/ 'Total Charge  in $:', lv_total.                    "#EC NOTEXT

And this is how it works: You only need an ID (in our case it was DDB732*) to get the function, then you define the context by calling the set_value() methods and then the process() method does the rest. It’s really easy and very generic.

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