Hi Everyone,
Scenario : Sending an Email for a Selected Record Using the RAP Model
Introduction:
In an SAP S/4HANA system, there is a need to send an email notification when a user selects or processes a specific record in a RAP (RESTful ABAP Programming)–based application. For example, when a sales order, request, or approval record is selected in the Fiori Elements app, an email should automatically be triggered to the responsible user or approver.
1. Creation of Table :
@EndUserText.label : 'Service Header Table'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #ALLOWED
define table zva_hdr_service {
key client : abap.clnt not null;
key serviceno : zva_serviceno not null;
servicename : zva_servicename;
startdate : abap.dats;
enddate : abap.dats;
@Semantics.amount.currencyCode : 'zva_hdr_service.currency'
amount : abap.curr(8,2);
currency : abap.cuky;
createdby : uname;
createdon : datum;
}2. Creation of Root View Entity :
In the SAP RESTful ABAP Programming Model (RAP), the Root View Entity is the main CDS view entity that defines the data model and structure of the root business object.
It serves as the entry point for the RAP business object and forms the foundation for its behavior and service exposure.
A Root View Entity is defined using the CDS keyword define root view entity. It typically represents the main database table or a combination of tables that store the business data.
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Root View'
@Metadata.ignorePropagatedAnnotations: true
define root view entity zva_header_serv_root as select from zva_hdr_service as Service
{
key Service.serviceno as Serviceno,
Service.servicename as Servicename,
Service.startdate as Startdate,
Service.enddate as Enddate,
@Semantics.amount.currencyCode: 'currency'
Service.amount as Amount,
Service.currency as Currency
}
3. Creation of Projection View for Root View Entity:
In SAP RAP, a Projection View is a Core Data Services (CDS) view that defines which parts of a Business Object (BO) — specifically its data and associations — are exposed to the outside world (for example, through an OData service or Fiori app).
It acts as a public interface of your business object.
While the Root View Entity defines the complete internal data model, the Projection View determines the external view that users or external systems can access.
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Projection View'
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true
define root view entity ZVA_HEADER_SERV_ROOT_pro as projection on zva_header_serv_root as Service
{
key Service.Serviceno,
Service.Servicename,
Service.Startdate,
Service.Enddate,
@Semantics.amount.currencyCode: 'Currency'
Service.Amount,
Service.Currency
}4. Creation of Metadata Extensions for Projection View:
Metadata extensions are used to define UI-specific annotations for CDS views. They allow the separation of concerns by keeping the data model independent of UI-related semantics. These extensions are particularly useful for defining Fiori UI layouts and behaviors without modifying the underlying CDS view.
@Metadata.layer: #CORE
annotate entity ZVA_HEADER_SERV_ROOT_pro
with
{
:{ lineItem:[{ type: #FOR_ACTION , dataAction: 'SendEmail',label: 'Email' } ] }
:{ lineItem:[{ position:1 }],
selectionField: [{ position: 1 ,element: 'Serviceno' }] }
Serviceno;
:{ lineItem: [{ label: 'Service Name' , position:2 }],
selectionField: [{ position: 2 ,element: 'Servicename' }] }
Servicename;
: { lineItem: [{ label: 'Start Date' , position:3 }],
selectionField: [{ position: 3,element: 'Startdate' }] }
Startdate;
: { lineItem: [{ label: 'End Date' , position:4 }],
selectionField: [{ position: 4 ,element: 'Enddate'}] }
Enddate;
.lineItem: [{ label: 'Amount' , position:5 }]
Amount;
.lineItem: [{ label: 'Currency' , position:6 }]
Currency;
}5. Creation of Root Abstract Entity :
A Root Abstract Entity is a CDS construct designed for modeling complex input parameters or non-standard operations in RAP. Unlike root view entities, abstract entities are not tied to database tables.
@EndUserText.label: 'Email'
define root abstract entity zva_email_send
{
// Email : char200;
Email : zva_email;
}
6. Creation of Behavior Definition for Root View or Consumption View and implement the classes:
Behavior Definition (BDEF) is a key component that defines the transactional behavior of a RAP Business Object (BO). It specifies how the BO can be accessed and manipulated by consumers, such as creating, updating, or deleting records. The BDEF is always tied to a Core Data Services (CDS) data model, which includes at least one root entity.
A BDEF consists of two main parts: a header and one or more entity behavior definitions. The header defines the overall behavior, while the entity behavior definitions specify the characteristics and operations for each entity. These operations include standard actions like create, update, and delete, as well as custom actions, determinations, and validations.
managed implementation in class zbp_va_header_serv_root unique;
strict ( 2 );
define behavior for zva_header_serv_root alias Service
persistent table ZVA_HDR_SERVICE
lock master
authorization master ( instance )
//etag master <field_name>
{
action SendEmail parameter zva_email_send;
}Place the cursor on the class name, press ( Ctrl + 1 ), choose Implement the Class, and then activate the class.
CLASS lhc_Service DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR Service RESULT result.
METHODS SendEmail FOR MODIFY
IMPORTING keys FOR ACTION Service~SendEmail.
ENDCLASS.
CLASS lhc_Service IMPLEMENTATION.
METHOD get_instance_authorizations.
ENDMETHOD.
METHOD SendEmail.
ENDMETHOD.
ENDCLASS.Implementation of SendEmail Method:
" Implementation of the custom action SendEmail
METHOD SendEmail.
" Get the first selected record from the action context
DATA(ls_keys) = VALUE #( keys[ 1 ] OPTIONAL ).
DATA(p_email) = ls_keys-%param-Email.
"-------------------------
" Step 1: Validate email
"-------------------------
IF p_email IS INITIAL.
" No email provided -> return error message
APPEND VALUE #( %tky = ls_keys-%tky
%msg = new_message( id = 'ZVA_MSG'
number = '000'
severity = if_abap_behv_message=>severity-error ) )
TO reported-Service.
RETURN.
ENDIF.
IF NOT p_email CP '*@*.*'.
" Invalid email format -> return error message
APPEND VALUE #( %tky = ls_keys-%tky
%msg = new_message( id = 'ZVA_MSG'
number = '001'
severity = if_abap_behv_message=>severity-error ) )
TO reported-Service.
RETURN.
ENDIF.
"-------------------------
" Step 2: Read service data
"-------------------------
READ ENTITIES OF zva_header_serv_root
ENTITY Service
ALL FIELDS
WITH VALUE #( ( Serviceno = ls_keys-Serviceno ) )
RESULT DATA(lt_serv).
DATA(ls_serv) = lt_serv[ 1 ].
"-------------------------
" Step 3: Prepare and send email
"-------------------------
TRY.
" Create persistent send request (BCS)
DATA(lo_send_request) = cl_bcs=>create_persistent( ).
" Prepare HTML email body
DATA: lt_body TYPE soli_tab,
lv_html TYPE string,
lv_text TYPE string.
lv_text = 'Hi Good Morning..'.
" Add HTML table header
CONCATENATE
'<html><body>'
'<p>' lv_text '</p>'
'<h3>Service Details</h3>'
'<table border="1" cellpadding="8" cellspacing="0" style="border-collapse:collapse;">'
'<tr>'
'<th>Service Number</th>'
'<th>Service Name</th>'
'<th>StartDate</th>'
'<th>EndDate</th>'
'<th>Amount</th>'
'</tr>'
INTO lv_html SEPARATED BY space.
APPEND lv_html TO lt_body.
CLEAR lv_html.
" Add dynamic service data rows
LOOP AT lt_serv INTO ls_serv.
DATA(lv_amount) = ls_serv-Amount.
CONCATENATE
'<tr>'
'<td>' ls_serv-Serviceno '</td>'
'<td>' ls_serv-Servicename '</td>'
'<td>' ls_serv-Startdate '</td>'
'<td>' ls_serv-Enddate '</td>'
'<td>' lv_amount '</td>'
'</tr>'
INTO lv_html SEPARATED BY space.
APPEND lv_html TO lt_body.
CLEAR lv_html.
ENDLOOP.
" Set up document object for the email
DATA(lo_document) = cl_document_bcs=>create_document(
i_type = 'HTM'
i_text = lt_body
i_subject = 'Service Details' ).
" Add document to send request
lo_send_request->set_document( lo_document ).
" Set sender as current SAP user
lo_send_request->set_sender( cl_sapuser_bcs=>create( sy-uname ) ).
" Add recipient email
lo_send_request->add_recipient(
i_recipient = cl_cam_address_bcs=>create_internet_address( p_email ),
i_express = abap_true ).
" Send the email
DATA(lv_sent_to_all) = lo_send_request->send( ).
ENDTRY.
"-------------------------
" Step 4: Show success or error messages
"-------------------------
IF lv_sent_to_all = abap_true.
" Email sent successfully
APPEND VALUE #( %tky = ls_keys-%tky
%msg = new_message( id = 'ZVA_MSG'
number = '002'
severity = if_abap_behv_message=>severity-success ) )
TO reported-Service.
ELSE.
" Email sending failed
APPEND VALUE #( %tky = ls_keys-%tky
%msg = new_message( id = 'ZVA_MSG'
number = '003'
severity = if_abap_behv_message=>severity-error ) )
TO reported-Service.
ENDIF.
ENDMETHOD.
7. Creation of Behavior Definition for Projection View and Implement the classes :
A Behavior Projection maps the transactional capabilities of the base behavior definition to a projection view. This allows for further customization of the behavior for specific use cases. For example:
projection implementation in class zbp_va_header_serv_root_pro unique;
strict ( 2 );
define behavior for ZVA_HEADER_SERV_ROOT_pro //alias <alias_name>
{
use action SendEmail ;
}Place the cursor on the class name, press ( Ctrl + 1 ), choose Implement the Class, and then activate the class.
8. Creation of Service Definition for Consumption View :
@EndUserText.label: 'Service Definition'
define service ZVA_HEADER_SERV_ROOT_PRO_SD {
expose ZVA_HEADER_SERV_ROOT_pro;
}9. Creation of Service Binding for Service Definition:
Click on public button and activate
Click on preview button then navigate the fiori .
Click on a Email button then open a popup then provide the email id.
if email id is not provided it's shows the error and incorrect email provided also shows a error message.
Email sent successful then shows the success message.
Go to SOST t-code we will check the the record.
Select the record and click on display button
In this implementation, a custom action SendEmail is added to a RAP BO to allow users to send an email containing service details directly from the application.
The action first retrieves the email ID passed through the action parameters.
It performs two validations:
Checks if the email field is empty
Checks if the email format is valid using a simple pattern *@*.*
If the validation fails, an error message is returned using RAP messaging.
The code reads the selected service record from the root entity (zva_header_serv_root) using READ ENTITIES.
The retrieved fields are later used to dynamically build the email content.
The email is sent using SAP Business Communication Services (BCS):
A persistent send request (cl_bcs) is created
An HTML email body is built, including:
Greeting text
A formatted HTML table
Dynamically added service details
The document is attached to the send request as an HTML email (HTM)
Sender is set as the logged-in SAP user
Recipient is the email address entered by the user
The email is finally sent using send( )
After sending, the system returns:
A success message if the email was sent
An error message if the sending process failed
These messages are reported back through RAP’s reported- structure.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
| User | Count |
|---|---|
| 36 | |
| 25 | |
| 17 | |
| 16 | |
| 16 | |
| 15 | |
| 13 | |
| 13 | |
| 12 | |
| 12 |