The primary purpose of this blog is to present a basic idea of bol programming.

Refer : How To Guide Business Object Layer Programming

Sample Code for BOL Creation :

*Loading a BOL object using CL_CRM_BOL_CORE
*You can use this class to access directly with Business object implementations.
*Also said as Heart of Root objects , only single instance can exists per session.
*To create or modify you need a reference of BOL object factory. 

Scenario : Create a Lead , Campaign , Business Partner or One Order transaction
               using Reports or use in methods of BAdis to get the instance of object.
Below is the code Creation of Activity – One Order Object in CRM system.

 

DATA : lr_core TYPE REF TO cl_crm_bol_core.
TRY.
     lr_core = cl_crm_bol_core=>get_instance( ).
     lr_core->load_component_set( 'BT' )      .
   CATCH cx_crm_genil_general_error.
ENDTRY.
*
*-->Build Create Parameters of Root Object.
DATA: ls_params               TYPE crmt_name_value_pair.
DATA: lt_params               TYPE crmt_name_value_pair_tab.
CLEAR : ls_params , lt_params[].
*
*-->Build Create parameters Root Object 'BTOrder'
*--> Process Type
ls_params-name   = 'PROCESS_TYPE'.
ls_params-value   =  'ZACTIVITY'.
APPEND ls_params TO lt_params.
*
*Create Root Instance or Entity Factory.
*
DATA : lr_factory             TYPE REF TO cl_crm_bol_entity_factory.
DATA : lr_order               TYPE  REF TO cl_crm_bol_entity.
*-->Note Either use root_create or get_entity_factory to create.
*--> Obtain Factory of Root Object in Entity.
TRY.
     lr_factory = lr_core->get_entity_factory( iv_entity_name = 'BTOrder' ).
     lr_order = lr_factory->create( lt_params ).
   CATCH cx_crm_unsupported_object.
ENDTRY.
DATA : lr_adminh TYPE REF TO cl_crm_bol_entity.
*--> Get Dependent Objects.
lr_adminh = lr_order->get_related_entity( iv_relation_name = 'BTOrderHeader' ).
IF lr_adminh IS NOT BOUND.
   TRY.
*-->Create Dependent Objects.
       lr_adminh = lr_order->create_related_entity( iv_relation_name = 'BTOrderHeader').
     CATCH cx_crm_genil_duplicate_rel cx_crm_genil_model_error.
   ENDTRY.
ENDIF.
DATA : ls_admin TYPE crmst_adminh_btil.
lr_adminh->get_properties( IMPORTING es_attributes = ls_admin ).
ls_admin-description = 'Activity Creation'.
ls_admin-posting_date = '20140110'.
lr_adminh->set_properties( EXPORTING is_attributes = ls_admin ).
*
DATA: lr_activity   TYPE REF TO cl_crm_bol_entity.
*--> Get Dependent Objects.
lr_activity = lr_adminh->get_related_entity( iv_relation_name = 'BTHeaderActivityExt' ).
IF lr_activity IS NOT BOUND.
   TRY.
*-->Create Dependent Objects.
       lr_activity = lr_adminh->create_related_entity( iv_relation_name = 'BTHeaderActivityExt' ).
     CATCH cx_crm_genil_duplicate_rel cx_crm_genil_model_error.
   ENDTRY.
ENDIF.
*
* -->set the attribute using set_property method.
DATA : ls_activity       TYPE  crmst_activityh_btil.
*
lr_activity->get_properties( IMPORTING es_attributes = ls_activity ).
ls_activity-category    = '101'..
ls_activity-priority    = '01'.
ls_activity-objective   = '003' .
lr_activity->set_properties( EXPORTING is_attributes = ls_activity ).
*
* -->Submit Root Objects and Child Objects Which are created.
* -->Always call modify on bol core.
lr_core->modify( ).
*
*Save and Commit Changes Using Global Transaction Context
*
DATA: lr_transaction TYPE REF TO if_bol_transaction_context .
DATA: lv_success     TYPE crmt_boolean.
*
lr_transaction = lr_core->get_transaction( ).
IF lr_transaction->check_save_needed( ) EQ abap_true
AND  lr_transaction->check_save_possible( ) EQ abap_true.
   lv_success = lr_transaction->save( ).
   IF lv_success IS NOT INITIAL.
     lr_transaction->commit( ).
   ELSE.
     lr_transaction->rollback( ).
   ENDIF.
ENDIF.







Sample Code for BOL SEARCH

Scenario : Retrieving the data of Business Partner , One Order transaction , Lead ,
Activity or any other business objects this can be done via

      CL_CRM_BOL_QUERY_SERVICE and CL_CRM_BOL_DQUERY_SERVICE class objects.

