

ABAP Restful Application Programming Model with Legacy BAPI
source link: https://blogs.sap.com/2021/07/02/abap-restful-application-programming-model-with-legacy-bapi/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

ABAP Restful Application Programming Model with Legacy BAPI
Summary
The research I have done for three months has shown that there is not much content produced on this subject(RAP with BAPIs). Because of this reason I decided to prepare a BAPI-based development example using RAP model over a real scenario.
While preparing this article, I have benefited greatly from this repo of Julie Plummer, which is the best resource I could access about unmanaged rap scenario. Thanks Julie.
To summarize, the restful programming logic works with a focus on Core Data Services. This CDS-focused structure can be configured with standard functions (such as BAPIs) that we have used in the legacy logics(brownfield scenario).
I suggest you look at the references below to get a good understanding of how the new RAP model works . In addition check out this resource to understand Save Sequence Runtime in ABAP Restful Application Programming Model.
If you don’t know anything about the ABAP Restful Application Programming Model . This openSap course is good starting point.
What will you learn?
In this example I will create “Unmanaged Restful Application Programming Model Scenario” with Legacy Appropriation Requests BAPIs and structures.
You’ll learn
1- How to create custom cds entity and implement a query provider class include BAPI_APPREQUEST_GETDETAIL’
2- How to create behavior definition and implementation include BAPI_APPREQUEST_CREATE function.
3- How to create service definition and service binding.
Legacy Codes Summary
- GET Appropriation Request Data through Legacy BAPI : ‘BAPI_APPREQUEST_GETDETAIL’
- CREATE Appropriation Request through BAPI: ‘BAPI_APPREQUEST_CREATE’
RAP Codes Summary
Get Appropriation Requests
- Create a Custom CDS Entity: ZHVL_IC_APPROPREQ
- Implement a query provider class: ZCL_APPROP_VIA_RFC->interface>if_rap_query_provider
Create Appropriation Request
- Create Behavior Definition for ZHVL_IC_APPROPREQ Custom CDS Entity
- Create Control Structure Name: ZHVL_CS_APPROP
- In Behavior Definition->create mapping for ZHVL_IC_APPROPREQ using control structure ZHVL_CS_APPROP
- Create Behavior Implementation->unmanaged implementation in class ZBP_HVL_IC_APPROPREQ
Create ODATA Service
- Create Service Definition
- Create Service Binding
1- Create Custom CDS Entity
@EndUserText.label: 'Approp Request Custom Cds Entity'
@ObjectModel.query.implementedBy: 'ABAP:ZCL_APPROP_VIA_RFC'
@UI: {
headerInfo: {
typeName: 'Approp Request',
typeNamePlural: 'Approp Requests'
}
}
define root custom entity ZHVL_IC_APPROPREQ
{
@UI.facet : [
{
id : 'AppropRequest',
purpose : #STANDARD,
type : #IDENTIFICATION_REFERENCE,
label : 'Approp Request',
position: 10 }
]
@UI : {
lineItem : [{position: 10, importance: #HIGH}],
identification : [{position: 10}],
selectionField : [{position: 10}]
}
key externalnumber : abap.char( 24 );
//MASTER DATA
@UI : {
lineItem : [{position: 20, importance: #HIGH}],
identification : [{position: 20}],
selectionField : [{position: 20}]
}
REQ_TXT : ima_txt50;
@UI : {
lineItem : [{position: 30, importance: #HIGH}],
identification : [{position: 30}],
selectionField : [{position: 30}]
}
RSP_COST_CENTER : ima_vkostl;
@UI : {
lineItem : [{position: 40, importance: #HIGH}],
identification : [{position: 40}],
selectionField : [{position: 40}]
}
APPR_DATE : ima_gdatu;
@UI : {
lineItem : [{position: 50, importance: #HIGH}],
identification : [{position: 50}],
selectionField : [{position: 50}]
}
ORIG_APPR_YEAR : ima_gjahr;
@UI : {
lineItem : [{position: 60, importance: #HIGH}],
identification : [{position: 60}],
selectionField : [{position: 60}]
}
//Variant Data
DESCRIPTION : ima_txv50;
@UI : {
lineItem : [{position: 70, importance: #HIGH}],
identification : [{position: 70}],
selectionField : [{position: 70}]
}
COMPLETION_DATE : ima_fdatu;
START_UP_DATE : ima_idatu;
//PLAN TOTAL
OVERHEAD_COSTS : bapicurr_d;
// ORG_UNITS
REQ_COST_CENTER : ima_akostl;
PERCENTAGE : ima_aproz;
//PARTNER DATA
PARTNER_FUNCTION : abap.char( 2 );
PARTNER : i_parnr;
//PLAN_YEAR
FISCAL_YEAR : gjahr;
INV_PROG : im_prnam;
APPR_YEAR : im_gnjhr;
PROGRAM_POS : abap.char( 24 );
PERCENT_PROG_POS : im_prozu;
}
2- Implement a query provider class to get the data, using a BAPI (Business Application Programming Interface)

CLASS zcl_approp_via_rfc DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_rap_query_provider .
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_approp_via_rfc IMPLEMENTATION.
METHOD if_rap_query_provider~select.
TYPES: BEGIN OF ty_approp,
externalnumber TYPE ima_posid,
req_txt TYPE ima_txt50,
rsp_cost_center TYPE ima_vkostl,
appr_date TYPE ima_gdatu,
orig_appr_year TYPE ima_gjahr,
description TYPE ima_txv50,
completion_date TYPE ima_fdatu,
start_up_date TYPE ima_idatu,
overhead_costs TYPE bapicurr_d,
req_cost_center TYPE ima_akostl,
percentage TYPE ima_aproz,
partner_function TYPE parvw,
partner TYPE i_parnr,
fiscal_year TYPE gjahr,
inv_prog TYPE im_prnam,
appr_year TYPE im_gnjhr,
program_pos TYPE im_posid,
percent_prog_pos TYPE im_prozu,
END OF ty_approp.
DATA: ls_approp_req TYPE ty_approp.
DATA: lt_approp_req TYPE STANDARD TABLE OF ty_approp.
DATA: ls_master_data TYPE bapiappreqmaster,
ls_controlling TYPE bapi_appreq_id-cntrl_area,
lt_org TYPE TABLE OF bapiappreqorgunit,
lt_partner TYPE TABLE OF bapiappreqpartnerout,
lt_pos TYPE TABLE OF bapiappreqexpprogassgn,
lt_variant TYPE TABLE OF bapiappreqvarntmulti,
lt_plantot TYPE TABLE OF bapiappreqplantotalmulti,
lt_planyear TYPE TABLE OF bapiappreqplanyearmulti,
lt_return TYPE TABLE OF bapiret2.
"Set RFC destination
TRY.
"data(lo_rfc_dest) = cl_rfc_destination_provider=>proxy_type_onpremise(
"i_name = ''
").
"DATA(lv_rfc_dest_name) = lo_rfc_dest->get_destination_name( ).
"Check if data is requested
IF io_request->is_data_requested( ).
* DATA lv_maxrows TYPE int4.
* DATA(lv_skip) = io_request->get_paging( )->get_offset( ).
* DATA(lv_top) = io_request->get_paging( )->get_page_size( ).
* lv_maxrows = lv_skip + lv_top.
io_request->get_paging( )->get_offset( ).
io_request->get_paging( )->get_page_size( ).
"Call BAPI
CALL FUNCTION 'BAPI_APPREQUEST_GETDETAIL'
EXPORTING
externalnumber = '2.018E11-016288'
* language =
* language_iso =
IMPORTING
master_data = ls_master_data
* user_fields =
"controlling_area = ls_controlling
TABLES
org_units = lt_org
* division =
* material_group =
* invest_reason =
* environmnt_invest =
* assets_equis =
* order =
* wbs_element =
partner = lt_partner
assignment_to_pos = lt_pos
* assignment_to_budg_categ =
variant = lt_variant
* variant_to_version =
* assigned_apprequests =
plan_total = lt_plantot
plan_year = lt_planyear
* plan_total_obj =
* plan_year_obj =
return = lt_return.
ENDIF.
ls_approp_req-externalnumber = '2.018E11-016288'.
ls_approp_req-req_txt = ls_master_data-req_txt.
ls_approp_req-rsp_cost_center = ls_master_data-rsp_cost_center.
ls_approp_req-appr_date = ls_master_data-appr_date.
ls_approp_req-orig_appr_year = ls_master_data-orig_appr_year.
READ TABLE lt_org INTO DATA(ls_org) INDEX 1.
ls_approp_req-req_cost_center = ls_org-req_cost_center.
ls_approp_req-percentage = ls_org-percentage.
READ TABLE lt_partner INTO DATA(ls_partner) INDEX 1.
ls_approp_req-partner_function = ls_partner-partner_function.
ls_approp_req-partner = ls_partner-partner.
READ TABLE lt_pos INTO DATA(ls_pos) INDEX 1.
ls_approp_req-inv_prog = ls_pos-inv_prog.
ls_approp_req-appr_year = ls_pos-appr_year.
ls_approp_req-percent_prog_pos = ls_pos-percent_prog_pos.
ls_approp_req-program_pos = ls_pos-program_pos.
READ TABLE lt_variant INTO DATA(ls_variant) INDEX 1.
ls_approp_req-req_cost_center = ls_variant-description.
ls_approp_req-start_up_date = ls_variant-start_up_date.
READ TABLE lt_plantot INTO DATA(ls_plantot) INDEX 1.
ls_approp_req-overhead_costs = ls_plantot-overhead_costs.
READ TABLE lt_planyear INTO DATA(ls_planyear) INDEX 1.
ls_approp_req-fiscal_year = ls_planyear-fiscal_year.
APPEND ls_approp_req TO lt_approp_req.
CLEAR ls_approp_req.
"Set total no. of records
io_response->set_total_number_of_records( lines( lt_approp_req ) ).
"Output data
io_response->set_data( lt_approp_req ).
CATCH cx_rfc_dest_provider_error INTO DATA(lx_dest).
ENDTRY.
ENDMETHOD.
ENDCLASS.
3- Create Behavior Definition for ZHVL_IC_APPROPREQ

unmanaged implementation in class zbp_hvl_ic_appropreq unique;
define behavior for ZHVL_IC_APPROPREQ alias approp
//late numbering
//lock master
//etag master <field_name>
{
create;
update;
delete;
mapping for ZHVL_IC_APPROPREQ control zhvl_cs_approp
{
externalnumber = externalnumber;
req_txt = req_txt;
rsp_cost_center = rsp_cost_center;
appr_date = appr_date;
orig_appr_year = orig_appr_year;
description = description;
completion_date = completion_date;
start_up_date = start_up_date;
overhead_costs = overhead_costs;
req_cost_center = req_cost_center;
percentage = percentage;
partner_function = partner_function;
partner = partner;
fiscal_year = fiscal_year;
inv_prog = inv_prog;
appr_year = appr_year;
program_pos = program_pos;
percent_prog_pos = percent_prog_pos;
}
}
3.1- Create control structure: zhvl_cs_approp
@EndUserText.label : 'Control Structure For Approp Req'
@AbapCatalog.enhancementCategory : #NOT_EXTENSIBLE
define structure zhvl_cs_approp {
externalnumber : xsdboolean;
req_txt : xsdboolean;
rsp_cost_center : xsdboolean;
appr_date : xsdboolean;
orig_appr_year : xsdboolean;
description : xsdboolean;
completion_date : xsdboolean;
start_up_date : xsdboolean;
overhead_costs : xsdboolean;
req_cost_center : xsdboolean;
percentage : xsdboolean;
partner_function : xsdboolean;
partner : xsdboolean;
fiscal_year : xsdboolean;
inv_prog : xsdboolean;
appr_year : xsdboolean;
program_pos : xsdboolean;
percent_prog_pos : xsdboolean;
}
4- Create a custom RFC function module and call legacy BAPI in this function module.**IMPORTANT
Important Note:
RAP framework does not allow Commit/Rollback statements, as the framework itself internally takes care for committing/roll backing entities. If you try calling BAPI directly in behavior implementation class methods. You’ll get a dump.Because of this reason,We will call this RFC enabled function with destination none in behavior implementation class.(this may not be the best method. But I couldn’t find a better way,If anyone can find a better way, I would appreciate it if they write in the comments section.)
FUNCTION zhvl_approp_req
IMPORTING
VALUE(legacy_entity_in) TYPE zhvl_ic_appropreq
EXPORTING
VALUE(gv_ext) TYPE bapi_appreq_id-appreq
VALUE(gv_appr) TYPE bapi_appreq_id-appreqvrnt.
DATA messages TYPE bapiret2.
DATA : ls_masterdata TYPE bapiappreqmaster.
DATA: lt_org TYPE TABLE OF bapiappreqorgunit,
lt_partner TYPE TABLE OF bapiappreqpartner,
lt_pos TYPE TABLE OF bapiappreqexpprogassgn,
lt_variant TYPE TABLE OF bapiappreqvarntmulti,
lt_plantot TYPE TABLE OF bapiappreqplantotalmulti,
lt_planyear TYPE TABLE OF bapiappreqplanyear,
lt_return TYPE TABLE OF bapiret2.
DATA: ls_org TYPE bapiappreqorgunit,
ls_partner TYPE bapiappreqpartner,
ls_pos TYPE bapiappreqexpprogassgn,
ls_variant TYPE bapiappreqvarnt,
ls_plantot TYPE bapiappreqplantotal,
ls_planyear TYPE bapiappreqplanyear,
ls_return TYPE bapiret2.
ls_masterdata-req_txt = legacy_entity_in-req_txt.
ls_masterdata-rsp_cost_center = legacy_entity_in-rsp_cost_center.
ls_masterdata-appr_date = legacy_entity_in-appr_date.
ls_masterdata-orig_appr_year = legacy_entity_in-orig_appr_year.
ls_variant-description = legacy_entity_in-description.
ls_variant-completion_date = legacy_entity_in-completion_date.
ls_variant-start_up_date = legacy_entity_in-start_up_date.
ls_plantot-overhead_costs = legacy_entity_in-overhead_costs.
ls_org-req_cost_center = legacy_entity_in-req_cost_center.
ls_org-percentage = legacy_entity_in-percentage.
APPEND ls_org TO lt_org.
* ls_partner-partner_function = legacy_entity_in-partner_function.
* ls_partner-partner = legacy_entity_in-partner.
* APPEND ls_partner TO lt_partner.
ls_partner-partner_function = 'I1'.
ls_partner-partner = 'user1'.
APPEND ls_partner TO lt_partner.
ls_partner-partner_function = 'I2'.
ls_partner-partner = 'user1'.
APPEND ls_partner TO lt_partner.
ls_partner-partner_function = 'I3'.
ls_partner-partner = 'user2'.
APPEND ls_partner TO lt_partner.
ls_partner-partner_function = 'I4'.
ls_partner-partner = 'user2'.
APPEND ls_partner TO lt_partner.
ls_partner-partner_function = 'I5'.
ls_partner-partner = 'user2'.
APPEND ls_partner TO lt_partner.
ls_partner-partner_function = 'I6'.
ls_partner-partner = 'user3'.
APPEND ls_partner TO lt_partner.
ls_planyear-fiscal_year = legacy_entity_in-fiscal_year.
ls_planyear-overhead_costs = legacy_entity_in-overhead_costs.
APPEND ls_planyear TO lt_planyear.
ls_pos-inv_prog = legacy_entity_in-inv_prog.
ls_pos-appr_year = legacy_entity_in-appr_year.
ls_pos-program_pos = legacy_entity_in-program_pos.
ls_pos-percent_prog_pos = legacy_entity_in-percent_prog_pos.
APPEND ls_pos TO lt_pos.
CALL FUNCTION 'BAPI_APPREQUEST_CREATE'
EXPORTING
apprequest_type = '10'
appropriationrequest_in = legacy_entity_in-externalnumber
appropriationrequestvariant_in = ''
controlling_area = 'A000'
master_data = ls_masterdata
"user_fields = ls_user
variant = ls_variant
plan_total = ls_plantot
test_run = ''
IMPORTING
externalnumber = gv_ext
appropriationrequestvariantout = gv_appr
TABLES
org_units = lt_org
"division = lt_division
"material_grp = lt_matgroup
"investment_reason = lt_investrea
"environmnt_invest = lt_environve
"orders = lt_order
"wbs_element = lt_wbselement
"variant_to_version = lt_variant
partner = lt_partner
assignment_to_pos = lt_pos
plan_year = lt_planyear
return = lt_return.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'.
ENDFUNCTION.
5- Create Behavior Implementation: class ZBP_HVL_IC_APPROPREQ.
CLASS lhc_ZHVL_IC_APPROPREQ DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS create FOR MODIFY
IMPORTING entities FOR CREATE approp.
METHODS delete FOR MODIFY
IMPORTING keys FOR DELETE approp.
METHODS update FOR MODIFY
IMPORTING entities FOR UPDATE approp.
METHODS read FOR READ
IMPORTING keys FOR READ approp RESULT result.
ENDCLASS.
CLASS lhc_ZHVL_IC_APPROPREQ IMPLEMENTATION.
METHOD create.
DATA legacy_entity_in TYPE zhvl_ic_appropreq.
DATA: gv_ext TYPE bapi_appreq_id-appreq,
gv_appr TYPE bapi_appreq_id-appreqvrnt.
LOOP AT entities ASSIGNING FIELD-SYMBOL(<entity>).
legacy_entity_in = CORRESPONDING #( <entity> MAPPING FROM ENTITY USING CONTROL ).
CALL FUNCTION 'ZHVL_APPROP_REQ' DESTINATION 'NONE'
EXPORTING
legacy_entity_in = legacy_entity_in
IMPORTING
gv_ext = gv_ext
gv_appr = gv_appr.
ENDLOOP.
ENDMETHOD.
METHOD delete.
ENDMETHOD.
METHOD update.
ENDMETHOD.
METHOD read.
ENDMETHOD.
ENDCLASS.
CLASS lsc_ZHVL_IC_APPROPREQ DEFINITION INHERITING FROM cl_abap_behavior_saver.
PROTECTED SECTION.
METHODS check_before_save REDEFINITION.
METHODS finalize REDEFINITION.
METHODS save REDEFINITION.
ENDCLASS.
CLASS lsc_ZHVL_IC_APPROPREQ IMPLEMENTATION.
METHOD check_before_save.
ENDMETHOD.
METHOD finalize.
ENDMETHOD.
METHOD save.
ENDMETHOD.
ENDCLASS.
6- Create Service Definition

7- Create Service Binding and Publish ODATA Service

8- Preview your App
8 .1- GET Appropriation Request Data through Legacy BAPI : ‘BAPI_APPREQUEST_GETDETAIL’ using custom CDS entity.
8.2 CREATE Appropriation Request through BAPI: ‘BAPI_APPREQUEST_CREATE’ using behavior implementation class.
Important Note:
The codes in this example are purely for illustrative purposes. No performance testing has been done. No development has been made regarding the return parameters. May not be suitable for production system.
If you think there is a mistake in this method, please contribute in the comment section.
Please submit questions in the respective Q&A area in SAP Community.
References
1- OpenSap Course-Building Apps with Restful Application Programming Model
Recommend
-
5
Renzo Colle June 27, 2022 6 minute read ...
-
9
Abhishek Sharma October 6, 2022 3 minute read...
-
7
Frequently Asked Questions This document answers the most frequently asked questions around the ABAP RESTful Application Programming Model (RAP) which offers a standardized programming model to efficientl...
-
6
Abhishek Sharma November 9, 2022 3 minute read...
-
2
Intro Hello everyone ! In this blog I am going to talk about RAP model –RESTful ABAP Programming Model. As described by SAP :- The ABAP RESTful Application Programming Model (in short RAP) defines the archi...
-
12
Rajat verma January 4, 2023 3 minute read ...
-
9
Hello, In this beginner blog post we are going to see how we can use #CHANGE_SET (Change Set Processing) in ABAP Restful Application Programming Model. Use Case: Change Set processing can be...
-
5
Abhishek Sharma January 24, 2023 7 minute read...
-
12
Abhishek Sharma February 13, 2023 8 minute read...
-
7
Last edit: 2023-02 This blog is about recommendations for building modern applications and Web APIs with RAP on SAP Business Technology Platform (BTP) ABAP Environment – aka Steampunk – and SAP S/4HANA. A. W...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK