Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Andre_Fischer
Product and Topic Expert
Product and Topic Expert

Introduction


Since the View Maintenance Tools (SM30/SM34) are not available in SAP BTP ABAP Environment another solution had to be offered in order to store and transport customizing data.

The solution for this requirement are Business Configuration Objects that have been explained in detail in the following blog of thomas.schneider.

Business Configuration for SAP Cloud Platform ABAP Environment | SAP Blogs

A Business Configuration Object is essentially a RAP Business Object. It defines the fields that can be changed by the user to influence the behavior of an app. SAP partners register their configuration objects via the ABAP API MBC_CP_API so they are shown in the Maintain Business Configurations Fiori app which is documented here:

Maintain Business Configurations App - SAP Help Portal

The RAP Business Object must be draft enabled and has to provide a service binding of type OData V4 - UI .

When creating a new Business Configuration Object Registration, the name of the OData v4 Service Binding must be supplied. The SMBC logical transport object, that is created during registration, is assigned to the package of the registered Service Binding.

How to create Business Configuration Objects ?


How to create a Business Configuration Object has been described in this tutorial. However, creating such an object still creates lots of manual steps so it was obvious that generating this type of boiler plate coding would be a perfect fit for the RAP Generator.

Please note, that it is planned to provide an out of the box solution based on the ABAP Development Tools in Eclipse with an upcoming release.

Nevertheless it is possible to use the RAP Generator to generate appropriate Business Configuration Objects already now.

The RAP Generator is described in the following blog and can be downloaded from GitHub from this repository.

Generating a Business Configuration


So lets look how you can generate a Business Configuration Object, register it automatically for the use in the Maintain Business Configuration App and have also the code generated so that your data can be transported.

1. Create tables


We will use the same data model as in the aforementioned tutorial and will start to create two tables ZFCAL_HOLI_344 and ZFCAL_HOLTXT_344. Be sure to use the delivery class C or S.

Table for root entity view: ZFCAL_HOLI_344 
@EndUserText.label : 'zfcal_holi_344'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #C
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zfcal_holi_344 {
key client : mandt not null;
key holiday_id : abap.char(30) not null;
month_of_holiday : abap.numc(2);
day_of_holiday : abap.numc(2);
changedat : timestampl;
config_deprecation_code : config_deprecation_code;
local_last_changed_at : timestampl;
created_by : syuname;
created_at : timestampl;
last_changed_by : syuname;

}

Table for child view: ZFCAL_HOLTXT_344.
@EndUserText.label : 'ZFCAL_HOLTXT_344'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #C
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zfcal_holtxt_344 {
key client : mandt not null;
@AbapCatalog.textLanguage
key spras : spras not null;
key holiday_id : abap.char(30) not null;
fcal_description : abap.char(100);

}

2. Create JSON file


In order to use the RAP Generator you simply have to provide the following JSON string to the RAP Generator:
{
"implementationType": "managed_semantic",
"namespace": "ZFCAL",
"suffix": "_344",
"prefix": "",
"package": "Z_CUST_344",
"datasourcetype": "table",
"bindingtype": "odata_v4_ui",
"draftenabled": true,
"transportrequest": "",
"iscustomizingtable": true,
"addbusinessconfigurationregistration": true,
"hierarchy": {
"entityName": "Holiday",
"dataSource": "zfcal_holi_344",
"drafttable": "zfcal_holid344",
"objectId": "holiday_id",
"lastChangedAt": "changedat",
"lastChangedBy": "last_changed_by",
"createdAt": "created_at",
"createdBy": "created_by",
"localInstanceLastChangedAt": "local_last_changed_at",
"children": [
{
"entityName": "HolidayText",
"dataSource": "zfcal_holtxt_344",
"drafttable": "zfcal_holtxtD344",
"objectId": "holiday_id",
"localInstanceLastChangedAt": "local_last_changed_at"
}
]
}
}

 
"implementationType": "managed_semantic"

The implementation type we choose is managed with semantic key fields.
"namespace": "ZFCAL",
"suffix": "_003 "

The namespace of our tables is ZFCAL and we have used a suffix 003 for testing purposes.
"bindingtype": "odata_v4_ui",
"draftenabled": true,


The binding type must be OData V4 - UI and the RAP object has to be draft enabled.
"isCustomizingTable": true,
"addBusinessConfigurationRegistration": true,

The two new parameters that enable the generation and registration of a business object are the parameters isCustomizingTable and addBusinessConfigurationRegistration.

When setting isCustomizingTable to true the RAP Generator will generate the appropriate coding to call the transport API into the behavior definition classes.

