SAP RAP: The ABAP RESTful Application Programming Model in Practice
RAP replaces BOPF and classic ABAP OO for transactional development. This post explains the BO → CDS → OData → Fiori Elements stack, managed vs. unmanaged scenarios, draft handling, and when RAP is — and isn't — the right choice.
If you are still writing transactional ABAP using classical ABAP Objects with manual locking, manual number assignment, and hand-rolled BAPI surfaces, you are building technical debt that S/4HANA’s architecture is explicitly designed to phase out. The ABAP RESTful Application Programming Model (RAP) is the replacement — not just for BOPF, but for the entire pattern of on-stack transactional development. This post explains what RAP actually is at the code level, when to use managed versus unmanaged scenarios, how draft handling works, and where CAP becomes the better choice.
What RAP replaces and why the replacement matters
The BOPF era
The Business Object Processing Framework (BOPF) was SAP’s previous standard for structured transactional object development. It provided a runtime for business object nodes, associations, and actions, and was the foundation for some S/4HANA standard objects. BOPF worked — but it was primarily a design-time framework for SAP’s own development teams, not a productivity model for customer and partner developers. Its learning curve was steep, tooling support in Eclipse was limited, and the number of artefacts required for even a simple business object was high.
Why RAP is different
RAP is contract-first and CDS-centric. The business object’s data model is a CDS entity. The behaviour — what the object can do, who can change it, what validations apply — is declared in a behaviour definition file (.bdef). The OData service is generated from the CDS view. The Fiori Elements UI is generated from annotations on the CDS view. The developer writes ABAP only in the behaviour implementation class — the boilerplate is gone.
This stack means a single CDS entity with annotations can produce a working, draft-enabled, Fiori Elements application with create/update/delete, field-level authorisation checks, and an OData V4 service — with far less code than the equivalent BOPF or classical MVC approach.
The RAP layer stack
graph TD
FE[Fiori Elements UI — auto-generated from UI annotations]
OD[OData V4 Service Binding — SRVB]
SRV[Service Definition — SRVD]
BDEF[Behavior Definition — .bdef]
BIMP[Behavior Implementation Class — ABAP]
CDS_P[CDS Projection View — alias, annotations]
CDS_I[CDS Interface View — data model, joins]
DB[(Database Tables / Released CDS Views)]
FE -->|OData V4 protocol| OD
OD --> SRV
SRV --> CDS_P
CDS_P --> BDEF
BDEF --> BIMP
CDS_P --> CDS_I
CDS_I --> DB
Each layer has a distinct responsibility:
- CDS Interface View (
I_naming convention by SAP standard): the base data model. Defines the fields, joins, and calculated fields. No Fiori annotations here — this is reusable across contexts. - CDS Projection View (
C_naming): adds the UI-specific annotations (@UI.lineItem,@UI.selectionField,@Search.searchable) and controls which fields and actions are exposed to which service context. - Behavior Definition: declares the create/update/delete capabilities, field properties (mandatory, read-only, hidden), validations, determinations, actions, and draft table associations.
- Behavior Implementation Class: the ABAP where business logic lives — validation methods, determination methods, action handlers. This is the only ABAP you write for a managed BO.
- Service Definition: names the root entity and any associated entities exposed via OData.
- Service Binding: binds the service definition to a protocol (OData V2 or V4) and endpoint type (UI, Web API). This is what you activate to produce a callable service URL.
Managed vs. unmanaged scenarios
Managed (use this by default)
In the managed scenario, the RAP framework handles the CRUD operations on the underlying tables. You declare which database table backs each entity in the behavior definition, and the framework generates the persistence layer:
managed implementation in class zbp_my_order unique;
define behavior for ZI_MyOrder alias Order
persistent table zmy_order
lock master
authorization master ( instance )
etag master LastChangedAt
{
field ( numbering : managed, readonly ) OrderUUID;
field ( readonly ) CreatedAt, CreatedBy, LastChangedAt, LastChangedBy;
create;
update;
delete;
draft table zmy_order_d;
with draft;
validation validateOrderDate on save { field OrderDate; }
determination setDefaultStatus on modify { field OrderStatus; }
action confirmOrder result [1] $self;
mapping from zmy_order
{
OrderUUID = order_uuid;
OrderDate = order_date;
OrderStatus = order_status;
CreatedAt = created_at;
CreatedBy = created_by;
}
}
The framework generates CREATE, UPDATE, DELETE, LOCK, and ETAG handling automatically. You implement only the named validation and determination methods in the implementation class.
Unmanaged (use when wrapping legacy logic)
In the unmanaged scenario, you implement all persistence yourself — typically because you are wrapping an existing BAPI, FM, or legacy persistence layer that cannot be replaced immediately. The interaction protocol (OData → RAP framework → your ABAP) is identical from the client’s perspective, but every CRUD handler must be coded:
unmanaged implementation in class zbp_my_legacy_order unique;
define behavior for ZI_MyLegacyOrder alias Order
lock master
authorization master ( global )
{
create;
update;
delete;
validation validateBusinessRules on save { create; update; }
}
Unmanaged is the right migration path when you have existing functional specifications and business logic in FM modules that would take too long to rewrite. It lets you present a clean RAP surface to consumers while the internals are still being modernised.
Draft handling
Draft is one of the most practically valuable RAP features and the one most often left out of early implementations. A draft-enabled BO persists incomplete object state to a draft table, allowing users to save partial work, hand off to another user, or return to a form later — without posting to the active database.
Activating draft requires:
- A draft table (
draft table zmy_order_d) — a DB table with the same fields as the active table plus draft administration fields - The
with draftkeyword in the behavior definition - The service binding type set to OData V4 UI (draft is not supported on V2 bindings)
- The Fiori Elements app to use a draft-aware List Report / Object Page template
From the implementation perspective, draft introduces a two-phase save: the user interacts with the draft instance (no business validations yet), and validations run on save_modified when the user explicitly activates the draft. Determinations can run in both phases.
For any user-facing transactional BO — anything an end user will edit in a Fiori form — draft should be the default. The user experience without draft (immediate save-or-cancel semantics) is significantly worse and leads to partial-data corruption if sessions are interrupted.
Field-level features in the behavior definition
RAP’s behavior definition provides field-level control that used to require significant custom code:
field ( readonly : create ) OrderNumber; " Set by system on create, not editable
field ( mandatory ) OrderDate; " Client-side and server-side mandatory
field ( readonly ) TotalAmount; " Derived field, never editable
field ( features : instance ) DeliveryDate; " Dynamic — controlled per instance
Dynamic features (features : instance) are controlled by a get_instance_features method in the implementation class, which returns a structure indicating whether each field is read-only, mandatory, or hidden for a given object instance. This replaces the custom screen logic that in classical ABAP lived in screen flow events.
When to choose RAP vs. CAP
The choice is architectural, not preference-based:
Choose RAP when:
- The application is transactional and needs to run on-stack in S/4HANA
- You need tight integration with S/4HANA’s locking, authorisation, and change document framework
- The data model is primarily S/4HANA tables and released CDS views
- Users access the application via Fiori launchpad in the S/4HANA system
Choose CAP (on BTP) when:
- The application is a side-by-side extension that must remain decoupled from S/4HANA upgrades
- The data model spans S/4HANA and non-SAP data sources
- The team is primarily Node.js or Java-skilled and ABAP expertise is limited
- The application needs to work across multiple SAP backend systems or tenants
- Multi-tenancy is a requirement (ISV scenario)
The clean core principle says: if it can be CAP, it should be CAP. But there are legitimate on-stack scenarios — particularly complex transactional processes deeply integrated with S/4HANA’s locking and authorisation model — where RAP on-stack is the better engineering choice.
RAP in the context of S/4HANA migration
For migration projects, RAP matters in two ways. First, existing BOPF-based custom objects need a migration path — for new development, RAP is the target. For existing BOPF objects, a conversion to RAP is typically worthwhile if the object will be significantly modified anyway; otherwise, BOPF remains supported in the near term.
Second, the s4ready.ai A6 RAP Builder agent generates RAP BO scaffolding — CDS interface view, projection view, behavior definition, behavior implementation class stub, service definition, and service binding — from a business object specification. This reduces the initial setup effort for a greenfield RAP BO from several hours to minutes, leaving developers to focus on the actual business logic.
SAP, ABAP, RAP, CDS, OData, Fiori Elements, BOPF, SAP BTP, and related marks are trademarks of SAP SE.
Keep reading
ABAP in VS Code is Now GA: What It Means for Your S/4HANA Migration and Clean Core Journey
SAP's ABAP Development Tools for VS Code are now generally available — a ground-up redesign built on a new ABAP Language Server, with a built-in MCP Server for AI agents. Here's what shipped, why the ABAP Cloud-only model enforces Clean Core by design, and what it means for your S/4HANA migration.
Read more →VS Code ADT vs Eclipse ADT: Complete Feature Comparison (2026)
SAP officially released ABAP Development Tools for VS Code in June 2026. Here's an honest, feature-by-feature comparison of VS Code ADT vs Eclipse ADT — and which one you should use.
Read more →abapGit: Version Control for ABAP Teams and How to Build a Real CI/CD Pipeline
ABAP development without version control has been the industry norm for decades. abapGit changes that — here is how it works, how to structure branching for ABAP teams, and how s4ready uses abapGit repos for automated code scanning.
Read more →