Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions blog/teaser-posts.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ Plain text — LinkedIn renders no markdown.
>
> #ABAP #SAP #UI5

## The Frontend That Does Not Know What It Shows
## The Frontend Knows Nothing

Plain text — LinkedIn renders no markdown.

Expand All @@ -139,7 +139,7 @@ Plain text — LinkedIn renders no markdown.
>
> #ABAP #SAP #UI5

## One Service for Every App
## The Same Service for Every App

Plain text — LinkedIn renders no markdown.

Expand Down Expand Up @@ -399,7 +399,7 @@ Plain text — LinkedIn renders no markdown.
>
> #ABAP #SAP #UI5

## Where the Line Is
## What It Does Not Do

Plain text — LinkedIn renders no markdown.

Expand Down Expand Up @@ -443,7 +443,7 @@ Plain text — LinkedIn renders no markdown.
>
> #ABAP #SAP #UI5

## Twenty-Five Years of ABAP on the Web
## From ITS to abap2UI5

Plain text — LinkedIn renders no markdown.

Expand Down
63 changes: 32 additions & 31 deletions docs/.vitepress/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -472,19 +472,17 @@ export default defineConfig({
// entries and Technical Insight - the last of them - is visible
// without scrolling, which it was not when it was the twelfth.
//
// Use Cases stays loose at the top: it moved out of Getting
// Started on purpose, because it answers a question a newcomer
// does not have yet, and on the entry page it reads as a required
// step. It is the one that says what this section is for, so it is
// what a reader opening it meets first.
// Use Cases is gone from this section: it was converted into the
// Technical Insights articles below - the clean core levels and the
// wrapper, on-stack against side-by-side, and one app serving many
// systems - and the page it used to be is in the git history.
//
// Add-ons stood next to it and is now under Resources. Every other
// page in this section teaches something you do to your own app -
// downport it, run it off-stack, extend it, wire it to something.
// Add-ons teaches nothing: it is a list of what other people
// published, which is the same kind of page as References and Who
// Uses abap2UI5?. The pages that need it still link it by name.
{ text: "Use Cases", link: "/advanced/use_cases" },
{
text: "Extensibility",
collapsed: true,
Expand Down Expand Up @@ -590,31 +588,34 @@ export default defineConfig({
link: "/advanced/insights/01-somewhere-on-the-way-to-ui5",
collapsed: true,
items: [
{ text: "Somewhere on the Way to UI5, We Lost RTTS", link: "/advanced/insights/01-somewhere-on-the-way-to-ui5" },
{ text: "abap2UI5 is not a Programming Model", link: "/advanced/insights/02-not-a-programming-model" },
{ text: "The Cost of a Screen", link: "/advanced/insights/03-the-cost-of-a-screen" },
{ text: "No Annotation in Between", link: "/advanced/insights/04-no-annotation-in-between" },
{ text: "UI5 Over-the-Wire", link: "/advanced/insights/05-ui5-over-the-wire" },
{ text: "The Frontend That Does Not Know What It Shows", link: "/advanced/insights/06-the-frontend-that-does-not-know" },
{ text: "One Service for Every App", link: "/advanced/insights/07-one-service-for-every-app" },
{ text: "Only the Changed Part", link: "/advanced/insights/08-only-the-changed-part" },
{ text: "PUBLIC Means Persisted", link: "/advanced/insights/09-public-means-persisted" },
{ text: "Swapping the View at Runtime", link: "/advanced/insights/10-swapping-the-view-at-runtime" },
{ text: "index.html Lives in a String", link: "/advanced/insights/11-index-html-lives-in-a-string" },
{ text: "Where Your Own JavaScript Goes", link: "/advanced/insights/12-where-your-own-javascript-goes" },
{ text: "Four Verbs", link: "/advanced/insights/13-four-verbs" },
{ text: "The Class That Runs", link: "/advanced/insights/14-the-class-that-runs" },
{ text: "Where the Selection Screen Went", link: "/advanced/insights/15-where-the-selection-screen-went" },
{ text: "No Cache, No Deploy, Any IDE", link: "/advanced/insights/16-no-cache-no-deploy-any-ide" },
{ text: "One Codebase, 7.02 to ABAP Cloud", link: "/advanced/insights/17-one-codebase-702-to-abap-cloud" },
{ text: "2,300 Lines", link: "/advanced/insights/18-2300-lines" },
{ text: "Where the Line Is", link: "/advanced/insights/19-where-the-line-is" },
{ text: "Cloud-Ready Is a Property of Your App", link: "/advanced/insights/20-cloud-ready-is-a-property-of-your-app" },
{ text: "Twenty-Five Years of ABAP on the Web", link: "/advanced/insights/21-abap-on-the-web" },
{ text: "Where the View Lives", link: "/advanced/insights/22-where-the-view-lives" },
{ text: "RAP or abap2UI5 — When to Use Which", link: "/advanced/insights/23-rap-or-abap2ui5" },
{ text: "UI5 Freestyle or abap2UI5 — When to Use Which", link: "/advanced/insights/24-freestyle-or-abap2ui5" },
{ text: "Low-Code or abap2UI5 — When to Use Which", link: "/advanced/insights/25-low-code-or-abap2ui5" },
{ text: "#1 Somewhere on the Way to UI5, We Lost RTTS", link: "/advanced/insights/01-somewhere-on-the-way-to-ui5" },
{ text: "#2 abap2UI5 is not a Programming Model", link: "/advanced/insights/02-not-a-programming-model" },
{ text: "#3 The Cost of a Screen", link: "/advanced/insights/03-the-cost-of-a-screen" },
{ text: "#4 No Annotation in Between", link: "/advanced/insights/04-no-annotation-in-between" },
{ text: "#5 UI5 Over-the-Wire", link: "/advanced/insights/05-ui5-over-the-wire" },
{ text: "#6 The Frontend Knows Nothing", link: "/advanced/insights/06-the-frontend-that-does-not-know" },
{ text: "#7 The Same Service for Every App", link: "/advanced/insights/07-one-service-for-every-app" },
{ text: "#8 Only the Changed Part", link: "/advanced/insights/08-only-the-changed-part" },
{ text: "#9 PUBLIC Means Persisted", link: "/advanced/insights/09-public-means-persisted" },
{ text: "#10 Swapping the View at Runtime", link: "/advanced/insights/10-swapping-the-view-at-runtime" },
{ text: "#11 index.html Lives in a String", link: "/advanced/insights/11-index-html-lives-in-a-string" },
{ text: "#12 Where Your Own JavaScript Goes", link: "/advanced/insights/12-where-your-own-javascript-goes" },
{ text: "#13 Four Verbs", link: "/advanced/insights/13-four-verbs" },
{ text: "#14 The Class That Runs", link: "/advanced/insights/14-the-class-that-runs" },
{ text: "#15 Where the Selection Screen Went", link: "/advanced/insights/15-where-the-selection-screen-went" },
{ text: "#16 No Cache, No Deploy, Any IDE", link: "/advanced/insights/16-no-cache-no-deploy-any-ide" },
{ text: "#17 One Codebase, 7.02 to ABAP Cloud", link: "/advanced/insights/17-one-codebase-702-to-abap-cloud" },
{ text: "#18 Cloud-Ready Is a Property of Your App", link: "/advanced/insights/18-cloud-ready-is-a-property-of-your-app" },
{ text: "#19 When the API Is Not Released", link: "/advanced/insights/19-when-the-api-is-not-released" },
{ text: "#20 On-Stack or Side-by-Side", link: "/advanced/insights/20-on-stack-or-side-by-side" },
{ text: "#21 One App, Many Systems", link: "/advanced/insights/21-one-app-many-systems" },
{ text: "#22 2,300 Lines", link: "/advanced/insights/22-2300-lines" },
{ text: "#23 From ITS to abap2UI5", link: "/advanced/insights/23-abap-on-the-web" },
{ text: "#24 What It Does Not Do", link: "/advanced/insights/24-where-the-line-is" },
{ text: "#25 Where the View Lives", link: "/advanced/insights/25-where-the-view-lives" },
{ text: "#26 RAP or abap2UI5 — When to Use Which", link: "/advanced/insights/26-rap-or-abap2ui5" },
{ text: "#27 UI5 Freestyle or abap2UI5 — When to Use Which", link: "/advanced/insights/27-freestyle-or-abap2ui5" },
{ text: "#28 Low-Code or abap2UI5 — When to Use Which", link: "/advanced/insights/28-low-code-or-abap2ui5" },
],
},
],
Expand Down
1 change: 0 additions & 1 deletion docs/advanced/insights/01-somewhere-on-the-way-to-ui5.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Somewhere on the Way to UI5, We Lost RTTS

*abap2UI5 Know-How #1 — scheduled for Tuesday, 25 August 2026*

![The dinosaur at a classic ALV grid, the sheep and the sloth at the same table
rendered in UI5, with cl_abap_structdescr->get_components( ) bridging the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# The Frontend That Does Not Know What It Shows
# The Frontend Knows Nothing

The first GET request delivers a UI5 app to the browser. It is worth asking
what is actually in it.
Expand Down
2 changes: 1 addition & 1 deletion docs/advanced/insights/07-one-service-for-every-app.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# One Service for Every App
# The Same Service for Every App

Count what a screen usually costs in backend artefacts. A CDS view or two, a
service definition, a service binding, a behavior definition and its
Expand Down
56 changes: 56 additions & 0 deletions docs/advanced/insights/19-when-the-api-is-not-released.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# When the API Is Not Released

SAP grades an extension, and since August 2025 it does so on four **clean core
levels**:

| Level | Language version | What the extension uses | Clean core |
|---|---|---|---|
| **A** | ABAP for Cloud Development | released APIs only | yes, and upgrade-stable |
| **B** | Standard ABAP | classic APIs and the frameworks SAP recommends for them: BAdIs, user exits, ALV, SAP GUI | yes, with less upgrade stability |
| **C** | Standard ABAP | SAP-internal objects, neither released nor classified | conditionally — re-check before every upgrade |
| **D** | Standard ABAP | modifications, implicit enhancements, objects SAP marks as no API | no |

They replaced the three-tier model, and nothing written under the tiers has to
be migrated: tier 1 is Level A, tier 2 was never a layer of its own — its
wrappers still exist and an app calling one stays Level A — and tier 3 is split
into B, C and D by what it touches. The ABAP Test Cockpit and the Cloudification
Repository Viewer say which level an object lands on.

abap2UI5 is Level A. It is written in ABAP for Cloud Development and calls
released APIs only.

That says nothing about the app. Which level an app reaches is decided by what
the app calls, and a screen built on a released API is Level A whether it
renders through abap2UI5 or anything else.

Which leaves the case that actually comes up: the API you need is not released.

The move is a wrapper. A class in Standard ABAP that calls the classic API and
is itself released for ABAP for Cloud Development. It is graded on its own — B,
as long as it stays with classic APIs — and the app calling it stays A.

![The app stays in ABAP for Cloud Development and reaches a classic API through a wrapper written in Standard ABAP](/advanced/use_cases/on_stack_wrapper.svg){ width=60% }

The value of that is not the grade. It is that the part of the system which is
not upgrade-stable has a name, a size and a boundary. One class to re-check when
SAP changes the classic API underneath it, instead of a search through every app
that ever touched it.

On S/4HANA Private Cloud and on-premise the app itself may also be Standard
ABAP, and on releases that do not know ABAP for Cloud Development yet that is
the only option. The framework stays Level A either way, so moving an app up a
level later means changing what it calls, not how it renders:

![Apps written in Standard ABAP call classic APIs or SAP-internal objects, while abap2UI5 itself stays Level A](/advanced/use_cases/on_stack_level_b.svg){ width=60% }

**A wrapper does not make the dependency clean. It makes it findable.**

Happy ABAPing! 🦖🦕🦣

*The levels are SAP's, from the
[Clean Core Extensibility white paper](https://community.sap.com/t5/technology-blog-posts-by-sap/why-clean-core-matters-get-some-insights-into-our-brand-new-extensibility/ba-p/14163750)
of August 2025; the
[ABAP Extensibility Guide](https://community.sap.com/t5/technology-blog-posts-by-sap/abap-extensibility-guide-clean-core-for-sap-s-4hana-cloud-august-2025/ba-p/14175399)
carries the technical rules behind each one, and
[Clean Core maturity and the new extensibility levels](https://community.sap.com/t5/technology-blog-posts-by-sap/clean-core-maturity-and-the-new-extensibility-levels/ba-p/14293974)
covers grading code that already exists.*
39 changes: 39 additions & 0 deletions docs/advanced/insights/20-on-stack-or-side-by-side.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# On-Stack or Side-by-Side

Two places to run an abap2UI5 app, and the choice is about lifecycles rather
than about code.

**On-stack** means the app runs inside the SAP system. It reads the data
directly, there is no remote call and no second system to operate, and
deployment is the transport you already use. Built on released APIs it runs
unchanged on S/4HANA Public Cloud, Private Cloud and on-premise. What it
inherits is that system's lifecycle: its release, its upgrade window, its
maintenance slots.

![abap2UI5 and the apps run inside S/4HANA and use released APIs only](/advanced/use_cases/on_stack_level_a.svg){ width=60% }

**Side-by-side** means the app runs on the SAP BTP ABAP Environment and calls
the S/4 system remotely — released OData, RFC or SOAP services. Everything on
the BTP side is Level A by construction, and it works against S/4HANA Public
Cloud, where on-stack custom code is not an option.

![The apps run on the SAP BTP ABAP Environment and call released remote APIs of S/4HANA](/advanced/use_cases/side_by_side_level_a.svg){ width=60% }

The separation is the point. A side-by-side app is released, upgraded and
restarted on its own schedule, and the S/4 system does not have to agree. Where
a release cycle is the actual constraint — a locked system, a long change
window, a team that cannot get a transport through this quarter — that is worth
more than the directness on-stack gives.

The cost is equally plain: a remote call is slower than a local read, the
released remote APIs are narrower than what a local `SELECT` can reach, and
there is a second system to run. When the released remote APIs do not cover the
case, a service on the S/4 side closes the gap and is graded on its own — the
BTP side stays Level A:

![The apps on SAP BTP stay Level A and call a service on S/4HANA that wraps classic APIs in Standard ABAP](/advanced/use_cases/side_by_side_custom_service.svg){ width=60% }

**Neither choice touches the app class. The same code renders in both places —
only what it reads changes.**

Happy ABAPing! 🦖🦕🦣
34 changes: 34 additions & 0 deletions docs/advanced/insights/21-one-app-many-systems.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# One App, Many Systems

A side-by-side app already runs outside the system it serves. Which raises a
question with a more interesting answer than it looks: how many systems can it
serve?

More than one. The app lives on the SAP BTP ABAP Environment and reaches each
S/4 system through its released APIs, so the connection is configuration rather
than code.

![One abap2UI5 app on the SAP BTP ABAP Environment serves several S/4HANA systems through their released APIs](/advanced/use_cases/saas.svg){ width=60% }

That is a real SaaS shape, in ABAP. One codebase, deployed once, serving several
customer tenants — each with its own system, its own data and its own release,
none of them needing anything installed. Nobody transports into a customer
system, nobody schedules a downtime there, and a fix reaches every tenant at
once.

It works because of what the earlier articles already established rather than
because of anything added for it. The frontend is a shell that renders whatever
arrives, so it does not care which system produced it. The app is one class with
no artefacts beside it, so there is nothing per-tenant to deploy. And the state
that makes a roundtrip work travels in the request, so no server holds a session
belonging to one customer.

The limits are the ones the shape implies. Every tenant needs its released APIs
reachable, latency is now on the wire, and the tenant's data boundary is
something the app has to enforce rather than something the system enforces for
it — one app now sees several customers.

**A framework with nothing to install per system is a framework that can serve
systems it was never installed on.**

Happy ABAPing! 🦖🦕🦣
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Twenty-Five Years of ABAP on the Web
# From ITS to abap2UI5

Worth laying out end to end, because the shape of it is not what most people
remember.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Where the Line Is
# What It Does Not Do

Eighteen articles is enough credit to say what this does not do.
Before choosing anything, the part that is easiest to leave out: what this
does not do.

**Offline is out.** Every event asks the server what happens next. Take the
server away and there is no app left — not a degraded one, none. An app that has
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@
The honest answer is that most systems end up with both, and the question is
never "which framework" but "which one for this screen".

| | RAP with Fiori Elements | abap2UI5 |
|---|---|---|
| **Backend** | CDS views, behavior definitions, OData V4 | ABAP classes producing an XML view and a JSON model |
| **Frontend** | a Fiori Elements app per service | one static UI5 shell, shared by every app |
| **UI definition** | UI annotations on CDS | XML views written in ABAP |
| **Data model** | fixed at design time in CDS | design time, or at runtime from internal tables |
| **Drafts** | RAP drafts, on the model | serialization, on the app |
| **Communication** | OData V4 — metadata, entities, actions | HTTP, two strings per request |
| **Deployment** | frontend and backend transported separately | activating the class |

Here is the split that holds up in practice.

**Reach for RAP when the behaviour matters more than the screen.** A
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ Both give full access to the UI5 control library. Neither limits what a screen
can contain. So the choice is not about what is possible — it is about where the
work happens and who does it.

| | UI5 Freestyle | abap2UI5 |
|---|---|---|
| **Backend** | OData or REST services, loosely coupled | ABAP classes producing an XML view and a JSON model |
| **Frontend** | your own UI5 app: JavaScript, XML views, controllers | one static UI5 shell, shared by every app |
| **UI definition** | XML views in the frontend project | XML views written in ABAP |
| **Where the logic runs** | split between controller and backend | backend only |
| **Client state** | held in the browser between roundtrips | travels with the request |
| **Tooling** | Business Application Studio, a frontend build | any ABAP IDE, no extra toolchain |
| **Deployment** | build and deploy the frontend, plus the backend | activating the class |

**Reach for UI5 Freestyle when the browser has to be smart.** Anything that must
keep working offline, anything where interesting state lives on the client
between roundtrips, anything genuinely interactive — drag and drop across a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ hardly be further apart — a visual designer on a licensed platform, or plain
ABAP in an open-source framework — so the choice is unusually clear once the
right question is asked.

| | Low-code platform | abap2UI5 |
|---|---|---|
| **App definition** | visual designer, platform-specific format | ABAP classes, written in any ABAP IDE |
| **App storage** | the platform's repository | your system, like any other development object |
| **Versioning, transport** | platform mechanisms | CTS or abapGit |
| **Testing** | platform tooling | ABAP Unit, plus the project's linter |
| **License** | commercial, typically per end user | MIT, unlimited users |
| **Installation** | platform or add-on, plus client components | one abapGit pull |
| **Release coverage** | what the vendor supports | NW 7.02 to ABAP Cloud |
| **Exit path** | apps exist in the platform's format | apps stay plain ABAP classes in your system |

**Reach for a low-code platform when the requirement is outside code.**
Offline-capable native mobile apps, where local storage and synchronisation
are the whole point. A bundled suite — workflow, API management, a portal —
Expand Down
Loading