Application Development and Automation Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
Gireesh_pg1
Explorer
2,365

Hi all,

In SAP's ABAP RESTFULL Application Programming Model (RAP), a function is a non-standard operation defined in behavior definitions. Functions are implemented in the ABAP behavior pool class and are used to return information without modifying the state of the business object. 

Here are some key points about functions in RAP: 

  • Purpose: Functions perform calculations or read operations on business objects without issuing locks or modifying data. 
  • Implementation: Functions are implemented in the `FOR READ` method in the ABAP behavior pool. 
  • Types: Functions can be instance-specific or static. Instance functions relate to a specific entity instance, while static functions relate to the entire entity. 
  • Usage: Functions can be used to default fields, perform calculations, or read data without side effects. 

Function in RAP is a custom read-operation that is part of business logic. 

Functions perform calculations or reads on business objects without causing any side effects. Functions don't issue any locks on database tables, and you can't modify or persist any data computed in a function implementation. 

Functions are specified as nonstandard operations in behavior definitions and are implemented in the ABAP behavior pool. 

We have 3 types of functions. 

  1. Internal function. 
  1. Static function. 
  1. Repeatable function. 

Note: You can't define authorization control or feature control for functions. 

Basically, I have taken 2 database tables. 

Step 1: - Header table.

 

 

@EndUserText.label : 'header table' 

@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE 

@AbapCatalog.tableCategory : #TRANSPARENT 

@AbapCatalog.deliveryClass : #A 

@AbapCatalog.dataMaintenance : #RESTRICTED 

define table zspfli_t_header { 

key client : abap.clnt not null; 

key carrid : abap.char(3) not null; 

key connid : abap.numc(4) not null; 

country_fly : abap.char(3); 

city_from : abap.char(20); 

airfrom : abap.char(3); 
} 

 

 

Gireesh_pg1_0-1737720586582.png

Step 2: - Item table

 

 

@EndUserText.label : 'item table' 

@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE 

@AbapCatalog.tableCategory : #TRANSPARENT 

@AbapCatalog.deliveryClass : #A 

@AbapCatalog.dataMaintenance : #RESTRICTED 

define table zflight_t_item1 { 
key client : abap.clnt not null; 

key carrid : abap.char(3) not null; 

key connid : abap.numc(4) not null; 

key fdate : abap.dats not null; 

@Semantics.amount.currencyCode : 'zflight_t_item1.p_currency' 

price : abap.curr(15,2); 

p_currency : abap.cuky; 

planetype : abap.char(10); 

seat_max : abap.int4; 
} 

 

 

Gireesh_pg1_0-1737720788097.png

We have some records in these 2 tables. 

After that I have created interface view for both header table and item table. 

Step 3: - This is my root entity.

 

@AccessControl.authorizationCheck: #NOT_REQUIRED 

@EndUserText.label: 'header details' 

define root view entity zi_flight_header01 as select from zspfli_t_header 

composition[0..*] of zi_flight_item01 as _item 

{ 

key carrid as Carrid, 

key connid as Connid, 

country_fly as CountryFly, 

city_from as CityFrom, 

airfrom as Airfrom, 

_item 
} 

 

Step 4: - This is my child entity. 

 

