RAP Code Generation: Using ADT Generator and Fiori Tools

Category
RAP
Published
Author
Johannes

Manual creation of all RAP artifacts is time-consuming: Tables, CDS Views, Behavior Definitions, Service Bindings - this quickly adds up to a dozen objects. With the RAP Generators in ADT and the Fiori Elements App Generator, you can dramatically accelerate this process.

Why Code Generation?

A complete RAP stack with draft handling typically includes:

1. Database table
2. Draft table
3. Interface CDS View
4. Projection CDS View
5. Metadata Extension
6. Behavior Definition
7. Behavior Implementation
8. Service Definition
9. Service Binding

Creating these nine objects manually and linking them correctly takes time - especially with consistent naming conventions and correct syntax. The RAP Generator creates all of this in a few clicks.

RAP Generator in ADT

The RAP Generator is directly integrated into ABAP Development Tools (ADT) and generates complete RAP Business Objects from table definitions.

Prerequisites

  • SAP S/4HANA 2022 or newer
  • SAP BTP ABAP Environment
  • ABAP Development Tools (Eclipse)

Step 1: Start Generator

Right-click on database table
→ Generate ABAP Repository Objects
→ Generate RAP BO

Alternatively:

Right-click on package
→ New → Other ABAP Repository Object
→ Business Services → Generate RAP BO

Step 2: Select Table

Select the main table for your Business Object. For our flight booking example:

Table: ZFLIGHT_BOOK

The generator automatically recognizes:

  • Key fields
  • Administrative fields (created_by, last_changed_at, etc.)
  • Associations to other tables

Step 3: Generation Options

OptionDescriptionRecommendation
Implementation TypeManaged or UnmanagedManaged for standard cases
Draft HandlingWith or without draftWith draft for editing apps
Data ModelSingle or HierarchyHierarchy for parent-child
ProjectionWith projection layerYes for UI applications

For the flight booking scenario:

Implementation Type: Managed
Draft Handling: Yes
Data Model: Single BO
Projection: Yes

Step 4: Configure Names

The generator suggests names based on the table:

Table: ZFLIGHT_BOOK
Interface View: ZI_FLIGHTBOOK
Projection View: ZC_FLIGHTBOOK
Behavior Def: ZI_FLIGHTBOOK
Service Definition: ZUI_FLIGHTBOOK
Service Binding: ZUI_FLIGHTBOOK_O4

Customize according to your naming conventions - consistent prefixes are important:

I_ = Interface Layer
C_ = Consumption/Projection Layer
UI_ = UI Service
_O4 = OData V4

Step 5: Execute Generation

After clicking “Finish,” all objects are created:

┌─────────────────────────────────────────────────────────┐
│ Generated Objects │
├─────────────────────────────────────────────────────────┤
│ ✓ ZDRAFT_FLIGHT_BOOK (Draft table) │
│ ✓ ZI_FLIGHTBOOK (Interface CDS View) │
│ ✓ ZI_FLIGHTBOOK (Behavior Definition) │
│ ✓ ZBP_I_FLIGHTBOOK (Behavior Implementation) │
│ ✓ ZC_FLIGHTBOOK (Projection CDS View) │
│ ✓ ZC_FLIGHTBOOK (Projection Behavior) │
│ ✓ ZUI_FLIGHTBOOK (Service Definition) │
│ ✓ ZUI_FLIGHTBOOK_O4 (Service Binding) │
└─────────────────────────────────────────────────────────┘

Understanding Generated Artifacts

Interface CDS View

The generator creates a complete Interface View:

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Flight Booking'
define root view entity ZI_FlightBook
as select from zflight_book
{
key booking_uuid,
flight_id,
customer_id,
booking_date,
seat_number,
status,
price,
currency_code,
@Semantics.user.createdBy: true
created_by,
@Semantics.systemDateTime.createdAt: true
created_at,
@Semantics.user.lastChangedBy: true
last_changed_by,
@Semantics.systemDateTime.lastChangedAt: true
last_changed_at,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
local_last_changed
}

Important: @Semantics annotations are automatically set for known field names.

Behavior Definition

managed implementation in class zbp_i_flightbook unique;
strict ( 2 );
with draft;
define behavior for ZI_FlightBook alias FlightBook
persistent table zflight_book
draft table zdraft_flight_book
etag master LocalLastChanged
lock master total etag LastChangedAt
authorization master ( global )
{
field ( readonly )
BookingUUID,
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt,
LocalLastChanged;
field ( numbering : managed )
BookingUUID;
create;
update;
delete;
draft action Activate optimized;
draft action Discard;
draft action Edit;
draft action Resume;
draft determine action Prepare;
}

Behavior Implementation

The generated class contains scaffolding for local handlers:

CLASS lhc_FlightBook DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS:
get_global_authorizations FOR GLOBAL AUTHORIZATION
IMPORTING REQUEST requested_authorizations FOR FlightBook
RESULT result.
ENDCLASS.
CLASS lhc_FlightBook IMPLEMENTATION.
METHOD get_global_authorizations.
" Implement your own authorization checks here
ENDMETHOD.
ENDCLASS.