The parameter addBusinessConfigurationRegistration instructs the RAP Generator to call the Maintain Business Configurations API to create Business Object registration.

Maintain Business Configurations API - SAP Help Portal

3. Create console application


The above mentioned JSON file can be used in the following command line application
CLASS zcl_rap_generator_cust_344 DEFINITION
PUBLIC
INHERITING FROM cl_xco_cp_adt_simple_classrun
FINAL
CREATE PUBLIC .

PUBLIC SECTION.
PROTECTED SECTION.
METHODS: main REDEFINITION.
PRIVATE SECTION.
ENDCLASS.



CLASS zcl_rap_generator_cust_344 IMPLEMENTATION.
METHOD main.

DATA(json_string) = '{' && |\r\n| &&
' "implementationType": "managed_semantic",' && |\r\n| &&
' "namespace": "ZFCAL",' && |\r\n| &&
' "suffix": "_344",' && |\r\n| &&
' "prefix": "",' && |\r\n| &&
' "package": "Z_CUST_344",' && |\r\n| &&
' "datasourcetype": "table",' && |\r\n| &&
' "bindingtype": "odata_v4_ui",' && |\r\n| &&
' "draftenabled": true,' && |\r\n| &&
' "transportrequest": "",' && |\r\n| &&
' "iscustomizingtable": true,' && |\r\n| &&
' "addbusinessconfigurationregistration": true,' && |\r\n| &&
' "hierarchy": {' && |\r\n| &&
' "entityName": "Holiday",' && |\r\n| &&
' "dataSource": "zfcal_holi_344",' && |\r\n| &&
' "drafttable": "zfcal_holid344",' && |\r\n| &&
' "objectId": "holiday_id",' && |\r\n| &&
' "lastChangedAt": "changedat",' && |\r\n| &&
' "lastChangedBy": "last_changed_by",' && |\r\n| &&
' "createdAt": "created_at",' && |\r\n| &&
' "createdBy": "created_by",' && |\r\n| &&
' "localInstanceLastChangedAt": "local_last_changed_at",' && |\r\n| &&
' "children": [' && |\r\n| &&
' {' && |\r\n| &&
' "entityName": "HolidayText",' && |\r\n| &&
' "dataSource": "zfcal_holtxt_344",' && |\r\n| &&
' "drafttable": "zfcal_holtxtD344",' && |\r\n| &&
' "objectId": "holiday_id",' && |\r\n| &&
' "localInstanceLastChangedAt": "local_last_changed_at"' && |\r\n| &&
' }' && |\r\n| &&
' ]' && |\r\n| &&
' }' && |\r\n| &&
'}'.