DATA : lr_core TYPE REF TO cl_crm_bol_core.
TRY.
     lr_core = cl_crm_bol_core=>get_instance( ).
     lr_core->load_component_set( 'BT' )      .
   CATCH cx_crm_genil_general_error.
ENDTRY.
DATA: lr_qs       TYPE REF TO cl_crm_bol_dquery_service,
       ls_param     TYPE        crmt_name_value_pair,
       lt_param     TYPE        crmt_name_value_pair_tab,
       lr_result    TYPE REF TO if_bol_entity_col,
       lr_iter      TYPE REF TO if_bol_entity_col_iterator,
       lr_entity    TYPE REF TO cl_crm_bol_entity.
*
*Get and prepare dynamic query service.
lr_qs ?= cl_crm_bol_dquery_service=>get_instance( 'BTQAct' ).
*
* Set Query Parameters.
ls_param-name = 'MAX_HITS'.
ls_param-value = '5'.
APPEND ls_param TO lt_param.
lr_qs->set_query_parameters( lt_param ).
*
*Add selected parameters or criteria .
lr_qs->add_selection_param( iv_attr_name = 'EMPLOYEE_RESP'
                             iv_sign = 'I'
                             iv_low  = '*'
                             iv_option = 'EQ'
                             iv_high = ' ').
*Execute Query and retrieve result
lr_result = lr_qs->get_query_result( ).
*
CHECK lr_result IS BOUND.
*Use Iterator to access entities in query result
lr_iter ?= lr_result->get_iterator( ).
*
* Get the first record from Collection.
lr_entity = lr_iter->get_first( ).
*
DATA : lv_guid TYPE crmt_object_guid.
DATA : lv_object_id TYPE crmt_object_id_db.
DATA : lr_parent TYPE REF TO cl_crm_bol_entity.
WHILE lr_entity IS BOUND.
*Access Attributes of Business object.
   lv_guid = lr_entity->get_property_as_string( 'GUID' ).
   WRITE lv_guid.
   lr_entity = lr_iter->get_next( ).
ENDWHILE.






*********************************************************************************************************************

Sample Code for BOL CHANGE OR UPDATE ENTITY

Scenario : To Modify or update a Business Object entities.

To update BOL entity , First we need to search using Search Object and get the entity object (Root object ) once we can the instance of Root object we can update the entity.

For Search : Use Above code use as reference.

data : lr_core type ref to cl_crm_bol_core.
    lr_core = cl_crm_bol_core=>get_instance( ).
     TRY.
         lr_core->start_up( EXPORTING iv_appl_name = 'ONEORDER'
                                      iv_display_mode_support = abap_true ).
       CATCH cx_crm_genil_general_error.                 "#EC NO_HANDLER
     ENDTRY.
DATA:
         lr_qs                     TYPE REF TO cl_crm_bol_query_service,
         lr_iterator              TYPE REF TO if_bol_entity_col_iterator,
         lr_search_result_coll   TYPE REF TO if_bol_entity_col,
lr_btorder TYPE REF TO cl_crm_bol_entity,
      lr_btorder_h TYPE REF TO cl_crm_bol_entity.
 *  Start BT Appl
   lr_qs = cl_crm_bol_query_service=>get_instance( 'BTQuery1O' ). "#EC NOTEXT
* set search parameters
   CALL METHOD lr_qs->set_property
     EXPORTING
       iv_attr_name = 'OBJECT_ID'
       iv_value     =  lv_object_id.
* set search parameters, Bus Object type 'LEAD'
   CALL METHOD lr_qs->set_property
     EXPORTING
       iv_attr_name = ' OBJECT_TYPE'
       iv_value     =  'BUS2000108'.
   lr_search_result_coll = lr_qs->get_query_result( ).
   IF lr_search_result_coll IS BOUND.
     lr_iterator = lr_search_result_coll->get_iterator( ).
   ENDIF.
IF lr_iterator IS BOUND.
     lr_btorder = lr_iterator->get_first( ).
ENDIF.
*Get the Entity of Activity Object
CALL METHOD lr_btorder->get_related_entity
   EXPORTING
     iv_relation_name = 'BTOrderHeader'
   RECEIVING
     rv_result        = lr_order_h.
CATCH cx_crm_genil_model_error .
ENDTRY.
*
lr_order_h->switch_to_change_mode( ).
*Locks are always set on root object.
IF lr_order_h->lock( ) = 'X'.
IF lr_order_h->is_changeable( ) = 'X'.
*
*Set property also locks the object entity if lock has not been set.
   lr_order_h->if_bol_bo_property_access~set_property( iv_attr_name = 'DESCRIPTION'
                                                               iv_value     = 'Melbourne' ).