Customizing Generated Objects

After generation, you typically need to extend the objects:

1. Add UI Annotations

In the Projection View or Metadata Extension:

@UI.headerInfo: {
typeName: 'Flight Booking',
typeNamePlural: 'Flight Bookings',
title: { value: 'FlightID' }
}
@UI.lineItem: [{ position: 10 }]
@UI.identification: [{ position: 10 }]
FlightID;
@UI.lineItem: [{ position: 20 }]
@UI.selectionField: [{ position: 10 }]
BookingDate;

2. Add Validations

In the Behavior Definition:

define behavior for ZI_FlightBook alias FlightBook
...
{
validation validateBookingDate on save { field BookingDate; }
validation validateSeat on save { field SeatNumber; }
}

In the Implementation:

METHOD validateBookingDate.
READ ENTITIES OF zi_flightbook IN LOCAL MODE
ENTITY FlightBook
FIELDS ( BookingDate )
WITH CORRESPONDING #( keys )
RESULT DATA(bookings).
LOOP AT bookings INTO DATA(booking).
IF booking-BookingDate < cl_abap_context_info=>get_system_date( ).
APPEND VALUE #( %tky = booking-%tky ) TO failed-flightbook.
APPEND VALUE #( %tky = booking-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Booking date must be in the future' )
%element-BookingDate = if_abap_behv=>mk-on
) TO reported-flightbook.
ENDIF.
ENDLOOP.
ENDMETHOD.

3. Add Custom Actions

define behavior for ZI_FlightBook alias FlightBook
...
{
action confirmBooking result [1] $self;
action cancelBooking result [1] $self;
}

Fiori Elements App Generator

After the RAP backend, you can generate the frontend with the Fiori Elements App Generator.

In Business Application Studio

1. Open Command Palette (F1)
2. Enter "Fiori: Open Application Generator"
3. Select template: "List Report Page" or "Worklist"
4. Data source: Select OData V4 Service
5. Enter Service Binding: ZUI_FLIGHTBOOK_O4
6. Select main entity: FlightBook
7. Assign project name

Generated App Structure

flight-booking-app/
├── webapp/
│ ├── manifest.json # App configuration
│ ├── Component.js # UI5 Component
│ ├── index.html # Start page
│ └── localService/ # Mock data
├── package.json # Dependencies
└── ui5.yaml # Build configuration

Customize manifest.json

The most important customizations:

{
"sap.app": {
"title": "{{appTitle}}",
"description": "{{appDescription}}"
},
"sap.ui5": {
"routing": {
"targets": {
"FlightBookList": {
"options": {
"settings": {
"initialLoad": true,
"variantManagement": "Page"
}
}
}
}
}
}
}

Generator vs. Manual: Decision Guide

ScenarioGeneratorManual
New greenfield projectRecommendedNo
Standard CRUD appRecommendedNo
Complex hierarchiesPartiallyPartly customization needed
Migration from legacyNoYes, for control
Unmanaged scenarioLimitedMostly manual
Learning/TrainingNoYes, for understanding
PrototypingRecommendedNo

When to Use Generator?

Recommended:

  • New standard applications
  • Managed scenario with draft
  • Quick prototypes
  • Consistent naming conventions important

Prefer Manual:

  • Unmanaged with legacy integration
  • Complex BO hierarchies
  • Special structural requirements
  • Learning projects for RAP understanding

Typical Customizations After Generation

Checklist for Generated Objects

Customize after generation:
□ Interface View
□ @EndUserText.label for all fields
□ Associations to other entities
□ @ObjectModel.text for text fields
□ Projection View
□ Define @UI.headerInfo
□ @UI.lineItem for List Report
□ @UI.identification for Object Page
□ @UI.selectionField for filters
□ Behavior Definition
□ Add validations
□ Determinations for default values
□ Define custom actions
□ Configure authorization checks
□ Service Binding
□ Activate publish
□ Test preview in browser

Best Practices

1. Generate, Then Customize

Use the generator as a starting point - not as a finished product:

Generator → Scaffold → Customization → Testing → Refinement

2. Define Naming Conventions First

Before you generate, define prefixes:

Z = Customer namespace
I_ = Interface Layer
C_ = Consumption Layer
A_ = Abstract Entity
UI_ = UI Service
_O4 = OData V4

3. Generator for Consistency

Even with manual development: Use the generator once to see the expected structure - then you can build consistently.

4. Use Version Control

Commit directly after each generation - this way you can track changes:

Terminal window
# After generation
git add .
git commit -m "feat: generated RAP BO for FlightBooking"
# After customizations
git commit -m "feat: added validations and UI annotations"

Conclusion

The RAP generators save significant time when creating standard applications. The key is proper use:

  1. Generator for scaffold - Structure and boilerplate
  2. Manual customization - Business logic and UI refinement
  3. Iterative approach - Generate, test, customize

For beginners, it’s still recommended to create all objects manually once - this way you understand what the generator does in the background. After that, you can use the generators effectively.