@AbapCatalog.viewEnhancementCategory: [#NONE] 

@AccessControl.authorizationCheck: #NOT_REQUIRED 

@EndUserText.label: 'item table details' 

@Metadata.ignorePropagatedAnnotations: true 

@ObjectModel.usageType:{ 

serviceQuality: #X, 

sizeCategory: #S, 

dataClass: #MIXED 

} 

define view entity zi_flight_item01 as select from zflight_t_item1 

association to parent zi_flight_header01 as _header 

on $projection.Carrid = _header.Carrid and  

$projection.Connid = _header.Connid 

{ 

key carrid as Carrid, 

key connid as Connid, 

key fdate as Fdate, 

@Semantics.amount.currencyCode: 'PCurrency' 

price as Price, 

p_currency as PCurrency, 

planetype as Planetype, 

seat_max as SeatMax, 

_header 
} 

 

And I have created a projection view for these basic views. 

Step 5: - Projection view for Header table. 

 

@EndUserText.label: 'header projection view' 

@AccessControl.authorizationCheck: #NOT_REQUIRED 

@Metadata.allowExtensions: true 

define root view entity zc_header_flight 

provider contract transactional_query as projection on zi_flight_header01 

{ 

key Carrid, 

key Connid, 

CountryFly, 

CityFrom, 

Airfrom, 

/* Associations */ 

_item 
} 

 

Step 6: - Projection view for Item table. 

 

@EndUserText.label: 'projection view for item' 

@AccessControl.authorizationCheck: #NOT_REQUIRED 

define view entity zc_flight_item 

provider contract transactional_query as projection on zi_flight_item01 

{ 

key Carrid, 

key Connid, 

key Fdate, 

Price, 

PCurrency, 

Planetype, 

SeatMax, 

/* Associations */ 

_header 
} 

 

Step 7: - After that I have created behavior definition. 

 

managed implementation in class zbp_i_flight_header01 unique; 

strict ( 2 ); 
define behavior for zi_flight_header01 alias header 

persistent table zspfli_t_header 

lock master 

authorization master ( global ) 

//etag master <field_name> 

{ 

create; 

update; 

delete; 

function fun_action result [1] $self; 
field ( readonly ) Carrid, Connid; 

association _item { create; } 

mapping for ZSPFLI_T_HEADER 

{ 

Carrid = carrid; 

CityFrom = city_from; 

Connid = connid; 

CountryFly = country_fly; 

Airfrom = airfrom; 
} 

} 

define behavior for zi_flight_item01 //alias <alias_name> 

persistent table zflight_t_item1 

lock dependent by _header 

authorization dependent by _header 

//etag master <field_name> 

{ 

update; 

delete; 

field ( readonly ) Carrid, Connid, Fdate; 

association _header; 
} 

 

Step 8: - Implementation class. 

 

CLASS lhc_zi_flight_header01 DEFINITION INHERITING FROM cl_abap_behavior_handler. 

PUBLIC SECTION. 

*INTERFACES if_oo_adt_classrun. 

PRIVATE SECTION. 
METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION 

IMPORTING REQUEST requested_authorizations FOR zi_flight_header01 RESULT result. 

METHODS fun_action FOR READ 

IMPORTING keys FOR FUNCTION zi_flight_header01~fun_action RESULT result. 
ENDCLASS. 

CLASS lhc_zi_flight_header01 IMPLEMENTATION. 

METHOD get_global_authorizations. 

ENDMETHOD. 
METHOD fun_action. 
READ ENTITIES OF zi_flight_header01 IN LOCAL MODE ENTITY header 

FIELDS ( carrid connid CountryFly CityFrom Airfrom ) WITH CORRESPONDING #( keys ) 

RESULT DATA(lt_result) 

FAILED DATA(lt_failed). 

if lt_result is NOT INITIAL. 

loop AT lt_result ASSIGNING FIELD-SYMBOL(<ls_result>). 

if <ls_result>-Airfrom = 'MYS' . 

<ls_result>-Airfrom = 'MD'. 

ENDIF. 

APPEND VALUE #( %tky = <ls_result>-%tky 

%param = CORRESPONDING #( <ls_result> ) ) TO result. 

ENDLOOP. 
ENDIF. 
ENDMETHOD. 
ENDCLASS. 

 

Step 9: - And also, projection view to consumption view.

 

projection; 

strict ( 2 ); 
define behavior for zc_header_flight //alias <alias_name> 
{ 
use create; 

use update; 

use delete; 

use function fun_action; 
} 

 

Step 10: - After that I have created service definition and service binding 

 

@EndUserText.label: 'service definition for flight header' 

define service Zservice_flight_h { 

expose zi_flight_header01; 

expose zi_flight_item01; 

} 

 

Step 11 : - Service Binding. 

Gireesh_pg1_0-1737721875231.png

After that this will be my output. 

Gireesh_pg1_1-1737721926672.png

Step 12: - But to function method calling I have taken another class it is inhering class classrun. 

 

CLASS zcl_test_ga DEFINITION 

PUBLIC 

INHERITING FROM cl_demo_classrun 

FINAL 

CREATE PUBLIC . 
PUBLIC SECTION. 

METHODS main REDEFINITION. 

PROTECTED SECTION. 

PRIVATE SECTION. 

ENDCLASS. 
CLASS zcl_test_ga IMPLEMENTATION. 

METHOD main. 

"Read operation executing a function 

READ ENTITIES OF zi_flight_header01 

ENTITY header 

EXECUTE fun_action 

FROM VALUE #( ( %tky-Carrid = 'LH' 

%tky-Connid = '0400' ) ) 

RESULT Data(LT_result) 

FAILED FINAL(faiLED) 

REPORTED FINAL(reported). 
OUT->write( LT_result ). 
ENDMETHOD. 
ENDCLASS. 

 

Conclusion. 

By using function, basically we can read the data from database and if it wants to modify the records we can modify in transactional buffer records only. We can't modify the database table records by using function methods. 

Output :--> console. 

Gireesh_pg1_2-1737722071423.png

Output :---> database table  

Gireesh_pg1_3-1737722121946.png

 

 

 

1 Comment