diff --git a/blog/teaser-posts.md b/blog/teaser-posts.md index 48e8bdab..2e5f7354 100644 --- a/blog/teaser-posts.md +++ b/blog/teaser-posts.md @@ -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. @@ -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. @@ -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. @@ -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. diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index 1a233a42..fa4fd484 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -472,11 +472,10 @@ 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 - @@ -484,7 +483,6 @@ export default defineConfig({ // 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, @@ -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" }, ], }, ], diff --git a/docs/advanced/insights/01-somewhere-on-the-way-to-ui5.md b/docs/advanced/insights/01-somewhere-on-the-way-to-ui5.md index 7e3da19d..a4cae003 100644 --- a/docs/advanced/insights/01-somewhere-on-the-way-to-ui5.md +++ b/docs/advanced/insights/01-somewhere-on-the-way-to-ui5.md @@ -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 diff --git a/docs/advanced/insights/06-the-frontend-that-does-not-know.md b/docs/advanced/insights/06-the-frontend-that-does-not-know.md index c1292079..3fe08eaa 100644 --- a/docs/advanced/insights/06-the-frontend-that-does-not-know.md +++ b/docs/advanced/insights/06-the-frontend-that-does-not-know.md @@ -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. diff --git a/docs/advanced/insights/07-one-service-for-every-app.md b/docs/advanced/insights/07-one-service-for-every-app.md index 7649b3e5..a03d11c7 100644 --- a/docs/advanced/insights/07-one-service-for-every-app.md +++ b/docs/advanced/insights/07-one-service-for-every-app.md @@ -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 diff --git a/docs/advanced/insights/20-cloud-ready-is-a-property-of-your-app.md b/docs/advanced/insights/18-cloud-ready-is-a-property-of-your-app.md similarity index 100% rename from docs/advanced/insights/20-cloud-ready-is-a-property-of-your-app.md rename to docs/advanced/insights/18-cloud-ready-is-a-property-of-your-app.md diff --git a/docs/advanced/insights/19-when-the-api-is-not-released.md b/docs/advanced/insights/19-when-the-api-is-not-released.md new file mode 100644 index 00000000..535ad371 --- /dev/null +++ b/docs/advanced/insights/19-when-the-api-is-not-released.md @@ -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.* diff --git a/docs/advanced/insights/20-on-stack-or-side-by-side.md b/docs/advanced/insights/20-on-stack-or-side-by-side.md new file mode 100644 index 00000000..be21e2ec --- /dev/null +++ b/docs/advanced/insights/20-on-stack-or-side-by-side.md @@ -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! 🦖🦕🦣 diff --git a/docs/advanced/insights/21-one-app-many-systems.md b/docs/advanced/insights/21-one-app-many-systems.md new file mode 100644 index 00000000..08ae872f --- /dev/null +++ b/docs/advanced/insights/21-one-app-many-systems.md @@ -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! 🦖🦕🦣 diff --git a/docs/advanced/insights/18-2300-lines.md b/docs/advanced/insights/22-2300-lines.md similarity index 100% rename from docs/advanced/insights/18-2300-lines.md rename to docs/advanced/insights/22-2300-lines.md diff --git a/docs/advanced/insights/21-abap-on-the-web.md b/docs/advanced/insights/23-abap-on-the-web.md similarity index 97% rename from docs/advanced/insights/21-abap-on-the-web.md rename to docs/advanced/insights/23-abap-on-the-web.md index 9e34843b..aa1789c5 100644 --- a/docs/advanced/insights/21-abap-on-the-web.md +++ b/docs/advanced/insights/23-abap-on-the-web.md @@ -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. diff --git a/docs/advanced/insights/19-where-the-line-is.md b/docs/advanced/insights/24-where-the-line-is.md similarity index 94% rename from docs/advanced/insights/19-where-the-line-is.md rename to docs/advanced/insights/24-where-the-line-is.md index e2570e6e..c84fd9d8 100644 --- a/docs/advanced/insights/19-where-the-line-is.md +++ b/docs/advanced/insights/24-where-the-line-is.md @@ -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 diff --git a/docs/advanced/insights/22-where-the-view-lives.md b/docs/advanced/insights/25-where-the-view-lives.md similarity index 100% rename from docs/advanced/insights/22-where-the-view-lives.md rename to docs/advanced/insights/25-where-the-view-lives.md diff --git a/docs/advanced/insights/23-rap-or-abap2ui5.md b/docs/advanced/insights/26-rap-or-abap2ui5.md similarity index 71% rename from docs/advanced/insights/23-rap-or-abap2ui5.md rename to docs/advanced/insights/26-rap-or-abap2ui5.md index de20418b..5baa9499 100644 --- a/docs/advanced/insights/23-rap-or-abap2ui5.md +++ b/docs/advanced/insights/26-rap-or-abap2ui5.md @@ -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 diff --git a/docs/advanced/insights/24-freestyle-or-abap2ui5.md b/docs/advanced/insights/27-freestyle-or-abap2ui5.md similarity index 69% rename from docs/advanced/insights/24-freestyle-or-abap2ui5.md rename to docs/advanced/insights/27-freestyle-or-abap2ui5.md index 5017e15e..c30ef9aa 100644 --- a/docs/advanced/insights/24-freestyle-or-abap2ui5.md +++ b/docs/advanced/insights/27-freestyle-or-abap2ui5.md @@ -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 diff --git a/docs/advanced/insights/25-low-code-or-abap2ui5.md b/docs/advanced/insights/28-low-code-or-abap2ui5.md similarity index 71% rename from docs/advanced/insights/25-low-code-or-abap2ui5.md rename to docs/advanced/insights/28-low-code-or-abap2ui5.md index f02cb80e..d1c75289 100644 --- a/docs/advanced/insights/25-low-code-or-abap2ui5.md +++ b/docs/advanced/insights/28-low-code-or-abap2ui5.md @@ -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 — diff --git a/docs/advanced/use_cases.md b/docs/advanced/use_cases.md deleted file mode 100644 index 171d983a..00000000 --- a/docs/advanced/use_cases.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -outline: [2, 4] ---- -# Use Cases - -abap2UI5 fits many contexts, whether you work in a cloud-ready environment or with classic ABAP. - -The sections below follow SAP's extensibility model. **On-stack** means the app runs inside your SAP system; **side-by-side** means it runs on a separate system (for example the SAP BTP ABAP Environment) and calls your SAP system remotely. Within each approach, SAP grades an extension by how "clean core" it is. Until 2025 that grade was the three-tier model; 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 replaced the tiers with four **clean core levels**, and SAP S/4HANA 2025 ships with them: - -| Level | Language version | What the extension uses | Clean core | -| --- | --- | --- | --- | -| **A** | ABAP for Cloud Development | released APIs only — on-stack, side-by-side or both | 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 that are neither released nor classified | conditionally — re-check before every upgrade | -| **D** | Standard ABAP | modifications, implicit enhancements, objects SAP marks as no API | no | - -The framework itself is Level A: it is written in ABAP for Cloud Development and uses released APIs only. Which level an *app* reaches depends on what the app calls, not on abap2UI5. - -::: tip Coming from the three-tier model -Tier 1 is Level A. Tier 2 was never a layer of its own — its wrappers still exist, written in Standard ABAP and released for ABAP Cloud, and an app that calls one stays Level A. Tier 3 is now split into Levels B, C and D by what it touches. Code written under the tier model does not need to be migrated; the ABAP Test Cockpit and the Cloudification Repository Viewer tell you which level an object lands on. -::: - -## On-Stack Extension - -### Level A -Build apps in ABAP for Cloud Development, using released APIs only. They are clean core, cloud-ready and upgrade-stable, and they run unchanged on S/4HANA Public Cloud, Private Cloud and on-premise: -![Level A on-stack extension: abap2UI5 and the apps run inside S/4HANA and use released APIs only](/advanced/use_cases/on_stack_level_a.svg){ width=60% } - -### Level A with a Wrapper -If an API you need is not released, wrap it: a class in Standard ABAP that calls the classic API and is released for ABAP for Cloud Development. The wrapper is graded on its own — Level B as long as it sticks to classic APIs — and the abap2UI5 app that calls it stays Level A: -![Level A on-stack extension with a wrapper: the apps stay in ABAP for Cloud Development and reach a classic API through a wrapper written in Standard ABAP](/advanced/use_cases/on_stack_wrapper.svg){ width=60% } - -### Levels B to D -On S/4HANA Private Cloud and on-premise you can also write the app itself in Standard ABAP, and on releases that do not know ABAP for Cloud Development yet it is the only option. Level B uses classic APIs and frameworks; Level C reaches SAP-internal objects and has to be re-checked before every upgrade; Level D — modifications and implicit enhancements — is not clean core. The framework stays Level A either way, so moving an app up a level later means changing what it calls, not how it renders: -![On-stack extension on Levels B to D: 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% } - -## Side-by-Side Extension - -### Level A -Build apps on the SAP BTP ABAP Environment, separate from your S/4 system's lifecycle, with remote calls to released APIs only — OData, released RFC or SOAP services. Everything on the BTP side is Level A by construction, and it works with S/4HANA Public Cloud too: -![Level A side-by-side extension: abap2UI5 and 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% } - -### With a Custom Service -When the released remote APIs do not cover what you need, expose your own service on the S/4 system. The BTP side stays Level A; the service on the S/4 side is graded by what it uses — Level B if it stays with classic APIs: -![Side-by-side extension with a custom service: 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% } - -## Software as a Service (SaaS) -With a Level A side-by-side extension, you can connect a single abap2UI5 app to multiple S/4 systems. Use the same abap2UI5 code across customer tenants and remote systems for a real SaaS setup: -![SaaS architecture: 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% } - -## Further Reading -- [Why Clean Core matters — 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), where SAP introduces the four levels -- [ABAP Extensibility Guide — Clean Core for SAP S/4HANA Cloud, August 2025 update](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), the technical rules behind each level -- [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), on grading existing custom code -- [Use Cases of abap2UI5 — an Overview](https://www.linkedin.com/pulse/use-cases-abap2ui5-overview-abap2ui5-udbde/), the background article with additional scenarios, still in the vocabulary of the tier model diff --git a/docs/get_started/about.md b/docs/get_started/about.md index 7ad5df76..f15713f1 100644 --- a/docs/get_started/about.md +++ b/docs/get_started/about.md @@ -95,7 +95,7 @@ It is deliberately not built for everything. Three cases are a poor fit, and kno - **Offline use and complex client-side behaviour.** The browser renders; it does not hold the application. - **Teams that work strictly separately.** The app is one ABAP class — that is the point, and it means there is no frontend project for a frontend team to own. -→ *See [Use Cases](/advanced/use_cases) for the on-stack, side-by-side and SaaS scenarios* +→ *See [On-Stack or Side-by-Side](/advanced/insights/20-on-stack-or-side-by-side) and [One App, Many Systems](/advanced/insights/21-one-app-many-systems) for the deployment scenarios* ## Compatibility