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: 
I323214
Advisor
Advisor
107,645
Hello Guys,

In this blog we will learn new programming model RAP in detail with an example, I would recommend to go through the theory as well before you start coding to understand RAP basics.I would like to thank my colleagues in SAP specially Kailash Satapathy and Gaurav Kumar for helping me in writing this blog.

Prerequisite: 

Concepts of Core Data Services(CDS) and annotations.

Lets Start 🙂

 RESTful ABAP Programming Model (RAP): The term RESTful ABAP Programming Model (RAP) is chosen to reflect its orientation towards a “stateless” REST architecture.

We will start with ABAP evolution over the years: -

Evolution of the ABAP Programming Model

We kick started our ABAP WORLD with classical ABAP programming using reports and module pool programs, then we moved to BSP/Webdynpro with FPM (for UI harmonization), then slowly shifted from ERP style developments to S/4 HANA model developments where our major programming consists of artifacts like CDS, BOPF, GW and Fiori.



ABAP Programming model for SAP Fiori (Current best practice) : -

This development model usually consists of CDS view, BOPF and GW where CDS is tightly coupled with BOPF and GW (using RDS Mapping or using @OData.Publish annotation).



Note: Issue with this model is flow is not well defined

Future Direction - New Programming Model (ABAP Restful Programming Model)



RESTful ABAP Programming model in detail: -

The ABAP RESTful programming model defines the architecture for efficient end-to-end development of intrinsically SAP HANA-optimized OData services (such as Fiori apps) in SAP Cloud Platform ABAP Environment. It supports the development of all types of Fiori applications as well as A2X services. It is based on technologies and frameworks such as Core Data Services (CDS) for defining semantically rich data models and a service model infrastructure for creating OData services with bindings to an OData protocol and ABAP-based application services for custom logic and SAPUI5-based user interfaces – as shown in the figure below



Understanding Concepts

  1. Business Object


business object (BO) is a common term to represent a real-world artifact in enterprise application development such as the Product, the Travel, or the SalesOrder. In general, a business object contains several nodes such as Items and and common transactional operations such as for creating, updating and deleting data and additional application-specific operations, such as Approve in a SalesOrder business object.

From a formal point of view, a business object is characterized by

  • a structure,

  • a behavior and

  • the corresponding runtime implementation.


See the figure for more details.



 

1.1 Structure of a Business Object

From structural aspect, a business object consists of a tree of nodes (SalesOrderItemsScheduleLines) where the nodes are linked by means of a special kind of associations, the compositions. A composition is specialized association that defines a whole-part relationship. A composite part only exists together with its parent entity (whole).

Each node of this composition tree is an element that is modelled with a CDS entity. The root entity is of particular importance: This is considered in the source code of the CDS data definition with the keyword ROOT. The root entity serves as a representation of the business object and defines the top node in a business object's structure.



1.2 Behavior of a Business Object

Each entity of the business object can offer the standard CUD operations create(), update() and delete(). In addition, each entity can also offer specific operations with a dedicated input and output structure which are called actions. The offered CUD operations, actions as well some behavior-relevant properties, such as lock dependencies between the parent and child entities are defined in the behavior definition artifact.

A behavior definition always refers to a CDS data model. As shown in the figure below, a behavior definition relies directly on the CDS root entity. One behavior definition refers exactly to one root entity and one CDS root entity has at most one behavior definition (a 0..1 relationship), which also handles all included child entities.



1.3 Business Object’s Runtime Implementation

The business object runtime mainly consists of two parts: The first part is the interaction phase where a consumer calls the business object operations to change data and read instances with or without the transactional changes. The business object runtime keeps the changes in its internal transactional buffer which represents the state of the instance data. This transactional buffer is always required for a business object. After all changes were performed, the data can be persisted. This is realized with the save sequence.



Business object runtime in detail

Interaction phase have different steps which we segregated as Modify, Read and Lock. Save sequence phase will have steps like Finalise, check_before_save, adjust_numbers and save.



Implementations can be classified as Unmanaged, Managed and Managed with save.

Currently supported implementation is Unmanaged. Managed and Managed with save implementations will come in future releases.



  1. Business Service


The ABAP development platform can act in the roles of service provider and service consumer, such as SAP Fiori UI client.

In the context of the ABAP RESTful programming model, a business service is RESTful service which can be called by a consumer. It is defined by exposing data models and behavior models. It consists of a Service definition and a Service binding which are illustrated in the figure below: -



 

The Service Definition is a projection of the data model and the related behavior to be exposed, whereas the Service Binding implements a specific protocol and the kind of service to be offered for a consumer. This separation allows the data models and service definitions to be integrated into various protocols without any re-implementation.

2.1 Service Definition

 A service definition represents the service model that is generically derived from the underlying CDS-based data model.

Example :-

DEFINE SERVICE service_definition_name

{

EXPOSE cds_entity_1 [AS alias_1];

EXPOSE cds_entity_2 [AS alias_2];

EXPOSE ...

EXPOSE cds_entity_m [AS alias_m];

}

