RAP and abap2UI5 fit together naturally: the business object keeps the business logic, abap2UI5 builds the UI on top of it — in plain ABAP, with no OData service and no annotations in between. If you already have RAP BOs, you can put a screen in front of them today. There is one runnable sample per EML statement, and the business object to run them against ships with this package, so you can start right away.
Two ways in — pick yours:
- You know EML and want the snippet → Find the snippet. Every class carries its statement in the comment at the very top, so you see it the moment you open the file.
- RAP is new to you → start with The business object. It is one page, and it makes every message the samples show readable.
The draft enabled half lives next door in 04 RAP with Draft.
Release: Cloud + Standard ≥ 7.54 (1909) — that is what EML asks for.
Branch: 03-rap
— this package alone, without the other eight on your system.
ABAP Platform >= 1909 or a BTP ABAP Environment. The business object
Z2UI5_R_SMPS_TRV and its table come with this package (src/03/01), so
nothing else has to be installed.
Run 000 overview —
?app_start=z2ui5_cl_smps_app_000. It lists every sample of this repository, the
RAP ones included, and opens each in a new browser tab, so the overview stays open
and several samples can run side by side. Regenerate Demo Data in its header
fills both business objects.
Fill the tables before the first run: execute Z2UI5_CL_SMPS_DATA_TRV (and
Z2UI5_CL_SMPS_DATA_TRD for the draft package) with F9 in ADT, or press
Regenerate Demo Data in the overview — Generate Demo Data in a single sample
does the same for its own business object. Both offer data_generate( ),
data_delete( ) and data_reset( ).
Demo data is created through the business object, not with an INSERT — otherwise
the determinations would not run and the rows would be data the BO could never
produce.
Z2UI5_R_SMPS_TRV manages a travel. It is an ordinary managed RAP BO — small on
purpose, but not so small that consuming it is uninteresting.
| Field | |
|---|---|
TravelId |
the readable key, 8 digits. Assigned by the BO, never by the caller |
AgencyId, CustomerId |
mandatory |
BeginDate, EndDate |
mandatory, and EndDate must not be before BeginDate |
BookingFee, CurrencyCode |
what the caller may write |
TotalPrice |
readonly — the BO derives it |
OverallStatus |
readonly — O open, A accepted, X rejected |
Description |
free text |
CreatedBy/At, LastChangedBy/At |
readonly — filled by the runtime |
What runs, and when, is the part worth knowing up front — once it clicks, the rest of the samples read themselves:
- Early numbering hands out
TravelIdwhile the CREATE is still in the transactional buffer. That is why the new key comes back inMAPPEDunder the%cidyou sent, and why you never pass a key on CREATE. - A determination (
setInitialValues) fillsOverallStatus,TotalPriceand the currency right after a create. Those fields are readonly for you precisely because the BO owns them. - Two validations (
validateCustomer,validateDates) run on save, not at theMODIFY. AMODIFYthat answered with an emptyFAILEDcan still be refused at theCOMMIT— which is why the samples always evaluate both responses. - Two actions (
acceptTravel,rejectTravel) setOverallStatus. An action is called withEXECUTE.
Five samples: four single statements, then one complete app. The numbers are the reading order.
| You want to | Statement | Sample |
|---|---|---|
| read an instance | READ ENTITIES |
001 |
| create one | MODIFY … CREATE → MAPPED |
002 |
| change fields | MODIFY … UPDATE FIELDS |
003 |
| delete one | MODIFY … DELETE FROM |
004 |
| show BO messages in the UI | msg_get_collect( ) |
context |
The complete app shows the next step: everything the single statements teach, now in one screen with popups, message handling and a refresh — roughly three times the size, and close to what a real app looks like. Best read once the snippets have made sense:
| call a BO action, save and catch what failed | MODIFY … EXECUTE, COMMIT ENTITIES RESPONSE OF |
005 manage travels |
Read — no SELECT, no OData.
READ ENTITIES OF z2ui5_r_smps_trv
ENTITY travel
ALL FIELDS WITH VALUE #( ( travelid = travel_id ) )
RESULT DATA(t_result)
FAILED DATA(s_failed).A key that does not exist is not an exception — it lands in FAILED, and RESULT
simply has one row less. The response is what you check, never sy-subrc.
Create — the %cid is yours; the key the BO assigns comes back under it.
MODIFY ENTITIES OF z2ui5_r_smps_trv
ENTITY travel
CREATE FIELDS ( agencyid customerid begindate enddate )
WITH VALUE #( ( %cid = `CREATE_1` agencyid = '070001' customerid = '000001' ) )
MAPPED DATA(s_mapped)
FAILED DATA(s_failed)
REPORTED DATA(s_reported).
DATA(new_id) = s_mapped-travel[ %cid = `CREATE_1` ]-travelid.Update / delete / action — same shape, only the operation differs.
UPDATE FIELDS ( description )
WITH VALUE #( ( travelid = travel_id description = `...` ) )
DELETE FROM VALUE #( ( travelid = travel_id ) )
EXECUTE acceptTravel FROM VALUE #( ( travelid = travel_id ) )Save — validations run here, not at the MODIFY.
COMMIT ENTITIES RESPONSE OF z2ui5_r_smps_trv
FAILED DATA(s_failed)
REPORTED DATA(s_reported).Messages — don't loop over %msg yourself. abap2UI5 ships the reader: it
recognises a RAP structure by %MSG/%FAIL, takes a whole REPORTED response or a
single entity table, and pulls out the failure cause, element, action, %cid and
%tky.
client->message_box_display( text = z2ui5_cl_util=>msg_get_collect( s_reported-travel )
type = `Error` ).04RAP with Draft — the same BO, draft enabled.05Business Events — what happens after the save.