*Modify BOL layer
   lr_core->modify( ).
ENDIF.ENDIF.
*
lr_transaction = lr_core->get_transaction( ).
lv_success = lr_transaction->save( ).
if lv_success eq abap_true. lr_transaction->commit( ).
endif.








*****************************************************************************************************

Sample Code for BOL Delete   

* Use Above code for Entity Object
lr_entity ?= lr_result->get_first( ).
*
*Lock and modify the property
IF  lr_entity->lock( ) = if_genil_boolean=>true.
  lr_entity->delete( ).
*Modify the Core Object
  lr_core->modify( ).
ENDIF.
* Then Again Use save and commit using transaction context.











****************************************************************************************************************************************

UI Development Codes

Saving Object into Database EH_ONSAVE

You use this interface to control transaction behaviour using if_bol_transaction_context.

  DATA lr_tx      TYPE REF TO if_bol_transaction_context.
   DATA lr_entity  TYPE REF TO cl_crm_bol_entity.
   DATA lr_core    TYPE REF TO cl_crm_bol_core.
*
   lr_entity ?= me->typed_context->object_name->collection_wrapper->get_current( ).
   lr_tx = lr_entity->get_transaction( ).
   IF lr_tx IS NOT BOUND.
     lr_core = cl_crm_bol_core=>get_instance( ).
     lr_tx = lr_core->begin_transaction( ).
   ENDIF.
   IF lr_tx IS BOUND.
     IF lr_tx->check_save_possible( ) = abap_true.
       CHECK lr_tx->save( ) = abap_true.
       lr_tc->commit( ).
     ENDIF.
   ENDIF.
   me->view_group_context->reset( ).










*********************************************************************************************************************

Cancel Changes or Reset Objects EH_ONCANCEL

DATA lr_entity   TYPE REF TO cl_crm_bol_entity.
DATA lr_tx          TYPE REF TO if_bol_transaction_context.
*
lr_entity ?= me->typed_context->node->collection_wrapper->get_current( ).
lr_tx = lr_entity->get_transaction( ).
lr_tx->revert( iv_suppress_buffer_sync = abap_true ).
me->view_group_context->reset( ).










**********************************************************************************************************************

Edit Objects EH_ONEDIT

DATA: lr_entity TYPE REF TO cl_crm_bol_entity.
*
   lr_entity ?= me->typed_context->node->collection_wrapper->get_current( ).
*
   CHECK lr_entity IS BOUND.
*
   CHECK lr_entity->is_change_allowed( ) = abap_true.
   lr_entity->lock( ).
*
   IF lr_entity->is_locked( ) = abap_false.
     me->view_group_context->reset( ).
   ELSE.
     me->view_group_context->set_all_editable( ).
ENDIF.










**********************************************************************************************************************

Config Use of DO_CONFIG_DETERMINATION method to change the screen layout.

*For Each Object type and Subobject type combination, there is 1 view configuration
*
lv_object_type        = 'ZOBJTYP'.
lv_subobject_type    = 'ZSUBTYP'.
*
* Set the config keys to fetch relevant configuration.
me->set_config_keys( iv_object_type          = lv_object_type
                      iv_object_sub_type      = lv_subobject_type
                      iv_propagate_2_children = abap_true ).










********************************************************************************************************************

Set or Populate value nodes with value using CL_BSP_WD_VALUE_NODE

TYPES: BEGIN OF str,
              status TYPE char20,
            END OF str.
*
* Structure of status context node.
DATA  lr_struct_ref    TYPE REF TO str.
*
* Structure of your context node
data  ls_struct    type  str.
*
DATA lr_value_node    TYPE REF TO cl_bsp_wd_value_node.
*
CREATE DATA lr_struct_ref.
CREATE OBJECT lr_value_node
   EXPORTING
     iv_data_ref = lr_struct_ref.
ls_struct-status = 'Your Value'.
lr_value_node->if_bol_bo_property_access~set_properties( ls_struct ).
*
*Add Value Node to a collection
typed_context->testnode->collection_wrapper->add( lr_value_node ).










Get a model node from Mixed node using CL_BSP_WD_MIXED_NODE

 

DATA: lr_mixednode TYPE REF TO cl_bsp_wd_mixed_node,
          lr_access TYPE REF TO if_bol_bo_property_access.
