More and more organizations are coming across the term ABAP on Cloud. Whether they are considering Side-by-Side Extension with SAP Business Technology Platform or On-stack Extension in S4 HANA, I'm certain that this is discussed in your strategy meeting at least once.
ABAP on Cloud(aka ABAP for Cloud Development language version) is similar yet different from standard ABAP in many ways. Even if your organization holds in-house ABAP developers, the transition path to ABAP on Cloud may not be easy. This is due to the fact that certain APIs(table, function module, tcode, etc.) exist in your system built with standard ABAP language are not functional in ABAP on Cloud. On the front-end level, the major factor of not being able to use SAP GUI changes certain ABAP based solutions. In addition, there are changes in ABAP syntax as well.
This blogs is a one-stop shop for developers and IT strategist who like to make smooth transition from standard ABAP to ABAP for Cloud Development. It consists of three parts:
- Cheat sheet on LoB(Line of Business) level
- Cheat sheet on Solution & Syntax level
- Solution overview & hint based on ABAP for Cloud Development
You can choose to just refer to the cheat sheet, or you can deep dive into each solution at later half of this blog.
Disclaimer:
|
LoB(Line of Business)
Standard ABAP object/ based solution | Public local API to use instead in ABAP for Cloud Development |
Business Partner | |
Table: KNA1 KNB1 KNVK KNVP KNVV LFA1 LFB1 LFM1 | CDS view: i_customer i_customercompany i_contactperson i_custsalespartnerfunc i_customersalesarea i_supplier i_suppliercompany i_supplierpurchasingorg |
Delivery | |
Table: LIKP LIPS TVST | CDS view: i_deliverydocument i_deliverydocumentitem i_shippingpoint |
Finance | |
Table: BKPF BSEG ACDOCA SKA1 SKB1 T001 T003 CEPC Function Module: BAPI_ACC_EMPLOYEE_EXP_POST BAPI_ACC_INVOICE_RECEIPT_CHECK BAPI_ACC_INVOICE_RECEIPT_POST BAPI_ACC_DOCUMENT_CHECK BAPI_ACC_DOCUMENT_POST BAPI_ACC_ACT_POSTINGS_REVERSE | CDS view: i_journalentry i_operationalacctgdocitem i_journalentryitem i_glaccountlineitem i_glaccountlineitemrawdata i_glaccountinchartofaccounts i_glaccountincompanycode i_companycode i_profitcenter Behavior Definition: i_journalentrytp |
Finance(Hierarchy) | |
Table: SETHEADER SETHEADERT SETLEAF SETNODE | CDS view: i_costcenterhierarchy i_costcenterhierarchynode i_costctractivitytypehiernode i_functionalareahierarchy i_functionalareahiernode i_profitcenterhierarchy i_profitcenterhierarchynode |
Manufacturing | |
Table: MARA MARC MARD MARM AFKO AFPO AFRU AFVC AFVU AFVV MKAL PLKO PLPO Function Module: BAPI_MATERIAL_MAINTAINDATA_RT BAPI_MATERIAL_SAVEREPLICA BAPI_MATERIAL_SAVEDATA BAPI_PLANNEDORDER_GET_DETAIL BAPI_PRODORD_CHANGE BAPI_PRODORD_COMPLETE_TECH BAPI_PRODORD_CREATE BAPI_PRODORD_RELEASE BAPI_MATERIAL_STOCK_REQ_LIST | CDS view: i_product i_productqm i_productsales i_productprocurement i_productplantbasic i_productsupplyplanning i_productstoragelocationbasic i_productunitsofmeasure i_manufacturingorder i_manufacturingorderitem i_mfgorderconfirmation i_manufacturingorderoperation i_manufacturingorderoperation i_manufacturingorderoperation i_productionversion i_billofoperationsgroup i_mfgbillofoperationsoperation Behavior Definition: i_producttp_2 i_plannedordertp i_productionordertp i_productionordconfirmationtp i_plndindeprqmttp i_supplydemanditemtp |
Payment | |
Table: REGUH REGUP REGUV REGUT | CDS view: i_paymentprogramcontrol i_paymentproposalpayment i_paymentproposalitem i_paymentproposalcontrol |
Physical Inventory Management | |
Table: IKPF ISEG T001L T001W MSEG MKPF Function Module: MB_CREATE_GOODS_MOVEMENT MB_POST_GOODS_MOVEMENT BAPI_GOODSMVT_CANCEL BAPI_GOODSMVT_CREATE BAPI_MATPHYSINV_CHANGECOUNT BAPI_MATPHYSINV_COUNT BAPI_MATPHYSINV_CREATE | CDS view: i_physinvtrydocheader i_physinvtrydocitem i_storagelocation i_plant i_materialdocumentitem_2 i_materialdocumentheader_2 Behavior Definition: i_materialdocumenttp i_physicalinventorydocumenttp |
Sales | |
Table: VBAK VBAP VBEP VBFA VBKD VBRK VBRP TVGRT TVKBT TVKBZ TVKGR TVKO TVTA TVTW Function Module: BAPISDORDER_GETDETAILEDLIST BAPI_SALESORDER_CREATEFROMDAT2 | CDS view: i_salesdocument i_salesdocumentitem i_salesdocumentscheduleline i_sddocumentmultilevelprocflow i_salesdocument i_billingdocumentbasic i_billingdocumentitembasic i_salesgroup i_salesoffice i_salesareasalesoffice i_salesgroup i_salesorganization i_salesarea i_distributionchannel Behavior Definition: i_salesordertp |
Sales (Pricing) | |
Table: KONH KONM KONP KONV PRCD_ELEMENTS T685 T685A | CDS view: i_slsprcgconditionrecord i_slsprcgcndnrecordscale i_slsprcgconditionrecord i_slsprcgconditionrecord i_slsprcgconditionrecord i_conditiontype i_pricingconditiontype |
Sourcing and Procurement | |
Table: EKKO EKPO RBKP RSEG MATDOC EBAN EBKN EINA EINE MSKA MSKU MSLB MSLBH Function Module: BAPI_PO_CHANGE BAPI_PO_CREATE1 BAPI_PR_CHANGE BAPI_PR_CREATE BAPI_REQUISITION_CHANGE BAPI_REQUISITION_CREATE BAPI_REQUISITION_GETDETAIL BAPI_INCOMINGINVOICE_CREATE BAPI_INCOMINGINVOICE_POST BAPI_INCOMINGINVOICE_RELEASE | CDS view: i_purchaseorderapi01 i_purchaseorderitemapi01 i_supplierinvoiceapi01 i_suplrinvcitempurordrefapi01 i_materialdocumentheader_2 i_purchaserequisitionitemapi01 i_purreqnacctassgmtapi01 i_purchasinginforecordapi01 i_purchasinginforecordapi01 i_materialstock Behavior Definition: i_purchaseordertp_2 i_purchaserequisitiontp i_purchasecontracttp i_supplierinvoicetp |
Solution & Syntax
ge ABAP memory but former is much simpler to use. BUFFER transfers to cluster data the buffer data object which is in xstring format.
The main difference is that passing data using MEMORY ID is not supported anymore. Therefore only these 2 options are available.
"ABAP memory using buffer
DATA:buffer TYPE xstring,
lt_input_bf TYPE STANDARD TABLE OF I_UnitOfMeasure,
lt_output_bf TYPE STANDARD TABLE OF I_UnitOfMeasure.
SELECT * FROM I_UnitOfMeasure INTO TABLE @lt_input_bf.
EXPORT input = lt_input_bf TO DATA BUFFER buffer.
IMPORT input = lt_output_bf FROM DATA BUFFER buffer.
Access management
* Below example demonstrates how to restrict access inside IAM app. In addition, you may choose to implement Access Control on your CDS Data Definition.
Similar to in SAP on-premise access management, Authorization Object and Role are still relevant in ABAP for Cloud development. The big difference is that User Profiles is not used anymore and instead, IAM App and Business Catalog are used to map Authorization Object and Business Role. User Profile is where the fine-grained access control is setup, so that some users have display access to certain table objects, while some users don’t. This is in turn done by IAM App and Access Control Object in the ABAP for Cloud development.
The actual authorization check uses the same ABAP syntax, AUTHORITY-CHECK OBJECT. This checks the authorization object and activity value, which hasn't changed from standard ABAP.
In my below example, I created Authorization Field "ZTABLE", Authorization Object "ZAUTH_OBJ". In the IAM app, set the authorization object and restrict the table name and activity.
In the Behavior Definition , implement global authorization instance.
managed implementation in class ZCL_BLOB_TEST unique;
strict ( 1 );
with draft;
define own authorization context
{
'ZAUTH_OBJ';
}
define behavior for ZI_BLOB_TEST alias BLOB_TEST
persistent table zblob_test
draft table ziblob_test_d
etag master LocalLastChangedAt
lock master total etag LastChangedAt
authorization master ( global )
In the Behavior Handler class, implement the authorization check in method "get_global_authorizations". Set a debug on this logic so that we see what is going on.
IF requested_authorizations-%create EQ if_abap_behv=>mk-on.
* check create authorization
AUTHORITY-CHECK OBJECT 'ZAUTH_OBJ' ID 'ACTVT' FIELD '01'.
result-%create = COND #( WHEN sy-subrc = 0 THEN
if_abap_behv=>auth-allowed ELSE
if_abap_behv=>auth-unauthorized ).
ENDIF.
IF requested_authorizations-%update EQ if_abap_behv=>mk-on.
* check update authorization
AUTHORITY-CHECK OBJECT 'ZAUTH_OBJ' ID 'ACTVT' FIELD '02'.
result-%update = COND #( WHEN sy-subrc = 0 THEN
if_abap_behv=>auth-allowed ELSE
if_abap_behv=>auth-unauthorized ).
ENDIF.
Now go to the Fiori application generated from the Odata service and go to the item to edit the record. The debugger should start and you can see that the result of authorization check for update(sy-subrc = 0) is OK. This is because in IAM app, 02(change) is allowed.
Now let's create a new record. This time, the authority check fails because IAM app does not allow 01(create).
Calendar(Factory calendar)
This example shows part of the feature to handle factory calendar from released API cl_fhc_calendar_runtime.
"Add 2 days from a date considering factory calendar
DATA(lo_holidaycalendar) = cl_fhc_calendar_runtime=>create_factorycalendar_runtime( iv_factorycalendar_id
= 'SAP_CA' ). "Canada
lo_holidaycalendar->add_workingdays_to_date(
EXPORTING
iv_start = '20221230'
iv_number_of_workingdays = 2
RECEIVING
rv_end = DATA(lv_end) "Result is 20230103
).
Calendar(Public holidays)
This example shows part of the feature to handle holidaycalendar from released API cl_fhc_calendar_runtime.
DATA(lo_holidaycalendar) = cl_fhc_calendar_runtime=>create_holidaycalendar_runtime(
EXPORTING
iv_holidaycalendar_id = 'SAP_CA' ). "Canada
"Check if the data is a holiday in Canada
lo_holidaycalendar->is_holiday(
EXPORTING
iv_date = '20230101'
RECEIVING
rv_holiday = DATA(lv_result)
).
"Get holiday information for 20230101
DATA: lv_date TYPE lo_holidaycalendar->ty_fhc_date VALUE '20230101'.
DATA(lo_holidays) = lo_holidaycalendar->get_holiday(
EXPORTING
iv_date = lv_date
).
lo_holidays->get_text(
EXPORTING
iv_language = sy-langu
RECEIVING
rs_text = DATA(ls_text)
).
Change document logging
1. Create a table where you want to log the document change. Create data element for the field and check on Change Document Logging.
2. Create Change Document Object and set your Z table. Check how you want to log your Z table
Log Field values for insert - Create log entry record for each field value that's entered.
Log Initial values for insert - Create log entry record for each field value even if they are empty. This created high volumn of change doucment records. Use with caution.
Log Field values for deletion - When object is deleted, create log entry record for each field value that's entered.
Log Initial values for deletion - When object is deleted, create log entry record for each field value even if they are empty. This created high volumn of change doucment records. Use with caution.
3. Creating change document entry. Use the generated class to write change document logging. In the below example, it's logging update of table field
DATA:lt_xzcd_test TYPE zcl_zobj_cd_test_chdo=>tt_zcd_test,
lt_yzcd_test TYPE zcl_zobj_cd_test_chdo=>tt_zcd_test,
lv_username TYPE if_chdo_object_tools_rel=>ty_cdusername.
DATA(lv_sys_datum) = cl_abap_context_info=>get_system_date( ).
DATA(lv_sys_time) = cl_abap_context_info=>get_system_time( ).
DATA(lv_user) = cl_abap_context_info=>get_user_formatted_name( ).
lv_username = lv_user.
APPEND INITIAL LINE TO lt_xzcd_test ASSIGNING FIELD-SYMBOL(<lw_xzcd_test>).
<lw_xzcd_test>-employeeid = '0000000001'.
<lw_xzcd_test>-role = 'Developer'. "New value
APPEND INITIAL LINE TO lt_yzcd_test ASSIGNING FIELD-SYMBOL(<lw_yzcd_test>).
<lw_yzcd_test>-employeeid = '0000000001'.
<lw_yzcd_test>-role = 'Solution designer'. "Old value
zcl_zobj_cd_test_chdo=>write(
EXPORTING
objectid = 'ZOBJ_CD_TEST'
utime = lv_sys_time
udate = lv_sys_datum
username = lv_username
* planned_change_number =
object_change_indicator = 'U'
* planned_or_real_changes =
* no_change_pointers =
xzcd_test = lt_xzcd_test
yzcd_test = lt_yzcd_test
upd_zcd_test = 'U'
IMPORTING
changenumber = DATA(lv_changenumbner)
).
4. Reading the change document entry. In the generated class, add method implementation "if_chdo_enhancements~authority_check" and put below code inside. This method is for implementing your own autheority check, but in the below example, it is simply returning rv_is_authorized = 'X', meaning the authroity check is succesfull.
METHOD if_chdo_enhancements~authority_check.
"No Auth check performed. Allow all
rv_is_authorized = 'X'.
ENDMETHOD.
Now, use class method cl_chdo_read_tools=>changedocument_read to read the change log.
cl_chdo_read_tools=>changedocument_read(
EXPORTING
i_objectclass = 'ZOBJ_CD_TEST'
IMPORTING
et_cdredadd_tab = DATA(lt_cdredadd_tab)
).
Excel upload to itab
The upload data
Step1. Upload excel file by RAP Odata service described in "Large object handing(storing as MIME)". This way, the excel data is transformed to XSTRING.
Step2. Read the XSTRING to with xco_cp_xlsx. This class will read worksheet specified. Prepare an internal table that matches the file structure of excel. Use IF_XCO_XLSX_RA_WORKSHEET to select the range of the worksheet. Finally, use write_to method in if_xco_xlsx_ra_rs_operation_fc to write the values in internal table.
TYPES:
BEGIN OF ts_row,
Column1 TYPE string,
Column2 TYPE string,
END OF ts_row,
tt_row TYPE STANDARD TABLE OF ts_row WITH DEFAULT KEY.
DATA:lt_rows TYPE tt_row.
DATA(lo_xlsx) = xco_cp_xlsx=>document->for_file_content( iv_file_content = <Your file that is in XSTRING format> )->read_access( ).
DATA(lo_worksheet) = lo_xlsx->get_workbook( )->worksheet->for_name( iv_name = 'Sheet1' ).
DATA(lo_selection_pattern) = xco_cp_xlsx_selection=>pattern_builder->simple_from_to( )->get_pattern( ).
lo_worksheet->select( lo_selection_pattern
)->row_stream(
)->operation->write_to( REF #( lt_rows )
)->if_xco_xlsx_ra_operation~execute( ).
Exchange rate
The released API cl_exchange_rates performs currency conversion and exchange rate update, but it does not have method to read the list of exchange rate. To workaround this, we can use standard app "Upload Business Configuration" from Fiori Launchpad. Role "SAP_CA_BC_IC_LND_PC" is required to access this, or assign role template "SAP_BR_BPC_EXPERT".
This app is meant to maintain your custom Z customizing table but by default, SAP has generously allowed the maintenance of below standard currency tables.
Forms and printing
*The below setup is for Business Technology Platform. Connecting Forms Service by Adobe with ABAP Environment in S4 may require different setup.
Preparation
Forms Service by Adobe and Forms Service by Adobe API are required in Business Technology Platform. On the service instance of Forms Service by Adobe API, create a service key. Finally, create destination for Forms Service by Adobe instance.
Build Form template
Since there is no SAP Script or Smartforms, Adobe LiveCycle Designer must be used to create form layout. Follow note 2187332 to install it to your local PC.
Once the template is created, download in Adobe XML Form (*xdp), then upload this to Forms Template Store.
Rendering Forms
Rendering forms requies Forms Service by Adobe. Follow my blog below to set it up and consume from ABAP. https://blogs.sap.com/2022/12/14/get-started-with-forms-service-by-adobe-rest-api-in-btp/
Create client for Forms Service by Adobe template store.
mo_http_destination = cl_http_destination_provider=>create_by_cloud_destination(
i_service_instance_name = CONV #( iv_service_instance_name )
i_name = 'ADS_SRV'
i_authn_mode = if_a4c_cp_service=>service_specific
).
mv_client = cl_web_http_client_manager=>create_by_http_destination( mo_http_destination ).
Render PDF by calling Forms Service by Adobe API URI "/v1/adsRender/pdf". You can find the complete list of supported URI of this API here. https://adsrestapi-formsprocessing.cfapps.eu10.hana.ondemand.com/swagger
The rendering will return the PDF content result with base64 encoded string.
Viewing PDF
To view the content, we must first convert base64 encoded content to xstring. Then upload this xstring as mime object in your Ztable. This Z table can be created following "Excel upload to itab" part of this blog.
"Get the base64 encoded PDF content
DATA(lo_json) = /ui2/cl_json=>generate( json = lv_rendered_pdf ).
IF lo_json IS BOUND.
ASSIGN lo_json->* TO FIELD-SYMBOL(<data>).
ASSIGN COMPONENT `fileContent` OF STRUCTURE <data> TO FIELD-SYMBOL(<field>).
ASSIGN <field>->* TO FIELD-SYMBOL(<pdf_base64>).
ENDIF.
"Upload the xstring to z table, so the content can be viewed with RAP generated report
DATA: lt_input TYPE STANDARD TABLE OF zblob_test.
lt_input = VALUE #( ( docnum = '1000000001' filename = 'test.pdf' attachment = lv_pdf_xstring mimetype =
'application/pdf' )
).
INSERT zblob_test FROM TABLE @lt_input.
Go to the RAP service and the inserted record is disaplayed. Click on the attachment and the generated PDF from Form Service by Adobe will open.
Print Queue
Create a print queue by using cl_print_queue_utils. The below examples sends data from table zcd_test and send it to print queue.
DATA: lv_print_data TYPE xstring,
lv_err_msg TYPE STRING.
SELECT * FROM zcd_test INTO TABLE @DATA(lt_table).
CALL TRANSFORMATION id SOURCE root = lt_table RESULT XML DATA(lv_xstring).
lv_print_data = lv_xstring.
DATA(lv_qitem_id) = cl_print_queue_utils=>create_queue_item_by_data(
EXPORTING
iv_qname = 'TEST_QUEUE'
iv_print_data = lv_print_data
iv_name_of_main_doc = 'zcd_test'
IMPORTING
ev_err_msg = lv_err_msg
).
out->write( lv_qitem_id ).
The print queue can be viewed in Fiori app Maintain Print Queue.
If you want to integrate physical printer to ABAP Environment, follow this blog that guides you from setting up communication scnerio and installing Cloud Print Manager. https://blogs.sap.com/2017/08/07/cloud-print-manager-installation-and-configuration/
Job scheduling
Required roles: Application Jobs(SAP_CORE_BC_APJ_JCE), Application Job Templates(SAP_CORE_BC_APJ_TPL), Maintain Job Users(SAP_CORE_BC_APJ_USR_PC)
1. There are predefined job template to schedule your job from. If none of them meet your need, you must create your custom job template.
2. To create your custom template, first define your job entry by creating below class. This defines design time information on your job.
CLASS zcl_job_schedule_apj DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_apj_dt_exec_object.
INTERFACES if_apj_rt_exec_object.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_job_schedule_apj IMPLEMENTATION.
METHOD if_apj_dt_exec_object~get_parameters.
" Return the supported selection parameters here
et_parameter_def = VALUE #(
( selname = 'S_ID' kind = if_apj_dt_exec_object=>select_option datatype = 'C' length = 10 param_text
= 'ID' changeable_ind = abap_true )
( selname = 'P_DESCR' kind = if_apj_dt_exec_object=>parameter datatype = 'C' length = 80 param_text = 'Description' lowercase_ind = abap_true changeable_ind = abap_true )
( selname = 'P_SIMUL' kind = if_apj_dt_exec_object=>parameter datatype = 'C' length = 1 param_text =
'Simulate Only' checkbox_ind = abap_true changeable_ind = abap_true )
).
" Return the default parameters values here
et_parameter_val = VALUE #(
( selname = 'S_ID' kind = if_apj_dt_exec_object=>select_option sign = 'I' option = 'EQ' low = '1001'
)
( selname = 'P_DESCR' kind = if_apj_dt_exec_object=>parameter sign = 'I' option = 'EQ' low = 'Application Job Description' )
( selname = 'P_SIMUL' kind = if_apj_dt_exec_object=>parameter sign = 'I' option = 'EQ' low =
abap_true )
).
ENDMETHOD.
METHOD if_apj_rt_exec_object~execute.
"Execution logic when the job is started
TYPES ty_id TYPE c LENGTH 10.
DATA s_id TYPE RANGE OF ty_id.
DATA p_descr TYPE c LENGTH 80.
DATA p_count TYPE i.
DATA p_simul TYPE abap_boolean.
" Getting the actual parameter values(Just for show. Not needed for the logic below)
LOOP AT it_parameters INTO DATA(ls_parameter).
CASE ls_parameter-selname.
WHEN 'S_ID'.
APPEND VALUE #( sign = ls_parameter-sign
option = ls_parameter-option
low = ls_parameter-low
high = ls_parameter-high ) TO s_id.
WHEN 'P_DESCR'.
p_descr = ls_parameter-low.
WHEN 'P_SIMUL'.
p_simul = ls_parameter-low.
ENDCASE.
ENDLOOP.
"Implement core process you want to execute with this job
".......................
".......................
".......................
ENDMETHOD.
ENDCLASS.
3. Then create another class to create the job catalog and job template from the job you defined. Note that you need package and transport request.
CLASS zcl_job_template_apj DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_job_template_apj IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DATA(lo_apj_create) = cl_apj_dt_create_content=>get_instance( ).
" Create job catalog
lo_apj_create->create_job_cat_entry(
iv_catalog_name = 'Z_TESTJOB_CATALOG'
iv_class_name = 'zcl_job_schedule_apj'
iv_text = 'Job catalog text'
iv_catalog_entry_type = cl_apj_dt_create_content=>class_based
iv_transport_request = 'H01K900008'
iv_package = 'ZSANDBOX'
).
out->write( |Job catalog entry created successfully| ).
" Create job template
DATA lt_parameters TYPE if_apj_dt_exec_object=>tt_templ_val.
NEW zcl_job_schedule_apj( )->if_apj_dt_exec_object~get_parameters(
IMPORTING
et_parameter_val = lt_parameters
).
lo_apj_create->create_job_template_entry(
iv_template_name = 'Z_TESTJOB_TEMPLATE'
iv_catalog_name = 'Z_TESTJOB_CATALOG'
iv_text = 'Job template text'
it_parameters = lt_parameters
iv_transport_request = 'H01K900008'
iv_package = 'ZSANDBOX'
).
out->write( |Job template created successfully| ).
ENDMETHOD.
ENDCLASS.
4. After successful execution, go to Fiori app maintain Application Job Template and the new job template is created.
5. Use Fiori app Application jobs to create a job with the job template.
6. The method if_apj_rt_exec_object~execute in class zcl_job_schedule_apjs is executed. Whatever business logic you implemented there will be processed.
7. If you want to start, change, delete jobs programmatically, use class cl_apj_rt_api.
Large object handling
The completely guide to storing large object in database table can be found in Streams in RAP : Uploading PDF , Excel and Other Files in RAP Application | SAP Blogs
Parallel processing
Here is example use case to trigger parallel processing.
Parallel process 1
CLASS zcl_paralell1 DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
TYPES ty_t_time TYPE STANDARD TABLE OF cl_abap_context_info=>ty_system_time WITH DEFAULT KEY.
INTERFACES if_abap_parallel.
METHODS get_time RETURNING VALUE(rt_time) TYPE ty_t_time.
METHODS get_wp_number RETURNING VALUE(rv_wp_number) TYPE char3.
PROTECTED SECTION.
PRIVATE SECTION.
DATA gt_time_1 TYPE TABLE OF cl_abap_context_info=>ty_system_time.
DATA gv_wp_number TYPE char3.
ENDCLASS.
CLASS zcl_paralell1 IMPLEMENTATION.
METHOD if_abap_parallel~do.
DO 3 TIMES.
WAIT UP TO 2 SECONDS.
DATA(lv_system_time) = cl_abap_context_info=>get_system_time( ).
APPEND lv_system_time TO gt_time_1.
ENDDO.
gv_wp_number = '001'.
ENDMETHOD.
METHOD get_time.
rt_time = gt_time_1.
ENDMETHOD.
METHOD get_wp_number.
rv_wp_number = gv_wp_number.
ENDMETHOD.
ENDCLASS.
Parallel process 2
CLASS zcl_paralell2 DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
TYPES ty_t_time TYPE STANDARD TABLE OF cl_abap_context_info=>ty_system_time WITH DEFAULT KEY.
INTERFACES if_abap_parallel.
METHODS get_time RETURNING VALUE(rt_time) TYPE ty_t_time.
METHODS get_wp_number RETURNING VALUE(rv_wp_number) TYPE char3.
PROTECTED SECTION.
PRIVATE SECTION.
DATA gt_time_2 TYPE TABLE OF cl_abap_context_info=>ty_system_time.
DATA gv_wp_number TYPE char3.
ENDCLASS.
CLASS zcl_paralell2 IMPLEMENTATION.
METHOD if_abap_parallel~do.
DO 3 TIMES.
WAIT UP TO 2 SECONDS.
DATA(lv_system_time) = cl_abap_context_info=>get_system_time( ).
APPEND lv_system_time TO gt_time_2.
ENDDO.
gv_wp_number = '002'.
ENDMETHOD.
METHOD get_time.
rt_time = gt_time_2.
ENDMETHOD.
METHOD get_wp_number.
rv_wp_number = gv_wp_number.
ENDMETHOD.
ENDCLASS.
Trigger parallel processing
DATA(lo_parallel) = NEW cl_abap_parallel( ).
DATA(lo_instance_1) = NEW zcl_paralell1( ).
DATA(lo_instance_2) = NEW zcl_paralell2( ).
lo_parallel->run_inst(
EXPORTING
p_in_tab = VALUE #( ( lo_instance_1 ) ( lo_instance_2 ) )
IMPORTING
p_out_tab = DATA(lt_out_tab)
).
LOOP AT lt_out_tab ASSIGNING FIELD-SYMBOL(<ls_out_tab>).
IF <ls_out_tab>-inst IS INSTANCE OF zcl_paralell1.
lo_instance_1 = CAST #( <ls_out_tab>-inst ).
out->write( 'System time for instance 1:' ).
LOOP AT lo_instance_1->get_time( ) ASSIGNING FIELD-SYMBOL(<lv_instance_1>).
out->write( <lv_instance_1> ).
ENDLOOP.
out->write( |WP number: { lo_instance_1->get_wp_number( ) }| ).
ENDIF.
IF <ls_out_tab>-inst IS INSTANCE OF zcl_paralell2.
lo_instance_2 = CAST #( <ls_out_tab>-inst ).
out->write( 'System time for instance 2:' ).
LOOP AT lo_instance_2->get_time( ) ASSIGNING FIELD-SYMBOL(<lv_instance_2>).
out->write( <lv_instance_2> ).
ENDLOOP.
out->write( |WP number: { lo_instance_2->get_wp_number( ) }| ).
ENDIF.
ENDLOOP.
Translation
Since there is no GUI, the GUI based translation maintenance is no longer available. For this purpose, Maintain Translations app is used.
List of all objects that are translatable.
- Application Log Object
- Business Configuration Object
- CDS Type Definition
- Data Definition
- Data Element
- Domain
- IAM Business Catalog
- Message Class
- Metadata Extension
Define the source language and target language. Demonstrate translation for metadata extension for RAP based application.
XLF file is downloaded and this is the file that defines the translation. Add target translation of Japanese. Upload the same file back in the Maintain Translation app and don't forget to publish the translation.
Start the application in Japanese and English. The field names are translated based on the uploaded XLF file.
UI
ABAP Development Tool output console
Since there is no SAP GUI, write statement or ALV output is not possible. The easiest way in ABAP for Cloud Development is to use output console in ADT. Wrap IF_OO_ADT_CLASSRUN into your class and use it's Write method to output data.
This output is only suited for simple string output. It is not meant only for developer, and not for generating report for business application user.
CLASS ztest_class DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES: if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS ztest_class IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
out->write( 'Hello world!' ).
ENDMETHOD.
ENDCLASS.
Fiori app generate by ABAP UI service
This is the primary approach to generate UI for report applications. It is part of ABAP RAP framework and no front end development is needed to generate Fiori application. It is completely different framework from SAP GUI. Instead of creating dynpro and controlling logic in PBO, PAI, ABAP RAP uses CDS view as base and expose Odata service. Fiori launchpad consumes UI service part of Odata and generates a Fiori list report based on the data from CDS view and metadata definition of it.
Supported feature:
- List page, object page to display data
- Search, filter, variant
- CRUD operation for backend database
- Visualization(graph, chart)
- Screen logic(Validation, conversion, user event)
- Draft & Copy capabilitties
- Inline edit
- Locking mechanism
Limitation:
- All limitation with Fiori Element apply(No flexibility in UI, limitation in screen control, etc.)
- Must be deployed outside of ABAP Environment, using WebEDI such as Business Application Studio or Visual Studio.
ABAP RAP reference - SAP help
Fiori app generate by ABAP2UI5(open source)
This is open source project that allows developer to create Fiori UI5 application with pure ABAP. It is the closest approach to built free-style UI5 application in ABAP Environment. https://github.com/abap2UI5/abap2UI5
Highlights:
- Avaialble for ABAP releases (from NW 7.02 to ABAP 2305)
- Avaialble for both ABAP for Cloud and Standard ABAP language version
- Supports Selection Screens, Tables, Lists, Popups, F4-Helps, MIME Editor, File Upload/download, Chart/Graph, Side Effects, etc..
- Supports all Fiori Elements floorplan
If you want to create more flexible UI with ABAP, consider using ABAP2UI5 instead of ABAP RAP(below is a sample UI I created with ABAP2UI5).