2.2 Service Binding

 The business service binding (short form: service binding) is an ABAP Repository object used to bind a service definition to a client-server communication protocol such as OData.

Relationship between the Data Model, the Service Definition and Service Binding



Let's learn RAP with a CRUD Example.

Here we will go with the Sales Order CRUD Example.

 For testing purpose, I have created Sales Order Header table – ZSSK_VBAK and Sales Order Item  table   – ZSSK_VBAP

ZSSK_VBAK





 

ZSSK_VBAP





We have 3 steps to implement here.

  1. Provide the CDS Data Model with Business Object Structure

  2. Defining and Implementing Behavior of the Business Object.

  3. Defining Business Service for Fiori UI.


 

  1. Provide the CDS Data Model with Business Object Structure


 

 Here we will create CDS view for Business object using Composition and associations to sub nodes.

 Code snippet for Sales Order Header CDS view: -

@AbapCatalog.sqlViewName: 'ZSSKSOHDR'

@AbapCatalog.compiler.compareFilter: true

@AbapCatalog.preserveKey: true

@AccessControl.authorizationCheck: #NOT_REQUIRED

@EndUserText.label: 'Sales Order Header'

@UI: {

headerInfo: {

typeName: 'Sales Order',

typeNamePlural: 'Sales Orders',

title: { type: #STANDARD, value: 'vbeln' }

}

}

@ObjectModel.semanticKey: ['vbeln']

@ObjectModel.representativeKey: 'vbeln'

define root view Zssk_SoHeader as select from zssk_vbak as SOHeader

composition [0..*] of Zssk_SoItem as _SOItem

{

@UI.facet: [

{

id: 'GeneralData',

type: #COLLECTION,

position: 10,

label: 'Sales Order Header'

},

{

type: #FIELDGROUP_REFERENCE,

position: 10,

targetQualifier: 'GeneralData1',

parentId: 'GeneralData',

isSummary: true,

isPartOfPreview: true

},

{

type: #FIELDGROUP_REFERENCE,

position: 20,

targetQualifier: 'GeneralData2',

parentId: 'GeneralData',

isSummary: true,

isPartOfPreview: true

},

{

id: 'SOItem',

purpose: #STANDARD,

type: #LINEITEM_REFERENCE,

label: 'Sales Order Item',

position: 10,

targetElement: '_SOItem'

}

]

@UI: {

lineItem: [ { position: 10, importance: #HIGH } ],

selectionField: [{position: 10 }],

fieldGroup: [{qualifier: 'GeneralData1',position: 10,importance: #HIGH }]

}

key   SOHeader.vbeln,

@UI: {

lineItem: [ { position: 20, importance: #HIGH } ],

selectionField: [{position: 20 }],

fieldGroup: [{qualifier: 'GeneralData2',position: 10,importance: #HIGH }]

}

SOHeader.erdat,

@UI: {

lineItem: [ { position: 30, importance: #HIGH } ],

fieldGroup: [{qualifier: 'GeneralData2',position: 20,importance: #HIGH }]

}

SOHeader.ernam,

@UI: {

lineItem: [ { position: 40, importance: #HIGH } ],

fieldGroup: [{qualifier: 'GeneralData1',position: 20,importance: #HIGH }]

}

SOHeader.vkorg,

@UI: {

lineItem: [ { position: 50, importance: #HIGH } ],

fieldGroup: [{qualifier: 'GeneralData1',position: 30,importance: #HIGH }]

}

SOHeader.vtweg,

@UI: {

lineItem: [ { position: 60, importance: #HIGH } ],

fieldGroup: [{qualifier: 'GeneralData1',position: 40,importance: #HIGH }]

}

SOHeader.spart,

//For action Set Favourite in UI

@UI.lineItem: [{ type: #FOR_ACTION,dataAction: 'set_favourite',label: 'Set Favourite' },

{position: 15, importance: #HIGH}]

@EndUserText.label: 'Favourite'

SOHeader.favourite,

SOHeader.lastchangedby,

SOHeader.lastchangedat,

/*Association*/

_SOItem

}

 

Code Snipper for Sales Order Item CDS view :-

@AbapCatalog.sqlViewName: 'ZSSKSOITM'

@AbapCatalog.compiler.compareFilter: true

@AbapCatalog.preserveKey: true

@AccessControl.authorizationCheck: #CHECK

@EndUserText.label: 'Sales Order Item'

@ObjectModel.representativeKey: ['vbeln','posnr']

define view Zssk_SoItem as select from zssk_vbap as SOItem

association to parent Zssk_SoHeader as _SOHeader on(

$projection.vbeln = _SOHeader.vbeln

)

{

@UI.facet: [

{type: #COLLECTION, position: 10, id: 'SoItem', label: 'Sales Order Item'},

{type: #FIELDGROUP_REFERENCE, position: 10, targetQualifier: 'SoItem1',parentId: 'SoItem', isSummary: true, isPartOfPreview: true},

{type: #FIELDGROUP_REFERENCE, position: 20, targetQualifier: 'SoItem2',parentId: 'SoItem', isSummary: true, isPartOfPreview: true}

]

@UI: {

lineItem: [ { position: 10, importance: #HIGH } ],

fieldGroup: [{qualifier: 'SoItem1',position: 10,importance: #HIGH }]

}

key  SOItem.vbeln,

@UI: {

lineItem: [ { position: 20, importance: #HIGH } ],

fieldGroup: [{qualifier: 'SoItem1',position: 20,importance: #HIGH }]

}

key  SOItem.posnr,

@UI: {

lineItem: [ { position: 30, importance: #HIGH } ],

fieldGroup: [{qualifier: 'SoItem2',position: 10,importance: #HIGH }]

}

SOItem.matnr,

@UI: {

lineItem: [ { position: 40, importance: #HIGH } ],

fieldGroup: [{qualifier: 'SoItem2',position: 20,importance: #HIGH }]

}

SOItem.zmeng,

SOItem.meins,

/*Association*/

_SOHeader

}

 

  1. Defining and Implementing Behavior of the Business Object


Here we will create Behavior definition and implementation for BO.



Right click on CDS view Zssk_SoHeader and create New Behavior definition

Code Snippet for Behavior Definition: -

implementation unmanaged;

define behavior for Zssk_SoHeader alias SOHeader

{

create;

update;

delete;

action set_favourite result [1] $self;

association  _SOItem { create; }

}

define behavior for Zssk_SoItem alias  SOItem

{

create;

update;

delete;

}

We can implement e-tag and locking also in behavior definition: -

 

After this step, we will create Behavior Implementation, right click Behavior definition and opt New Behavior Implementation.

 

Note: The moment you create a new Behavior implementation, local classes will get generated with Behavior class definition for Interaction Phase and Save Sequence Phase (Please refer topic Business object runtime in detail)



 

We will write our logic in respective class, to make it simple I am putting code only in Modify Method in lcl_handler class.

Note : Ideally scenario will be like entries from the UI will be putting into the transaction buffer by Interaction phase( modify(), read() and lock() methods) with a proper locking mechanism and Save Sequence phase( finalize(),check_before_save(),adjust_numbers() and save() methods) will take care of database commit and rollback part with proper validation.

 

Code Snippet for Modify method to update Sales Order Header and Item tables.

Here I am using INSERT,UPDATE and DELETE statements for CRUD operations to make it simple, but in ideal scenarios we will be using BAPI/APIs for CRUD operations.

CLASS lcl_handler DEFINITION INHERITING FROM cl_abap_behavior_handler.

PRIVATE SECTION.

DATA : lt_soheader TYPE TABLE  OF Zssk_vbak,

lt_soitem     TYPE TABLE OF Zssk_vbap,

ls_vbap       TYPE Zssk_vbap,

lt_fields       TYPE TABLE OF dfies.

 

METHODS modify FOR BEHAVIOR IMPORTING

" For Header table

it_set_fav FOR ACTION soheader~set_favourite RESULT et_soheader

it_soheader_create    FOR CREATE soheader

it_soheader_update   FOR UPDATE soheader

it_soheader_delete    FOR DELETE soheader

" For Item table

it_soheader_soitem_create     FOR CREATE soheader\_soitem

it_soitem_create    FOR CREATE soitem

it_soitem_update    FOR UPDATE soitem

it_soitem_delete    FOR DELETE soitem.

ENDCLASS.

CLASS lcl_handler IMPLEMENTATION.

METHOD modify.

/**************************Action Set Favourite************************/

IF it_set_fav IS NOT INITIAL.

DATA(ls_fav_so) = it_set_fav[ 1 ].

UPDATE zssk_vbak SET favourite = 'X' WHERE vbeln = ls_fav_so-vbeln.

IF sy-subrc EQ 0.

SELECT * FROM zssk_vbak INTO CORRESPONDING FIELDS OF TABLE et_soheader WHERE vbeln = ls_fav_so-vbeln.

ENDIF.

ENDIF.

/***************************************************************************/

/* CRUD Operations  for Header table */

/***************************Create****************************************/

IF it_soheader_create IS NOT INITIAL.

MOVE-CORRESPONDING   it_soheader_create TO lt_soheader.

INSERT  zssk_vbak FROM TABLE lt_soheader.

ENDIF.

/*************************************************************************/

/***************************Update*************************************/

IF it_soheader_update IS NOT INITIAL.

CALL FUNCTION 'DDIF_FIELDINFO_GET'

EXPORTING

tabname        = 'ZSSK_VBAK'

TABLES

dfies_tab      = lt_fields

EXCEPTIONS

not_found      = 1

internal_error = 2

OTHERS         = 3.

IF sy-subrc <> 0.

ENDIF.

DATA(ls_hdr) = it_soheader_update[ 1 ].

SELECT SINGLE *

FROM zssk_vbak

INTO @DATA(ls_vbak)

WHERE vbeln = @LieneS_hdr-vbeln.

LOOP AT lt_fields ASSIGNING FIELD-SYMBOL(<fs_field>).

ASSIGN COMPONENT <fs_field>-fieldname OF STRUCTURE ls_hdr TO FIELD-SYMBOL(<fs_target>).

IF <fs_target> IS ASSIGNED AND <fs_target> IS NOT INITIAL.

ASSIGN COMPONENT <fs_field>-fieldname OF STRUCTURE ls_vbak TO FIELD-SYMBOL(<fs_source>).

<fs_source> = <fs_target>.

ENDIF.

ENDLOOP.

APPEND ls_vbak TO lt_soheader.

UPDATE  zssk_vbak  FROM TABLE lt_soheader.

ENDIF.

/*************************************************************************/

/****************************Delete*************************************/

IF it_soheader_delete IS NOT INITIAL.

MOVE-CORRESPONDING   it_soheader_delete TO lt_soheader.

DELETE  zssk_vbak FROM TABLE lt_soheader.

IF sy-subrc EQ 0.

DATA(lv_vbeln) = lt_soheader[ 1 ]-vbeln.

IF  lv_vbeln IS NOT INITIAL.

DELETE FROM zssk_vbap WHERE vbeln EQ lv_vbeln.

ENDIF.

ENDIF.

ENDIF.

/*************************************************************************/

/* CRUD Operations  for Item table */

/***************************Create****************************************/

IF  it_soheader_soitem_create IS NOT INITIAL.

READ TABLE it_soheader_soitem_create INTO DATA(ls_item) INDEX 1.

IF sy-subrc EQ 0.

MOVE-CORRESPONDING ls_item-%target TO lt_soitem.

ENDIF.

IF lt_soitem IS NOT INITIAL.

INSERT  zssk_vbap FROM TABLE lt_soitem.

ENDIF.

ENDIF.

IF it_soitem_create IS NOT INITIAL.

MOVE-CORRESPONDING   it_soitem_create TO lt_soitem.

INSERT  zssk_vbap FROM TABLE lt_soitem.

ENDIF.

/*************************************************************************/

/***************************Update*************************************/

IF it_soitem_update IS NOT INITIAL.

CALL FUNCTION 'DDIF_FIELDINFO_GET'

EXPORTING

tabname        = 'ZSSK_VBAP'

TABLES

dfies_tab      = lt_fields

EXCEPTIONS

not_found      = 1

internal_error = 2

OTHERS         = 3.

IF sy-subrc <> 0.

ENDIF.

DATA(ls_itm) = it_soitem_update[ 1 ].

SELECT  *

FROM zssk_vbap

INTO TABLE @DATA(lt_vbap)

WHERE vbeln = @LieneS_itm-vbeln.

CLEAR ls_itm.

LOOP AT  it_soitem_update INTO ls_itm.

READ TABLE lt_vbap INTO DATA(ls_vbap) WITH KEY vbeln = ls_itm-vbeln posnr = ls_itm-posnr.

IF sy-subrc EQ 0.

LOOP AT lt_fields ASSIGNING FIELD-SYMBOL(<fs_itm_field>).

ASSIGN COMPONENT <fs_itm_field>-fieldname OF STRUCTURE ls_itm TO FIELD-SYMBOL(<fs_itm_target>).

IF <fs_itm_target> IS ASSIGNED AND <fs_itm_target> IS NOT INITIAL.

ASSIGN COMPONENT <fs_itm_field>-fieldname OF STRUCTURE ls_vbap TO  FIELD-SYMBOL(<fs_itm_source>).

<fs_itm_source> = <fs_itm_target>.

ENDIF.

ENDLOOP.

ENDIF.

APPEND ls_vbap TO lt_soitem.

CLEAR: ls_vbap,

ls_itm.

ENDLOOP.

UPDATE  zssk_vbap  FROM TABLE lt_soitem.

ENDIF.

/*************************************************************************/

/****************************Delete*************************************/

IF it_soitem_delete IS NOT INITIAL.

MOVE-CORRESPONDING   it_soitem_delete TO lt_soitem.

DELETE  zssk_vbap FROM TABLE lt_soitem.

ENDIF.

/*************************************************************************/

ENDMETHOD.

ENDCLASS.

CLASS lcl_saver DEFINITION INHERITING FROM cl_abap_behavior_saver.

PROTECTED SECTION.

METHODS finalize          REDEFINITION.

METHODS check_before_save REDEFINITION.

METHODS save              REDEFINITION.

ENDCLASS.

 

CLASS lcl_saver IMPLEMENTATION.

METHOD finalize.

ENDMETHOD.

METHOD check_before_save.

ENDMETHOD.

METHOD save.

ENDMETHOD.

ENDCLASS.

 

  1. Defining Business Service for Fiori UI


Here we will create Service definition and Service Binding.



 

 Service Definition.

The service definition is a projection of the data model and the related behavior to be exposed.

Right click your Package->New->other ABAP Repository Object->Business Service->Service Definition



Code Snippet for Service Definition: -



 

 Service Binding

The service binding implements a specific protocol and the kind of service to be offered for a consumer.

Right click your Package->New->other ABAP Repository Object->Business Service->Service Binding.



Give name of Service Binding and service definition name for which binding needs to be created and click on Finish



Click on the button Publish as shown below to publish Odata service locally which makes service ready for consumption



Once we published, we can see published Information on right side.



Click on Service Url to see the Metadata



Right click on SOHeader/SoItem to see the UI Preview



 

APP Preview

This is just a preview and it will be useful to check how the UI looks with annotations implemented in CDS.



 

Note: - We can create proper UI project from Web IDE and map our Service Binding to test this application. Launch Web IDE -> Create Project from template->List Report->Map Service Binding



Our App will look like this :- It will show a list of sales orders.



Once we select the line item, Action 'Set Favourite' and CUD operations will be enabled:-



Once we click on the line item, It will go to the respective Sales order item page.



The above steps will guide you on how to create a RAP CRUD application.

Overview: ABAP Restful Programming Model: Development Flow



Steps to remember:-

  1. Model CDS view with proper annotations.( For simplicity I have created only one CDS view for root and then one for Item, but ideally, we will follow like we will create basic views for SO header and Item, then transactional( BO views ) for SO header and Item and then Projection views for SO Header and Item ).

  2. Create a Behavior definition for CDS views. ( Behavior definition for root transactional view and Behavior projection for Projection view )

  3. Create Behavior implementation for Behavior definition.

  4. Create a Service definition.

  5. Create Service Binding and add Service definition name for which binding needs to be created and Publish.

  6. Create WebIde project and map Service binding to it.


Conclusion: This programming model will be the future of ABAP which will be protocol agnostic and the good news is SAP will continue to support the ABAP Programming Model for SAP Fiori beside the ABAP RESTful Programming Model in the future for upwards compatibility reasons.

Hope you find this blog helpful.

 
51 Comments
yvallipi
Discoverer
0 Kudos
Nice Blog.. sony
I323214
Advisor
Advisor
0 Kudos
Thanks Yugandhar
AbhijeetK
Active Participant
0 Kudos

Nice Blog Indeed!

I believe ‘Service Binding’ and ‘Service Definition’ along with Behaviour Definition is not part of S4 HANA 1809 on Premises as it is giving error to me, may be it is part of Cloud.

 

Regards,

Abhijeet

nabheetscn
Active Contributor
0 Kudos
Great stuff and recap!
maheshpalavalli
Active Contributor
Yeah, It is currently released in cloud and in 1909 release, it will come to on premise.
I323214
Advisor
Advisor
0 Kudos

Thanks Mahesh for the quick response:)

I323214
Advisor
Advisor
0 Kudos
Thanks Abhijeet:) as Mahesh mentioned it is currently part of cloud release .
I323214
Advisor
Advisor
0 Kudos
Thanks Nabheet:)
Former Member

Hello Sony Sukumar,

When I tried with the SCN developer tutorial and created separate CUD methods it works for me but when I put them in one modify method it only works for create and throws dump in Update and delete.

The dump is related to the model IMO.

METHOD trigger_appl_model_error_dump.
DATA(_) = COND i( WHEN mv_aunit_exc_instead_of_dump <> abap_true THEN
THROW SHORTDUMP cx_sadl_dump_appl_model_error( ix_cause = cause )
"########################################################################################
"# !!! ATTENTION !!! #
"# Processing was deliberately stopped because an application modeling error has been #
"# detected. Please identify the root cause and contact the application owners: #
"# Carefully read the "Error Analysis" section of this dump ("Long text" tab in ADT #
"# or if viewed in SAP GUI (transaction ST22) in "ABAP Developer View"). #
"# For more detailed information refer to the exception chain contained in the dump. #
"# Identify the CDS view and/or service implementation classes to route this issue to #
"# the responsible application component. To facilitate the support incident please #
"# attach a full export of this dump and a description of your scenario. Thank you! #
"########################################################################################
ELSE THROW RESUMABLE cx_sadl_dump_appl_model_error( ix_cause = cause ) ). " For unit tests only; RESUMABLE allows for 100% coverage.
ENDMETHOD.

 

Can you please help ?

BDL =>

implementation unmanaged;
define behavior for YI_BOOKING_xxx implementation in class y_i_booking_xxx
lock master
etag LastChangedAt
{
field ( mandatory ) CustomerName, DateOfBooking, DateOfTravel, EmailAddress;
create;
update;
delete;
action set_status result [1] $self;
}

 

CDS =>

@AbapCatalog.sqlViewName: 'YV_BOOKING_XXX'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'View on booking information'
@Search.searchable: true

@UI: {
headerInfo: {
typeName: 'Booking',
typeNamePlural: 'Bookings',
title: { type: #STANDARD, value: 'Booking' }
}
}

define root view YI_BOOKING_xxx
as select from ypsb_booking_xxx as Booking
association [0..1] to I_Country as _Country on $projection.country = _Country.Country
association [0..1] to I_Currency as _Currency on $projection.CurrencyCode = _Currency.Currency
{

@UI.facet: [
{
id: 'Booking',
purpose: #STANDARD,
type: #IDENTIFICATION_REFERENCE,
label: 'Booking',
position: 10 }
]


@UI: {
lineItem: [ { position: 10, label: 'Booking ID', importance: #HIGH },
{ type: #FOR_ACTION, dataAction: 'set_status', label: 'Set Status'} ],
identification:[ { position: 10, label: 'Booking ID' } ]
}

key booking as Booking,

@UI: {
lineItem: [ { position: 20, label: 'Customer', importance: #HIGH } ],
identification:[ { position: 20, label: 'Customer' } ]
}
@Search.defaultSearchElement: true
customername as CustomerName,

@UI: {
lineItem: [ { position: 30, label: 'No of Passengers', importance: #HIGH } ],
identification:[ { position: 30, label: 'No of Passengers' } ]
}
numberofpassengers as NumberOfPassengers,

@UI: {
lineItem: [ { position: 50, label: 'Email', importance: #HIGH } ],
identification:[ { position: 40, label: 'Email' } ]
}
emailaddress as EmailAddress,

@UI: {
identification:[ { position: 50, label: 'Country' } ]
}
country,

@UI: {
identification:[ { position: 60, label: 'Booked On' } ]
}
dateofbooking as DateOfBooking,

@UI: { identification:[ { position: 70, label: 'Traveling on' } ] }
dateoftravel as DateOfTravel,


@UI: {
lineItem: [ { position: 40, label: 'Cost', importance: #HIGH } ],
identification:[ { position: 80, label: 'Price' } ]
}
@Semantics.amount.currencyCode: 'CurrencyCode'
cost,

@UI: { identification:[ { position: 90, label: 'Currency' } ] }
@Semantics.currencyCode: true
currencycode as CurrencyCode,

@UI: { identification:[ { position: 100, label: 'Last Changed At' } ] }
lastchangedat as LastChangedAt,

//publich associations
_Country,
_Currency
}

 

Handler class code=>

CLASS lcl_buffer DEFINITION.
ENDCLASS.

CLASS lhc_YI_BOOKING_xxx DEFINITION FINAL INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.

METHODS modify FOR BEHAVIOR IMPORTING
lt_data_to_create FOR CREATE YI_BOOKING_xxx
lt_data_to_update FOR UPDATE YI_BOOKING_xxx
lt_data_to_delete FOR DELETE YI_BOOKING_xxx
lt_data_set_status FOR ACTION YI_BOOKING_xxx~set_status RESULT action_results.

ENDCLASS.

CLASS lhc_YI_BOOKING_xxx IMPLEMENTATION.


METHOD modify.
DATA lt_data TYPE STANDARD TABLE OF ypsb_booking_xxx.

" To create a new entry in the business object +++
IF lt_data_to_create IS NOT INITIAL.
lt_data = CORRESPONDING #( lt_data_to_create ).
MODIFY ypsb_booking_xxx FROM TABLE @lt_data.
ENDIF.

" To update an existing entry in the business object +++
IF lt_data_to_update IS NOT INITIAL.
lt_data = CORRESPONDING #( lt_data_to_create ).
UPDATE ypsb_booking_xxx FROM TABLE @lt_data.
ENDIF.

" To delete an existing entry in the business object +++
IF lt_data_to_delete IS NOT INITIAL.
lt_data = CORRESPONDING #( lt_data_to_create ).
DELETE ypsb_booking_xxx FROM TABLE @lt_data.
ENDIF.

" To handle an action on the business object +++
IF lt_data_set_status IS NOT INITIAL.
DATA(ls_data) = CORRESPONDING ypsb_booking_xxx( lt_data_to_create[ 1 ] ).
ENDIF.
ENDMETHOD.

ENDCLASS.

CLASS lsc_YI_BOOKING_xxx DEFINITION INHERITING FROM cl_abap_behavior_saver.
PROTECTED SECTION.

METHODS check_before_save REDEFINITION.

METHODS finalize REDEFINITION.

METHODS save REDEFINITION.

ENDCLASS.

CLASS lsc_YI_BOOKING_xxx IMPLEMENTATION.

METHOD check_before_save.
ENDMETHOD.

METHOD finalize.
ENDMETHOD.

METHOD save.

ENDMETHOD.

ENDCLASS.

 

 

 

uttam_kumar4
Explorer
0 Kudos
Is it right that we cannot develop a service of its own and develop a Fiori Like application using RAP until we move to cloud?
0 Kudos
Nice Way of Explaining the Concept in Detail. Its really helpful blog for the Developers to Understand the RAP Concept and your Example for this blog is much helpful as well. Thanks a lot.

Regards

Ram
I323214
Advisor
Advisor
0 Kudos

Hi Uttam

RAP on prem is released as part of 1909 

I323214
Advisor
Advisor
0 Kudos
Thanks Sriram 🙂
0 Kudos

Hi Sony,

Great blog to understand the RAP model with example.Thanks.

Regards,

Manish Kumar

I323214
Advisor
Advisor
0 Kudos
Thanks Manish 🙂
SyambabuAllu
Contributor
Hi Sony,

I have tried this and working as expected 🙂

thanks for sharing this blog in detail!

Thanks,

Syam

 
I323214
Advisor
Advisor
0 Kudos
Thanks Syam
0 Kudos
Hi Sony! How did you configure the destination on SAP Cloud Platform cockpit? I'm stuck in this part.. Thanks in advance.
alexs0uza
Explorer
Hi marcellapenha, you can create a project from template based on the Multi-Target Application on WebIDE. Then you right-click the name of your project > New > SAP Cloud Platform, and it will open a pop-up where you can search for ABAP and add the service from your Dev Space. You can follow the steps in this tutorial: https://developers.sap.com/tutorials/abap-environment-deploy-cf-production.html
Thanks a lot, Alessandra!
former_member327092
Participant
0 Kudos
Hi Sony,

Great Blog and good introduction to RAP.

sonysukumar.kattoor - Couple of questions on this model and strategy that SAP is moving towards:

  1. Is this applicable to only SCP - ABAP Runtime Instance where you can locally query the tables in SCP and provide them as a service for consumption?

  2. How does this Programming model impact the S4 on-prem systems? In What scenarios we would use this on-prem?

  3. In On-Prem / Could we can define CDS View and then expose them as oData through annotations and this can be consumed in WebIDE for Fiori apps? I do not fully understand the difference between these 2 approaches. Can you shed some light?

Andy1
Product and Topic Expert
Product and Topic Expert
0 Kudos
Hi  Sony,

Really useful explanation and demo for RAP.

The ABAP Programming model for SAP Fiori (Current best practice) is already powerful to deliver Fiori app/OData Service/API for both cloud and OP, CDS view integrated well with BOPF,  it is efficient and easy for draft handling, lock handling, validation, determination within BOPF object generated by CDS View Annotation.  What's the limitation of current best practice? Why need RAP? What’s the current best practice cannot do but RAP support for SAP Cloud strategy?

Thank you for your reply in advance.

 
imihailovs
Explorer
0 Kudos
Not sure if relevant, but when I try to create a Behavior definition via ADT - I get the following error message:

Behavior Definition Validation Service not available

 

I have checked S4CORE version and it is 103, SP 2.

What else I might be missing?

Thank you in advance.
I323214
Advisor
Advisor
0 Kudos
Hi Raj,

 

1) RAP was released for cloud now it is available on Prem from 1909.

2 and 3) Normally for CDS based BOPF, we will first create BO using CDS and then it will be exposed to SAP GW, but here in RAP, in Behavior implementation, we can use existing BAPI's and API and this model is Protocol-agnostic.Hope this helps you.
I323214
Advisor
Advisor
0 Kudos
Hi Tikeer,

Normally for CDS based BOPF, we will first create BO using CDS and then it will be exposed to SAP GW, but here in RAP, in Behavior implementation, we can use existing BAPI’s and API. RAP is investing in Draft and it will be more powerful with future releases.
ravi_rajput
Participant
0 Kudos
Nice blog. Do you have any idea how do we implement Etags and locks in the unmanaged scenario ?
I323214
Advisor
Advisor
0 Kudos
We have options for Etag and lock  in behavior definition
I044911
Employee
Employee
0 Kudos
Hi Sony,

 

Thanks for your detail sharing. I met one issue during Unit Test. There is no EML for GET_FEATURES request, and this method can't be accessed directly as they are private sections.

How can we write UT for the GET_FEATURES method?

 

Regards

Gavin
former_member184739
Contributor
0 Kudos
sonysukumar.kattoor

My next questions to you would be, if a customer is running onprem-1909, then what is advised for the developers to chose? Will it be be CDS based BOPF or RAP ? Or that depends on the use case and requirements and if so could you please explain them at high level.

On an additional note, my understanding is, use CDS based BOPF for Greenfield implementation  involving transactional requirements and plain CDS for read only use cases.

Secondly use RAP for brownfield requirements which involves using BAPI'S, RFC & Functional modules.

Please correct me if my understanding is wrong. Thank you for your inputs and appreciate your help.

Regards

Praba
0 Kudos
Thanks Sony for sharing, very nice!

I wonder how would you make it to enable an action for all instances of an entity? In the sample of this blog, to make visible the button to set as favourite but all instances at once, not having to select any of them to be triggered?

Thanks.

Regards,

Daniel
I323214
Advisor
Advisor
Do you mean instead of the radio button, you need a checkbox and then enable action for those items selected in UI?

In this case, you have to do 2 changes:-

  1. In UI you have to make changes to enable the checkbox instead of a radio button.

  2. In Behavior definition action

    change result[1] $self to result[0..*] $self; and change behavior implementation accordingly , this might work.



We cannot use BAPI which include 'commit' statement. When BAPI is called, we get error BEHAVIOR_ILLEGAL_STATEMENT. I tried to use BAPI_SALESORDER_CHANGE and got this error message.

Header Information

































Short Text  Statement "CALL FUNCTION .. IN UPDATE TASK" is not allowed with this status.
Runtime Error  BEHAVIOR_ILLEGAL_STATEMENT
Program  SAPMV45A
Date/Time  06.07.2020 14:38:15 (System)
User 
Client 
Host 

What happened?


Error in the ABAP application program.

The current ABAP program "SAPMV45A" had to be terminated because it found a
statement that could not be executed.

Error analysis


There is probably an error in the program
"SAPMV45A".
A BEHAVIOR implementation is active for XYZ While this is the case,
the following ABAP statements are illegal:

- COMMIT
- ROLLBACK
- SUBMIT
- CALL TRANSACTION
- LEAVE
all DYNPRO-related statements, such as MESSAGE, CALL DIALOG, and CALL
SCREEN

The following statement is only allowed in the "Save” phase: - CALL
FUNCTION IN UPDATE TASK

 
md1992india
Explorer
0 Kudos
HI Sony,

Can you please tell how to handle draft feature in managed?
0 Kudos
Hi Sony ,

 

When I use VKORG as data element it says that it is not permitted !
0 Kudos
Hi Sony,

i have scenario like some fields need to restriction while create option like create date,last changed date etc.i have tried with @UI.hidden: #(CreateAction) but not working.

any idea to achieve this.

 

 
I323214
Advisor
Advisor
0 Kudos





Use field (read only ) field1; at behavior definition level then it will be reflected as read-only for that field in UI




0 Kudos
Yes, is there any possibility of in create scenario  hide the fields completely. bcoz those field not required at create action.
0 Kudos
Hi SOny,

I can see item fields for READ operation. But am not able to see item fields in CREATE scenario. I can see only Header fields. Am I missing any thing?

 

BR,

RAM.
kyo_choi2
Participant
0 Kudos

Can you provide the code and system version?  Are you on Cloud version or on-prem 1909?

former_member570896
Participant
I have the same issue trying to create an invoice. Did you solve this issue?

Thank you in advance.
Pradpandey
Explorer
0 Kudos
Hi sonysukumar.kattoor

It is really a very helpful blog.

we are also facing the same situation with BAPI_EQUI_CREATE which calls an FM in update task which was causing the issue in create method. To solve that I moved the Bapi call in Save method of behaviour implementation call and now we are able to create equipment, but we are unable to send back any success/error response as the SAVE method doesn't have any parameter.

Is there any way by which we can pass the response back from the SAVE method?

 

Thanks

Pradeep
OmPrakashJha
Participant
0 Kudos
Nice Blog!
emilian_felman1
Explorer
0 Kudos
Same issue here... did you create a ticket for this?
0 Kudos
Hi PRadeep,

How did you pass the entity values to the SAVE method.

I am unable to carry values from my behaviour implementation method to the standard SAVE method.

 
0 Kudos
Hi Sony,

We are trying to extend a Root CDS and added a new association to the extended CDS.
Now we all know that unless the association is not exposed in service definition it cannot be consumed by UX. So the CDS is extended, is there also a framework where service definition can be extended and the new association is exposed there?.

Thanks & Regards,

Udita Saklani
umtyzc
Participant
0 Kudos

I think you should use create, update or read method to carry values.

Look at this example: https://github.com/SAP-samples/abap-platform-rap-opensap/blob/main/week4/unit3.md

METHOD create.

DATA legacy_entity_in TYPE test.

legacy_entity_in = CORRESPONDING #( <entity> MAPPING FROM ENTITY USING CONTROL ).


CALL FUNCTION 'ABC'
EXPORTING
is_input = legacy_entity_in
IMPORTING
es_output = legacy_entity_out


ENDMETHOD.


METHOD save.
CALL FUNCTION 'ABC_SAVE'.
ENDMETHOD.
Raju
Explorer
0 Kudos
Have u find any solution for this ?
kawatra02
Explorer
0 Kudos
Hi sonysukumar.kattoor,

 

Is this the same code that will work on-Premise system as well?

 

Regards,

Himanshu
0 Kudos
Hi Sony,

Great information!

Is RAP a good choice for free style Fiori apps too? Can we achieve all the functionalities which are there for SEGW approach of service creation? How will be the UI code for create, update, delete etc.? For example, oModel.create(?), oModel.update(?).. for file upload, we have create_stream and other features like function import?

Thanks in advance!

Shahir

 
Balu483
Participant
0 Kudos

hi Sunil,

i am also facing the same isse.

i am calling BAPI '/DMO/FLIGHT_TRAVEL_CREATE' in Create method (Transactional Buffer) of local handler class of Behaviour implementation. by the time of this FM called BEHAVIOR_ILLEGAL_STATEMENT Dump i am getting and Description as 'Statement "UPDATE " is not allowed with this status'.

as per my understanding 'CREATE', 'UPDATE', 'DELETE' statements are not allwoed to use in Transaction buffer phase. almost all BAPI's might have used any one of these statements inside there respective implementations, in that case we are not able to call BAPI's in Transactional Buffer like inside create. modify, delete methods implementations?

Like me may people are facing the same issue. i had searched in Community But unfortunatly there is no much information how to resolve this error.  andre.fischer ,carine.tchoutouodjomo, volker.drees  could you please help us how to resolve the issue.

Thank you in advance.

 

Regards,

B@lu.