OData (Open Data Protocol) services are widely used in SAP to expose data and business logic to external applications in a standardized way. While OData provides metadata for entities and properties, custom annotations can add additional context or metadata to enhance client applications. This blog demonstrates how to enhance an OData service with custom annotations, providing a complete explanation, coding steps, and expected output.
Custom annotations are user-defined metadata extensions added to the standard metadata of an OData service. They provide additional information about entities, properties, or operations, enabling client applications to:
In SAP, annotations are often used to control aspects such as field visibility, data validation, or dynamic behavior, offering greater flexibility for client applications.
In this example, we will enhance an OData service to add a custom annotation that specifies the visibility of certain fields based on the user role. This annotation dynamically informs the client whether a field should be displayed.
The visibility of these fields will vary depending on the user’s role. For instance:
Create a new project in SEGW (Transaction: SEGW)
Define the Data Model:
Properties: Productid, ProductName, Category, Price
Redefine the GET_ENTITYSET method in the DPC_EXT class to provide data.
METHOD zproductset_get_entityset.
DATA: lt_products TYPE TABLE OF zrv_t_product,
ls_product TYPE zrv_t_product.
" Sample data
ls_product-productid = 'P001'.
ls_product-productname = 'Laptop'.
ls_product-category = 'Electronics'.
ls_product-price = '1500.00'.
APPEND ls_product TO lt_products.
ls_product-productid = 'P002'.
ls_product-productname = 'Table'.
ls_product-category = 'Furniture'.
ls_product-price = '500.00'.
APPEND ls_product TO lt_products.
" Transfer data to the framework
copy_data_to_ref( EXPORTING is_data = lt_products
CHANGING cr_data = et_entityset ).
ENDMETHOD.
Redefine the DEFINE method in the MPC_EXT class to add custom annotations.
method DEFINE.
SUPER->define( ).
" Access the entity type
data(lo_entity_type) = model->get_entity_type( iv_entity_name = 'ZProduct' ).
" Add a custom annotation
DATA(lo_annotation) = lo_entity_type->/iwbep/if_mgw_odata_annotatabl~create_annotation( iv_annotation_namespace = 'Custom.Visibility' ).
lo_annotation->add( iv_key = 'FieldVisibility'
iv_value = 'Dynamic based on user role' ).
" Assign annotation to a property
DATA(lo_property) = lo_entity_type->get_property( iv_property_name = 'Price' ).
lo_property->/iwbep/if_mgw_odata_annotatabl~create_annotation( iv_annotation_namespace = lo_annotation ).
endmethod.
In this step, we define a custom annotation called Custom Visibility to specify visibility rules based on the user's role. We then assign this annotation to the Price property.
Modify the GET_ENTITYSET method in the DPC_EXT class to provide dynamic annotations based on user roles.
METHOD zproductset_get_entityset.
DATA: lt_products TYPE TABLE OF zrv_t_product,
ls_product TYPE zrv_t_product,
lv_user_role TYPE string.
" Determine user role (fetch from user context or session)
lv_user_role = me->get_user_role( ).
" Sample data
ls_product-productid = 'P001'.
ls_product-productname = 'Laptop'.
ls_product-category = 'Electronics'.
ls_product-price = '1500.00'.
APPEND ls_product TO lt_products.
ls_product-productid = 'P002'.
ls_product-productname = 'Table'.
ls_product-category = 'Furniture'.
ls_product-price = '500.00'.
APPEND ls_product TO lt_products.
" Apply role-based filtering
LOOP AT lt_products ASSIGNING FIELD-SYMBOL(<ls_product>).
CASE lv_user_role.
WHEN 'Admin'.
" Admin sees all fields
CONTINUE.
WHEN 'Viewer'.
CLEAR: <ls_product>-price.
WHEN OTHERS.
CLEAR: <ls_product>.
ENDCASE.
ENDLOOP.
" Transfer data to the framework
copy_data_to_ref( EXPORTING is_data = lt_products
CHANGING cr_data = et_entityset ).
ENDMETHOD.
In this method, we dynamically filter out fields based on the user's role. For instance, the Viewer role will only see Productid, ProductName and Category while the Restricted role will not see any product data.
Once the service is implemented and tested, the following behavior should be observed:
The $metadata document will include custom annotations as follows:
Admin Role:
All fields (Productid, ProductName, Category, and Price) will be visible.
For a Viewer Role:
Product Price will be hidden.
Restricted Role:
No fields will be visible.
Custom annotations in OData services provide a powerful way to enhance metadata, allowing you to define specific behaviors and rules that can be utilized by client applications. In this blog, we demonstrated how to implement custom annotations to dynamically control field visibility based on the user's role. By using the power of custom annotations, you can tailor your OData service to meet specific business needs and provide a more personalized user experience.
This approach can be extended to other use cases such as data validation, dynamic formatting, and even triggering specific actions based on user roles.