DATA(rap_generator) = NEW /dmo/cl_rap_generator( json_string ).
DATA(todos) = rap_generator->generate_bo( ).
DATA(rap_bo_name) = rap_generator->root_node->rap_root_node_objects-service_binding.
out->write( |RAP BO { rap_bo_name } generated successfully| ).
out->write( |Todo's:| ).
LOOP AT todos INTO DATA(todo).
out->write( todo ).
ENDLOOP.
ENDMETHOD.

ENDCLASS.

 

As a result you will see that the following in our package.

 


 

 

4. Run console application


When we let the class run by pressing F9 we get the following output
RAP BO ZFCALUI_Holiday_344_O4 generated successfully
Todo's:
Messages from XCO framework
Type: BDEF Object name: ZFCALC_HOLIDAY_344 Message: The field "HOLIDAYID" is used for "parent" dependency (in the ON clause
Type: BDEF Object name: ZFCALC_HOLIDAY_344 Message: of the association "_Holiday"). This means it should be flagged as
Type: BDEF Object name: ZFCALC_HOLIDAY_344 Message: "readonly / readonly:update".
Type: BDEF Object name: ZFCALI_HOLIDAY_344 Message: The field "HOLIDAYID" is used for "parent" dependency (in the ON clause
Type: BDEF Object name: ZFCALI_HOLIDAY_344 Message: of the association "_Holiday"). This means it should be flagged as
Type: BDEF Object name: ZFCALI_HOLIDAY_344 Message: "readonly / readonly:update".
Messages from XCO framework (Service Binding)
Type: Object name: Message: To enable publish of local service endpoint, activate the Service Binding
Messages from business configuration registration
ZFCALI_Holiday_344 registered successfully.

We see that the following objects have been generated for our convenience:

 


 

5. Publish Business Configuration object


Do not forget to publish the Service Binding of the generated Business Configuration



6. Run Maintain Business Configuration App


When we run the Maintain Business Configuration App we see that our service is listed here :


When we click on the registration entry a Fiori Elements App is started on the fly that allows us to enter Business Configuration Data for our convenience.



Transport support


The SAP Cloud Platform ABAP Environment exposes an API that you can use for managing customizing requests and the content in customizing requests cl_a4c_bc_factory. The RAP Generator generates the appropriate coding in the behavior implementation classes for the root and the child entities.

Please note that an appropriate software component of type Business Configuration must be present in your system because otherwise the transport API will fail.

When having saved the data as shown above we can see a new entry in the Customizing Transport Organizer App.


Drilling down into the details we find the information about the two tables to which data has been written to.



 

When checking the code of the code of the local handler class of the behavior implementation class you will find code such as the following that has been generated by the RAP Generator that adds data to a transport request.

 
CLASS lcl_handler IMPLEMENTATION.
METHOD get_instance_features.
ENDMETHOD.
METHOD val_transport.
CHECK lines( keys ) > 0.
DATA table_keys TYPE TABLE OF zfcal_holi_344 .
table_keys = VALUE #( FOR key IN keys (
holiday_id = key-HolidayID
) ).
TRY.
cl_a4c_bc_factory=>get_handler( )->add_to_transport_request(
EXPORTING
iv_check_mode = abap_true
it_object_tables = VALUE #( ( objname = 'ZFCAL_HOLI_344'
tabkeys = REF #( table_keys ) ) )
iv_mandant_field_name = 'CLIENT'
IMPORTING
rt_messages = DATA(messages)
rv_success = DATA(success) ).
CATCH cx_a4c_bc_exception INTO DATA(exc).
success = abap_false.
ENDTRY.
IF success NE 'S'.
failed-Holiday = CORRESPONDING #( keys ).
DATA report LIKE LINE OF reported-Holiday.
report = CORRESPONDING #( keys[ 1 ] ).
IF exc IS BOUND.
report-%msg = new_message_with_text( text = exc->get_text( ) ).
INSERT report INTO TABLE reported-Holiday.
ENDIF.
LOOP AT messages ASSIGNING FIELD-SYMBOL(<msg>).
report-%msg = new_message(
id = <msg>-msgid
number = <msg>-msgno
severity = CONV #( <msg>-msgty )
v1 = <msg>-msgv1
v2 = <msg>-msgv2
v3 = <msg>-msgv3
v4 = <msg>-msgv4 ).
INSERT report INTO TABLE reported-Holiday.
ENDLOOP.
ENDIF.
ENDMETHOD.
ENDCLASS.

 

And we also see coding in the local saver class that calls the transport API cl_a4c_bc_factory.
CLASS lcl_saver IMPLEMENTATION.
METHOD save_modified.
DATA table_keys TYPE TABLE OF zfcal_holi_344.
DATA object_tables TYPE if_a4c_bc_handler=>tt_object_tables.
table_keys = VALUE #( FOR key IN create-Holiday (
holiday_id = key-HolidayID
) ).
LOOP AT update-holiday ASSIGNING FIELD-SYMBOL(<update>).
INSERT VALUE #(
holiday_id = <update>-HolidayID
) INTO TABLE table_keys.
ENDLOOP.
LOOP AT delete-Holiday ASSIGNING FIELD-SYMBOL(<delete>).
INSERT VALUE #(
holiday_id = <delete>-HolidayID
) INTO TABLE table_keys.
ENDLOOP.
IF table_keys IS NOT INITIAL.
INSERT VALUE #( objname = 'ZFCAL_HOLI_344'
tabkeys = REF #( table_keys ) ) INTO TABLE object_Tables.
ENDIF.
CHECK object_tables IS NOT INITIAL.
TRY.
cl_a4c_bc_factory=>get_handler( )->add_to_transport_request(
EXPORTING
iv_check_mode = abap_false
it_object_tables = object_tables
iv_mandant_field_name = 'CLIENT'
IMPORTING
rv_success = DATA(success) ).
CATCH cx_a4c_bc_exception.
success = abap_false.
ENDTRY.
ASSERT success = 'S'. "point of no return - previous validation must catch all exceptions
ENDMETHOD.
ENDCLASS.

In an upcoming release the code it is planned to provide a simplified API that allows to write the data that is stored in the tables of your Business Configuration App in just two lines of code. Once this API is available I will adapt the RAP Generator to use this new API.

Troubleshooting


No authorization


When you forget to publish the generated Business Configuration Object you will get the following error message when clicking on the entry

No authorization for configuration Holiday_344 maintenance.

 



No usable repository found


When you forget to create and clone a suitable software component of type Business Configuration you will get the following error when saving data with your Business Configuration app.



 

 

 
1 Comment