*
*Get the current entity from your mixed node
lr_mixednode ?= me->typed_context->contexnodename->collection_wrapper->get_current( ).
lr_access ?= lr_mixednode->if_bsp_wd_ext_property_access~get_model_node( ).











Display Custom Internal Table on UI  on a Table View Context Node.

DATA : lr_valuenode        TYPE REF TO cl_bsp_wd_value_node.         " Collection to fill node
DATA : lr_tabline             TYPE REF TO ty_org.                                 " Type Structure
DATA : lr_ent_col            TYPE REF TO if_bol_bo_col.
DATA : lr_coll_wrapp       TYPE REF TO cl_bsp_wd_collection_wrapper. " Collection Wrapper
CREATE DATA lr_tabline.
     CREATE OBJECT lr_ent_col TYPE cl_crm_bol_bo_col.
     LOOP AT lt_table INTO ls_str.
*     Create value object with current line for colleciton
       CREATE OBJECT lr_valuenode
         EXPORTING
           iv_data_ref = lr_tabline.
*
*     Set current line data
       lr_valuenode->set_properties( ls_str ).
*     Add current line to collection
       lr_ent_col->add(
         EXPORTING
           iv_entity    =  lr_valuenode    " Access Interface for BO Attributes
                      ).
     ENDLOOP.
     typed_context->context_node->collection_wrapper->clear_collection( ).
     CREATE OBJECT lr_coll_wrapp.
     lr_coll_wrapp->set_collection( lr_ent_col ).
     typed_context->salesorg->set_collection_wrapper( lr_coll_wrapp ).
     typed_context->context_node->build_table( ).




Access or Read a Context Node of another Component using Controllers if they are linked with each other.

 

data : lr_object type ref to  cl_bsp_wd_view_controller.
IF lr_object IS NOT BOUND.
   lr_object =                me->get_subcontroller_by_viewname( iv_viewname = 'ComponentName/MainWindow' ).
     IF lr_object IS BOUND.
      lr_object =     lr_object->get_subcontroller_by_viewname( iv_viewname = 'ComponentName/ViewSet' ).
       IF lr_object IS BOUND.
        lr_object =   lr_object>get_subcontroller_by_viewname( iv_viewname = 'ComponentName/ViewName' ).
       ENDIF.
     ENDIF.
ENDIF.

 

Sequence of some of the methods called when component is loaded.

Order of methods before displaying the view :

1) DO_INIT_CONTEXT  is basically used to initialize the context nodes or pre-populate them with some values.

2) DO_VIEW_INIT_ON_ACTIVATION Always called, after context init is used for registering the handlers.

3) DO_CONIG_DETERMINATION is used  to change the screen layout.

4) SET_VIEW_GROUP_CONTEXT in general used to on overview page to set a view in editable , display or reset         mode.

5) DO_PREPARE_OUTPUT is used at every each event in order to refresh or default the initial values based upon the parameter iv_first_time = ‘X’.

6) .HTM Page is to load bsp page

7) Get_XXX methods of the attributes transfer BOL data to view code text fetch logic can be implemented in this method.

After the user perform some action the order will be as follows :

 

1) DO_HANDLE_DATA  is called at the runtime after user has made inputs on the view or a user action has been triggered.

2) SET_XXX methods of the attributes transfer view data to BOL field conversion can be implemented in this method.

3) DO_VALIDATE_INPUT is used to validate the data of the whole context before  it is transferred to the APIs.

4) DO_HANDLE_EVENT Responsible for triggering the corresponding event handler depending on the user actions triggered.

5) DO_FINISH_INPUT  used at the end of all the data input on the screen.ex: when user press Enter on view

 

 

To report this post you need to login first.

24 Comments

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

    1. Sumeet Gehlot Post author

      Hi Christian ,

      I was not aware of this doc…

      I am trying to put as many as sample codes in a single blog and more code samples yet to upload related to navigations pop ups dropdows on click actions etc…..so that if required it can be used by all.

      if there is still any issue related to posing this doc , let me know so that i will delete

      Regards,

      Sumeet

      (0) 
      1. Christian Dr. Drumm

        Hi Sumeet,

        i think the examples related to pop ups and drop downs could be interesting.

        With respect to the BOL examples I think you should link to the BOL How To Guide as it is IMHO a very good and complete document.

        Best,

        Christian

        (0) 
  1. Andrey Vishnevskiy

    Hello, Sumeet.

    Thank you for bringing my attention to this post.

    In case of any doubts how to classify this or that content on SCN I personally always refer to The Difference between a Discussion, Blog Post, Document and Wiki document.

    To my mind this particular content had to be put as a Wiki. Or at least a document. Because a blog is intended to express your own opinion or experience.

    I think it’s too late to convert to either a wiki or a document now. Quite many people have already bookmarked, rated or liked it. Could you please put at least a reference to the BOL programming guide mentioned by Christian Drumm in your blog post itself? And please use a mentioned post to classify your content in the future. Thank you.

    (0) 
  2. Abhi Rockzz

    HI christian

    Thank’s for the post on BOL , it was very helpful.could you please refer me any video links for BOLprogramming.

    Thanks

    ABHI

    (0) 
  3. Alexander Krisananto

    Hi Sumeet,

    Nice post. I have a dew question about updating a bol layer. I already get a bol header from search method. But it seems doesn’t work when I updating the bol layer, after I debug it, the entity is not changeable. I already used the display mode support and switch to change mode. I copied your code in my work, but it still doesn’t change to change mode. Does you have some advise about this case?

    Thanks for your share in this blog. It’s very helpful.

    (0) 
    1. Sumeet Gehlot Post author

      Hi Alexander,

      If your header entity is locked, then it wont switch to change mode or in a changeable mode.

      Check the entity might have been locked (already in edit mode) from the front end or gui transaction.

      Regards,

      Sumeet

      (0) 
      1. Alexander Krisananto

        Hi Sumeet,

        Thanks for your reply. So, that’s mean I can change it directly, since it already in edit mode? or I set it to display mode and then start to lock it again to change the properties values?

        Regards.

        (0) 
        1. Sumeet Gehlot Post author

          Hi,

          once entity is locked from front end u will be not able to change by code also, try setting it to display mode and then start to lock it again to change the properties values…


          Regards,

          Sumeet

          (0) 
    1. Christian Dr. Drumm

      Hi Rohan,

      you can get the messages from the message container. I’m currently unsure if the BP messages end up in the global message container (via bol_core->get_global_message_cont( )) or in the message container of the entity (

      bol_core->get_message_cont_manager( )->get_message_cont()). In one of those message containers you should be able to read the error messages.

      The following document describes the different message handling approaches in more detail: http://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/f08a833a-f5c0-2e10-bf94-d464bf5355dc?overridelayout=t…

      Christian

      (0) 
      1. Rohan Parab

        Dear Christian,

        I have already tried this but I am not able to get messages from lr_core->get_global_message_cont->if_genil_message_container~get_messages

        or lr_core->get_message_cont_manager->get_message_cont->get_messages

        We have to modify the core then get messages from lr_entity->get_message_container to get error messages.

        Thanks & Regards,

        Rohan

        (0) 
        1. Rohan Parab

          Dear Christian,

          Due to this my number range skips if there exists any error and if I roll backed the transaction.

          Is there exist any other solution.

          Thanks Regards,

          Rohan

          (0) 
          1. Christian Dr. Drumm

            Hi Rohan,

            what do you mean with “my number range skips?”.

            Whenever a number is requested from a number range object the number range is increased. For example, if you try to create a BP a new BP number is requested from the number range object. If an error occurs the transaction is rolled back an the BP is not created. If you try to create a new BP again the next number from the number range is requested. The number used in the failed transaction is “lost” and won’t be reused.

            If this is the problem you are talking about, there is no solution for it. It is the core functionality of the number range objects that can’t be changed.

            Christian

            (0) 
            1. Rohan Parab

              Dear Christian,

              You are right but there should be some method to check data before requesting number from number range object.

              I have used BOL it is quiet simple and requires less coding but I am not able to figure out how errors are calculated. Number is requested when I write below statement:

              lr_entity = lr_factory->create( lt_params )

              I have got errors only after below code:

              lr_core->modify( )

              lr_msg_cont = lr_entity->get_message_container( ) “Root Entity

              Using this method if central data contains error number always goes for nothing.

              I tried using BAPI also it requires some extra efforts in coding but atleast checks for errors and if central data contains error it does not generate a number.

              Thanks & Regards,

              Rohan

              (0) 
  4. Igor Barbaric

    Hi Sumeet,

    Having experience with BOL programming already, but 2 years ago, I had to jump into it again, with no time for nice and easy recap (as usually). Your blog, however, contained just about everything one needs for such a lightning fast (re)start.

    Thanks for this!

    Igor

    (0) 
  5. Puneet Mittal

    Hi Sumeet,

    Firstly thanks for sharing a nice document.. it is very helpful to create business transaction using BOL Proramming.

    I have followed this document. When i am modifying our transaction i am getting interface changed at runtime.

    While run this line lr_core->modify( ) then i am getting dump.

    Can you please help me out to this issue.

    Regards,

    Puneet Mittal

    (0) 

Leave a Reply