logo

Are you need IT Support Engineer? Free Consultant

Validations in BOPF and Consistency Validation in …

  • By Sanjay
  • 09/05/2026
  • 4 Views


Hello Everyone,

In this blog we will be going to learn about the Validations in BOPF.

What is Validation in BOPF? 

In BOPF, a validation is a consistency check defined on a node of the business object that ensures the data fulfills specific business rules before it is saved or processed. 

In BOPF, keeping the data clean and consistent is very important. Validations help achieve this by checking the data against specific rules. Just like determinations, validations are created on the node of the data model where they are needed. Today, we’ll walk you through how to create a validation and write the logic for it in the implementation class. 

Procedure  

Here we are defining a custom Travel table (zkk_dt_travel). 

@EndUserText.label : 'Data base table for Travel Details'
@AbapCatalog.enhancement.category : #EXTENSIBLE_ANY
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #ALLOWED
define table zkk_dt_travel {

  key client     : abap.clnt not null;
  key travel_id  : zkk_de_travel_id not null;
  key user_email : zkk_de_email not null;
  start_date     : dats;
  destination    : zkk_de_destination;
  status         : zkk_de_status;
  expense_type   : zkk_de_item_type;
  @Semantics.amount.currencyCode : 'zkk_travel_hdr.curr_key'
  total_cost     : zkk_de_cost;
  curr_key       : zkk_de_cost_key;
  remarks        : zkk_de_remarks;
  created_by     : zkk_de_createdby;
  created_on     : datum;

}

The above table has the below shown data.

Krishna_Karale_1-1757594071182.Png

For the Database table we are defining the Basic view  

@AbapCatalog.sqlViewName: 'ZKK_DBV_TRAVEL'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Interface view for Travel details'
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true


@ObjectModel:{
modelCategory: #BUSINESS_OBJECT,
compositionRoot: true,
transactionalProcessingEnabled: true,
writeActivePersistence: 'ZKK_dt_travel',

createEnabled: true,
updateEnabled: true,
deleteEnabled: true
}

@OData.publish: true
define view zi_kk_travel
  as select from zkk_dt_travel
{
  key travel_id,
      @ObjectModel.mandatory: true
  key user_email,
      start_date,
      destination,
      status,
      @ObjectModel.mandatory: true
      expense_type,
      @ObjectModel.mandatory: true
      total_cost,
      curr_key,
      remarks,
      created_by,
      created_on
}

For creating the Business object directly from the Eclipse editor, we have to make use of annotations which I have given with their functionality 

Here’s the explanation of each annotation in your snippet: 

@ObjectModel: { 
 modelCategory: #BUSINESS_OBJECT, 
 compositionRoot: true, 
 transactionalProcessingEnabled: true, 
 writeActivePersistence: ‘ZKK_dt_travel', 
 
 createEnabled: true, 
 updateEnabled: true, 
 deleteEnabled: true 
} 
 Explanation 

modelCategory: #BUSINESS_OBJECT 

  • Declares that the CDS view represents a Business Object (BO). This means it can be used in BOPF to handle business logic and transactional operations. 

compositionRoot: true 

  • Defines this entity as the root node of the Business Object. Other nodes (child entities) can be linked to it via composition relationships. 

transactionalProcessingEnabled: true 

  • Enables transactional behavior (create, update, delete, save, rollback) for the entity, making it suitable for business object processing. 

writeActivePersistence: ‘ZKK_dt_travel' 

  • Specifies the database table (ZKK_DT_TRAVEL) where the active (persisted) data of this entity is stored. 

createEnabled: true 

  • Allows the creation of new records in the entity. 

updateEnabled: true 

  • Allows modification of existing records. 

deleteEnabled: true 

  • Allows deletion of records. 

@odata.publish: true    turns your CDS view into an OData service provider, making its data available for consumption via OData protocols. 

In short: 

This annotation block is used to define a CDS entity as a Business Object root node with full CRUD (Create, Read, Update, Delete) support and persistence in the custom table ZKK_DT_TRAVEL. 

Here I am creating the Metadata extension for the Basic view (ZI_KK_TRAVEL) for consuming it in the front end. 

@Metadata.layer: #CORE
@UI.headerInfo: {
    typeName: 'Travel',
    typeNamePlural: 'Travel Details'
}
annotate entity zi_kk_travel
    with 
{
@UI.facet: [{ 
id: 'Travel', 
purpose: #STANDARD, 
position: 10, 
label: 'Travel Details ', 
type: #IDENTIFICATION_REFERENCE 
} ]
 @UI.lineItem: [{ position: 10, label: 'Travel Id' }]
 @UI.identification: [{ position: 10 }]
    travel_id;
 @UI.lineItem: [{ position: 20, label: 'Email' }]
 @UI.identification: [{ position: 20 }]
    user_email;
 @UI.lineItem: [{ position: 30, label: 'Travel Date' }]
 @UI.identification: [{ position: 30 }]
    start_date;
 @UI.lineItem: [{ position: 40, label: 'Destination' }]
 @UI.identification: [{ position: 40 }]
    destination;
 @UI.lineItem: [{ position: 50, label: 'Status' }]
 @UI.identification: [{ position: 50 }]
    status;
 @UI.lineItem: [{ position: 60, label: 'Expense Type' }]
 @UI.identification: [{ position: 60 }]
    expense_type;
 @UI.lineItem: [{ position: 65, label: 'Amount' }]
 @UI.identification: [{ position: 65 }]
    total_cost;
 @UI.lineItem: [{ position: 70, label: 'Currency' }]
 @UI.identification: [{ position: 70 }]
    curr_key;
 @UI.lineItem: [{ position: 80, label: 'Remarks for Expense' }]
 @UI.identification: [{ position: 80 }]
    remarks;
 @UI.lineItem: [{ position: 85, label: 'Created By' }]
 @UI.identification: [{ position: 10 }]
    created_by;
 @UI.lineItem: [{ position: 90, label: 'Created Date' }]
 @UI.identification: [{ position: 90 }]
    created_on;   
}

 Now activate the Basic view and the meta data extension, when it gets activated the Business Object get created implicitly. 

Now open the BOBX Transaction. 

Krishna_Karale_0-1757592499811.Png

We can search the business object in Home business objects or click on the below marked option.

Krishna_Karale_1-1757592499815.Png

Provide the BO name which is our Basic View name (ZI_KK_TRAVEL) 

Krishna_Karale_2-1757592550543.Png

Krishna_Karale_3-1757592550545.Png

Now to Implement the validations expand the Node Elements  

Krishna_Karale_4-1757592664872.Png

Right Click on Validations will see the option to Create Validations 

Krishna_Karale_5-1757592664876.Png

Provide the Validation Name and Description and Class for implementing the validation logic. 

Krishna_Karale_6-1757592724202.Png

Double click on Class Name, and create a class which will be having the super class implicitly 

Krishna_Karale_7-1757592724204.Png

Krishna_Karale_8-1757592724206.Png

Now we have to provide Triggering conditions for the validations, so select the Node instance and tick on Create, Update, Delete and Check  

Krishna_Karale_9-1757592724208.Png

Save it and check and generate it. 

Krishna_Karale_10-1757592724210.Png

After this we have to go to eclipse and create a service definition on basic view (ZI_KK_TRAVEL) 

Krishna_Karale_0-1757593000483.Png

Now create a Service binding on top of Service definition and publish it  

Krishna_Karale_1-1757593000486.Png

When we preview it  

It will be navigated to the frontend while navigating it will ask for your SAP GUI Credentials to login.

Krishna_Karale_2-1757594121268.Png

Now go to SE91 Transaction and create a message class

Krishna_Karale_3-1757593000492.Png

Here, I am doing Validation for a Single status field only so i have passed only two messages  

Krishna_Karale_4-1757593127901.PngNow I want to provide the Validations for Status field, so go to our class which we have created in Validations 

Krishna_Karale_5-1757593127904.PngImplement our Custom login in this method.

  METHOD /bobf/if_frw_validation~execute.

    CLEAR : et_failed_key, eo_message.
    eo_message = /bobf/cl_frw_factory=>get_message( ).
    DATA : lt_data TYPE ztikk_travel,   " Table type for header node
           ls_msg  TYPE symsg.
    io_read->retrieve(
      EXPORTING
        iv_node                 = is_ctx-node_key
        it_key                  = it_key
        iv_fill_data            = abap_true
        it_requested_attributes = VALUE #(
                                          (                 zif_i_kk_travel_c=>sc_node_attribute-zi_kk_travel-status )
                                         ) )
      IMPORTING
        et_data                 = lt_data
    ).
    LOOP AT lt_data REFERENCE INTO DATA(ls_data).
      IF ls_data->status IS INITIAL .
        ls_msg-msgid = 'ZKK_MSG_BOPF'.
        ls_msg-msgno = '000'.
        ls_msg-msgty = 'E'.

        eo_message->add_message(
          is_msg       = ls_msg                 " Message that is to be added to the message object
          iv_node      = is_ctx-node_key            " Node to be used in the origin location
          iv_key       = ls_data->key            " Instance key to be used in the origin location
iv_attribute = zif_i_kk_travel_c=>sc_node_attribute-zi_kk_travel-status
          " Attribute to be used in the origin location
        ).

        INSERT VALUE #( key = ls_data->key ) INTO TABLE et_failed_key.
      ENDIF.

      DATA(lv_status) = to_upper( condense( ls_data->status ) ).
      IF lv_status NA 'ACCEPT' OR lv_status NA 'REJECT'.
        ls_msg-msgid = 'ZKK_MSG_BOPF'.
        ls_msg-msgno = '001'.
        ls_msg-msgty = 'E'.

        eo_message->add_message(
          is_msg       = ls_msg
          iv_node      = is_ctx-node_key
          iv_key       = ls_data->key
          iv_attribute = zif_i_kk_travel_c=>sc_node_attribute-zi_kk_travel-status
        ).

        INSERT VALUE #( key = ls_data->key ) INTO TABLE et_failed_key.
      ENDIF.
    ENDLOOP.
  ENDMETHOD.

Now go to service binding and preview it. Try to create a new record. 

Here I am keeping Status field as empty so it will throw error. 

Krishna_Karale_0-1757593607942.Png

Now Status should accept only ‘ACCEPT’ or ‘REJECT’. If I try to give any other value it will throw error again. 

Krishna_Karale_1-1757593607945.Png

If you give the correct value ‘Accept’ or ‘Reject’. 

Krishna_Karale_2-1757593607947.Png

Conclusion

Validations in BOPF play a vital role in safeguarding data quality and enforcing business rules at the framework level. By defining validations directly on the business object nodes, we ensure that only consistent and compliant data enters the system, regardless of whether it originates from an SAP UI, an external interface, or a background process. This not only strengthens the reliability of the application but also reduces the need for redundant checks across different layers. In short, validations serve as a powerful and centralized mechanism to guarantee data integrity within the BOPF model.



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *