https://raw.githubusercontent.com/ajmaradiaga/feeds/main/scmt/topics/ABAP-Development-blog-posts.xmlSAP Community - ABAP Development2026-07-24T20:00:03.774661+00:00python-feedgenABAP Development blog posts in SAP Communityhttps://community.sap.com/t5/abap-blog-posts/debugging-sap-smartforms-smart-tip-to-debug-sap-smartforms/ba-p/14323346Debugging SAP Smartforms : Smart tip to debug SAP smartforms2026-07-05T07:07:11.154000+02:00Surendra_Karmahttps://community.sap.com/t5/user/viewprofilepage/user-id/870700<P><SPAN><STRONG>Introduction:</STRONG><BR />In SAP, Forms vary from SAPscript to Smartforms, Adobe forms, Form templates and Form fragments. Smartforms are quite useful method since 1998 and companies are keeping it frequently till date. But in some situations, any smartform printing starts raising an exception, not giving expected print, giving dump suddenly and we'll keep debugging to find exact NODE for the dump. Here, I would like to share a smart tip to get to the affected NODE within a couple of minutes.</SPAN></P><P><STRONG>Smart Tip:<BR /></STRONG>I have been debugging ABAP codes from long back whether its standard or custom code. And finally, I had a spot which can show you exactly which NODE in SMARTFORM is having the issue. And I would like to share this knowledge which can save your time and complete the deliveries on time.</P><P>Program: SAPLSTXBC or Function Group: STXBC</P><P>Include: LSTXBCFDC</P><P>Subroutine/Perform: CALLBACK</P><P><span class="lia-inline-image-display-wrapper lia-image-align-left" image-alt="Screenshot 2026-02-07 115807.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/369742iF9C5189CD75A01EF/image-size/large?v=v2&px=999" role="button" title="Screenshot 2026-02-07 115807.png" alt="Screenshot 2026-02-07 115807.png" /></span></P><P><SPAN>Here, you just have to pay attention after which NODE your smartform is not giving print or raising an exception when calling from driver program. And that is the NODE which has an issue.</SPAN></P><P><SPAN><STRONG>Best Real-time use case:</STRONG><BR />In migration projects, a few of the complex smartforms have still not been migrated to Adobe Forms while migrating from ECC to S/4 HANA. I</SPAN>n such cases, smartforms are either not giving prints or some field mapping has been changed in new system. Or some standard texts do not exist, or some graphics do not exist, not giving expected print, raising an exception or giving dumps. Sometimes, in other scenarios we also have to debug and find the NODE which is causing the issue.</P><P>Thanks for reading, Comments are always welcome.<BR />Happy Learning!</P>2026-07-05T07:07:11.154000+02:00https://community.sap.com/t5/artificial-intelligence-blogs-posts/how-to-connect-claude-code-to-abap-with-zero-config-mcp/ba-p/14426854How to Connect Claude Code to ABAP with Zero-Config MCP2026-07-05T13:39:48.252000+02:00Nibeditahttps://community.sap.com/t5/user/viewprofilepage/user-id/42141<DIV><SPAN>Before We Start - What This Post Deliberately Skips</SPAN></DIV>
<DIV><SPAN>-</SPAN><SPAN> What is Claude Code, and what are the available models?</SPAN></DIV>
<DIV><SPAN>-</SPAN><SPAN> What is MCP (Model Context Protocol) and how it works conceptually?</SPAN></DIV>
<DIV><SPAN>-</SPAN><SPAN> What is vibe coding and why AI-assisted development matters?</SPAN></DIV>
<DIV><SPAN>-</SPAN><SPAN> What are the benefits of using AI in SAP development?</SPAN></DIV>
<DIV><SPAN>-</SPAN><SPAN> What development platforms are available (Web, Desktop, CLI)?</SPAN></DIV>
<DIV><SPAN>If you need more details, you can find these topics in sap community portal. Read that, then come back here.</SPAN></DIV>
<DIV>
<H3 id="toc-hId-1947359105"><FONT size="4">What This Post Covers - and Why It Matters?</FONT></H3>
<P class="">This post walks you through connecting Claude Code to a live SAP system using the ABAP Remote Filesystem extension's native MCP server - no external Node.js setup, no manual JSON editing, just a single toggle. </P>
<P class=""><STRONG>What this changes for SAP development:</STRONG></P>
<UL class="">
<LI><STRONG>No more hand-typed routine code.</STRONG> TYPE declarations, SELECT statements, ALV setup - written directly into the SAP object from a single prompt.</LI>
<LI><STRONG>No more AI guesswork.</STRONG> Without a live connection, AI tools hallucinate tables and function modules that don't exist. With MCP, every suggestion is grounded in your actual system.</LI>
<LI><STRONG>No more setup overhead.</STRONG> What used to require a custom Node.js project now takes one checkbox and one command - open to any developer with VS Code.</LI>
<LI><STRONG>Clean Core by default.</STRONG> Claude works through the same ADT API and released objects that Eclipse uses, so generated code fits your governance model instead of fighting it.</LI>
</UL>
<P class="">This is the point where AI-assisted ABAP stops being a chat-window experiment and starts being a real part of your IDE.</P>
</DIV>
<DIV> </DIV>
<DIV><STRONG>Goal: I will cover the entire topic in 4 parts:</STRONG></DIV>
<DIV><SPAN>|</SPAN><SPAN>Part 1</SPAN><SPAN>| Installing Claude Code on Windows and setting up the VS Code extension |</SPAN></DIV>
<DIV><SPAN>|</SPAN><SPAN>Part 2</SPAN><SPAN>| Connecting VS Code to your live SAP system via the ABAP FS extension |</SPAN></DIV>
<DIV><SPAN>|</SPAN><SPAN>Part 3</SPAN><SPAN>| Enabling the native MCP server with a single toggle - no Node.js setup, no JSON editing |</SPAN></DIV>
<DIV><SPAN>|</SPAN><SPAN>Part 4</SPAN><SPAN>| A live demo: one plain-English prompt creates a real, running ABAP report on SAP |</SPAN></DIV>
<DIV><SPAN>If you're here, you already know why this matters. Let's get to the actual steps.</SPAN></DIV>
<DIV> </DIV>
<DIV><STRONG>Pre-requisite:</STRONG> This guide assumes you already have an active Claude subscription (Pro, Max, Team, or Enterprise). If not, sign up at <A class="" href="https://claude.ai" target="_blank" rel="noopener nofollow noreferrer">claude.ai</A> before proceeding</DIV>
<DIV> </DIV>
<DIV><STRONG>Part 1 - The Setup: Getting Claude Code Running on Windows</STRONG></DIV>
<DIV><U>Step 1.1 - Install Claude Code CLI</U></DIV>
<DIV><SPAN>Open </SPAN><SPAN>PowerShell</SPAN><SPAN> (the built-in Windows command-line shell) and run:</SPAN></DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_0-1782403645482.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426129i7BB852B951EAE47D/image-size/medium?v=v2&px=400" role="button" title="Nibedita_0-1782403645482.png" alt="Nibedita_0-1782403645482.png" /></span>
<P> </P>
</DIV>
<DIV><SPAN>This downloads Anthropic's official installer and executes it in one step. '</SPAN><SPAN>irm'</SPAN><SPAN> fetches the script, '</SPAN><SPAN>iex'</SPAN><SPAN> runs it.</SPAN></DIV>
<DIV><SPAN>></SPAN><SPAN> <span class="lia-unicode-emoji" title=":warning:">⚠️</span> </SPAN><SPAN>Common Error - Git Bash Not Found</SPAN></DIV>
<DIV><SPAN>></SPAN><SPAN> Claude Code needs a bash shell to run on Windows. If you see this error, install </SPAN><SPAN><STRONG>Git for Windows</STRONG></SPAN><SPAN> from [</SPAN><SPAN>git-scm.com/downloads/win</SPAN><SPAN>](</SPAN><SPAN><A href="https://git-scm.com/downloads/win" target="_blank" rel="noopener nofollow noreferrer">https://git-scm.com/downloads/win</A></SPAN><SPAN>). During setup, select: </SPAN><SPAN>Git from the command line and also from 3rd-party software</SPAN><SPAN>. Then re-run the install command above.</SPAN></DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_1-1782403737130.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426130i0A321240F9C2F45B/image-size/medium?v=v2&px=400" role="button" title="Nibedita_1-1782403737130.png" alt="Nibedita_1-1782403737130.png" /></span></DIV>
<DIV><U><SPAN>Step 1.2 — Verify the Installation</SPAN></U>
<P> </P>
</DIV>
<DIV><SPAN>Close PowerShell and open a fresh window. Run:</SPAN></DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_2-1782403839582.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426131i7F58BA2D89AD974E/image-size/medium?v=v2&px=400" role="button" title="Nibedita_2-1782403839582.png" alt="Nibedita_2-1782403839582.png" /></span></DIV>
<DIV><SPAN>You should see a version number like '</SPAN><SPAN>claude 1.x.x'</SPAN><SPAN>. If PowerShell says </SPAN><SPAN>claude is not recognized</SPAN><SPAN>, the PATH wasn't set automatically. Fix it manually:</SPAN>
<P> </P>
</DIV>
<DIV><SPAN>1.</SPAN><SPAN> Start → search </SPAN><SPAN>Environment Variables in system settings</SPAN></DIV>
<DIV><SPAN>2.</SPAN><SPAN> Edit the environment variables for your account</SPAN></DIV>
<DIV><SPAN>3.</SPAN><SPAN> Select </SPAN><SPAN>Path</SPAN><SPAN><SPAN> → Edit → New → paste ( in this case path can be taken from powershell commnad prompt)</SPAN></SPAN></DIV>
<DIV><SPAN><SPAN> for eg: </SPAN></SPAN><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_3-1782403944264.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426132i1C30F8ADF7812B7F/image-size/medium?v=v2&px=400" role="button" title="Nibedita_3-1782403944264.png" alt="Nibedita_3-1782403944264.png" /></span>
<P> </P>
</DIV>
<DIV><SPAN>4.</SPAN><SPAN> Close and reopen PowerShell, then re-run </SPAN><SPAN>claude --version</SPAN><SPAN>.</SPAN></DIV>
<P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_5-1782404089631.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426134i3AE56F1C88B91B5F/image-size/medium?v=v2&px=400" role="button" title="Nibedita_5-1782404089631.png" alt="Nibedita_5-1782404089631.png" /></span></P>
<P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_6-1782404105391.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426135iDA769D6378034E9A/image-size/medium?v=v2&px=400" role="button" title="Nibedita_6-1782404105391.png" alt="Nibedita_6-1782404105391.png" /></span></P>
<P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_7-1782404136711.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426136iCFD7B02CB11A40B3/image-size/medium?v=v2&px=400" role="button" title="Nibedita_7-1782404136711.png" alt="Nibedita_7-1782404136711.png" /></span></P>
<DIV><SPAN>></SPAN> <SPAN>Run </SPAN><SPAN>claude doctor</SPAN><SPAN> - this command checks your PATH, authentication, Node.js version, and config in one shot. Always the first step when something isn't working.</SPAN></DIV>
<DIV><U>Step 1.3 - Launch Claude Code and the VS Code Extension</U></DIV>
<DIV><SPAN>Navigate to your project folder and launch Claude Code.</SPAN></DIV>
<DIV><SPAN>The first launch opens your browser to authenticate with your </SPAN><SPAN>Anthropic account</SPAN><SPAN> (Pro, Max, Team, or Enterprise all work). </SPAN></DIV>
<DIV><SPAN>For everyday ABAP work, the <STRONG>VS Code extension</STRONG> is where you'll spend most of your time.</SPAN></DIV>
<DIV><SPAN>Download and Install VS code from <A href="http://code.visualstudio.com" target="_self" rel="nofollow noopener noreferrer">code.visualstudio.com</A> for windows if you don't already have it. Once it is installed.</SPAN><SPAN>Open VS Code, press '</SPAN><SPAN>Ctrl+Shift+X'</SPAN><SPAN>, search for </SPAN><SPAN>Claude Code</SPAN><SPAN> (published by Anthropic), and install it. Once installed, the Claude icon appears in the Activity Bar and connects automatically to your account.</SPAN></DIV>
<P> </P>
<P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_1-1782404981935.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426140iA94712F10DC28E49/image-size/medium?v=v2&px=400" role="button" title="Nibedita_1-1782404981935.png" alt="Nibedita_1-1782404981935.png" /></span></P>
<DIV><SPAN>The extension gives you a persistent chat panel inside VS Code - ask Claude about the file you have open, highlight any ABAP block and ask it to explain or refactor, and switch between ABAP and CAP projects in the same session. No terminal switching required.</SPAN></DIV>
<DIV><SPAN>></SPAN> <SPAN>Note on Software Center installs:</SPAN><SPAN> If your organization restricts installations, Claude Code for VS Code is typically available via your company Software Center / Company Portal.</SPAN></DIV>
<DIV> </DIV>
<DIV><SPAN><STRONG>Part 2 - Connecting VS Code to Your SAP System via ABAP FS</STRONG></SPAN></DIV>
<DIV><SPAN>This is where the magic begins. The </SPAN><SPAN><STRONG>ABAP Remote Filesystem</STRONG> (ABAP FS)</SPAN><SPAN>extension - built by <STRONG>Marcello Urbani</STRONG> - connects VS Code to your SAP system using the same ADT REST API that Eclipse uses. Once connected, your ABAP objects (programs, classes, CDS views, behavior definitions) appear as files in VS Code. Claude Code can then read, write, and review them like any local code file.</SPAN></DIV>
<DIV><STRONG>Pre-requisites Before You Connect</STRONG></DIV>
<DIV><SPAN>You'll need these four things from your SAP system before starting:</SPAN></DIV>
<DIV><SPAN>| </SPAN><SPAN>Hostname or IP</SPAN><SPAN> | The address of your SAP server (hostname preferred - IP causes SSL issues explained below) |</SPAN></DIV>
<DIV><SPAN>| </SPAN><SPAN>ADT Service active</SPAN><SPAN> | Go to transaction SICF → '</SPAN><SPAN>/sap/bc/adt'</SPAN><SPAN> must be activated |</SPAN></DIV>
<DIV><SPAN>| </SPAN><SPAN>Client number</SPAN><SPAN>| e.g. '</SPAN><SPAN>100'</SPAN><SPAN> - visible in the SAP logon screen |</SPAN></DIV>
<DIV><SPAN>|</SPAN><SPAN>Username & Password</SPAN><SPAN>| Your regular SAP development user |</SPAN></DIV>
<DIV><SPAN>| </SPAN><SPAN>Port</SPAN><SPAN> | HTTPS: '</SPAN><SPAN>44300'</SPAN><SPAN> (typical) | HTTP: '</SPAN><SPAN>8000'</SPAN><SPAN> for instance 00, '</SPAN><SPAN>8001'</SPAN><SPAN> for instance 01 |</SPAN></DIV>
<DIV> </DIV>
<DIV><U>Step 2.1 - Install and Configure ABAP FS</U></DIV>
<DIV><SPAN>1.</SPAN><SPAN> In VS Code Extensions ('</SPAN><SPAN>Ctrl+Shift+X'</SPAN><SPAN>), search </SPAN><SPAN>ABAP remote filesystem</SPAN><SPAN> by Marcello Urbani → Install.</SPAN></DIV>
<DIV><SPAN>2.</SPAN><SPAN> Press '</SPAN><SPAN>Ctrl+Shift+P'</SPAN><SPAN> → type </SPAN><SPAN>ABAP FS: Connection Manager</SPAN><SPAN> → open it.</SPAN></DIV>
<DIV><SPAN>3.</SPAN><SPAN> Add a new connection and fill in the fields:</SPAN></DIV>
<DIV><SPAN> </SPAN><SPAN>-</SPAN> <SPAN>Name:</SPAN><SPAN> anything you like (e.g. </SPAN><SPAN>DEV</SPAN><SPAN> or </SPAN><SPAN>SANDBOX</SPAN><SPAN>)</SPAN></DIV>
<DIV><SPAN> </SPAN><SPAN>-</SPAN> <SPAN>Server URL:'</SPAN><SPAN>https://<hostname>:44300'</SPAN></DIV>
<DIV><SPAN> </SPAN><SPAN>-</SPAN><SPAN> <span class="lia-unicode-emoji" title=":warning:">⚠️</span> </SPAN><SPAN>Do NOT add '</SPAN><SPAN>/sap/bc/adt'</SPAN><SPAN> to the URL</SPAN><SPAN> - the extension adds this automatically. If you include it, the path doubles and the connection fails.</SPAN></DIV>
<DIV><SPAN> </SPAN><SPAN>-</SPAN> <SPAN>Client, Username, Language:</SPAN> '<SPAN>EN'</SPAN></DIV>
<DIV><SPAN>4.</SPAN><SPAN> Save.</SPAN></DIV>
<DIV><SPAN>5.</SPAN><SPAN> Press '</SPAN><SPAN>Ctrl+Shift+P'</SPAN><SPAN> → </SPAN><SPAN>ABAP FS: Connect to an SAP system</SPAN><SPAN>→ select your connection → enter password.</SPAN></DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_2-1782405670643.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426149i8AF50AE6ACE63C2C/image-size/medium?v=v2&px=400" role="button" title="Nibedita_2-1782405670643.png" alt="Nibedita_2-1782405670643.png" /></span></DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_3-1782405784275.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426150i4B79820C05FB228E/image-size/medium?v=v2&px=400" role="button" title="Nibedita_3-1782405784275.png" alt="Nibedita_3-1782405784275.png" /></span> <span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_4-1782405864816.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426151i6AB93286C9C60C5F/image-size/medium?v=v2&px=400" role="button" title="Nibedita_4-1782405864816.png" alt="Nibedita_4-1782405864816.png" /></span>
<P> </P>
</DIV>
<DIV><SPAN>></SPAN><SPAN> <span class="lia-unicode-emoji" title=":warning:">⚠️</span> </SPAN><SPAN>SSL Certificate Error (very common on internal systems)</SPAN></DIV>
<DIV><SPAN>></SPAN><SPAN> If you see </SPAN><SPAN>IP does not match certificate's altnames</SPAN><SPAN> - this is because your SAP system's SSL certificate was issued with a hostname, not the IP. The fix: Get the hostname (e.g. '</SPAN><SPAN><A href="https://sapdev.company.com:44300" target="_blank" rel="noopener nofollow noreferrer">https://sapdev.company.com:44300'</A></SPAN><SPAN>) and use that instead of the IP. </SPAN></DIV>
<DIV><SPAN>></SPAN><SPAN> <span class="lia-unicode-emoji" title=":warning:">⚠️</span></SPAN><SPAN>ADT Service Not Found</SPAN></DIV>
<DIV><SPAN>></SPAN><SPAN> If you see </SPAN><SPAN>Resource /sap/bc/adt does not exist</SPAN><SPAN> - the ADT service isn't activated. Run tcode SICF → navigate to </SPAN><SPAN>default_host → 'sap/bc/adt' </SPAN><SPAN>→ right-click → Activate Service.</SPAN></DIV>
<DIV> </DIV>
<DIV><U>Step 2.2 - Navigating ABAP Objects</U></DIV>
<DIV>ABAP FS gives you two ways to find objects. <STRONG>Object Search</STRONG> lets you find anything by name instantly. If you prefer a tree view like Eclipse ADT, enable <STRONG>SAP GUI Integration</STRONG> in your connection settings - this gives you a full package tree (Dictionary, Source Code Library, Transactions) and even embeds SAP GUI for HTML directly inside VS Code, so you can run transactions without leaving the editor.</DIV>
<DIV><SPAN>1.</SPAN><SPAN> Click </SPAN><SPAN>OBJECT SEARCH </SPAN><SPAN>in the left sidebar</SPAN></DIV>
<DIV><SPAN>2.</SPAN><SPAN> Type the object or package name (e.g. '</SPAN><SPAN>ZCL_MY_CLASS'</SPAN><SPAN> or '</SPAN><SPAN>Z_MY_PACKAGE'</SPAN><SPAN>)</SPAN></DIV>
<DIV><SPAN>3.</SPAN><SPAN> Double-click any result to open it as a text file in VS Code</SPAN></DIV>
<DIV><SPAN>4.</SPAN><SPAN> To edit: right-click </SPAN><SPAN> → edit → save (changes push back to SAP automatically)</SPAN></DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_5-1782406842709.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426154iFCC48857AA2801D1/image-size/medium?v=v2&px=400" role="button" title="Nibedita_5-1782406842709.png" alt="Nibedita_5-1782406842709.png" /></span></DIV>
<DIV><SPAN>Once an object is open in VS Code, open the integrated terminal (</SPAN><SPAN>Ctrl+) and run </SPAN><SPAN>claude. Some prompts that immediately pay off:</SPAN>
<P> </P>
</DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_6-1782406930523.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426155iF35ED8070217C462/image-size/medium?v=v2&px=400" role="button" title="Nibedita_6-1782406930523.png" alt="Nibedita_6-1782406930523.png" /></span></DIV>
<DIV><STRONG><SPAN>Part 3 -The Game Changer: Enabling the Native MCP Server</SPAN></STRONG>
<P> </P>
</DIV>
<DIV><SPAN>This is the step that changes everything - and the reason this post exists.</SPAN></DIV>
<DIV><STRONG>Why ABAP FS Alone Isn't Enough?</STRONG></DIV>
<DIV><SPAN>With only ABAP FS connected, Claude can see only the one file you currently have open. Ask it to create a new class and it might invent table names, function modules, or BAdI definitions that don't exist on your system. It's helpful, but it's guessing.</SPAN></DIV>
<DIV><STRONG> ABAP FS Only </STRONG> <STRONG>ABAP FS + MCP</STRONG>
<TABLE>
<TBODY>
<TR>
<TD>Claude sees what we search Manually</TD>
<TD>Claude <STRONG>autonomously searches</STRONG> any object on the system</TD>
</TR>
<TR>
<TD>Hallucinates objects it hasn't seen</TD>
<TD>Grounded in live SAP system data</TD>
</TR>
<TR>
<TD>You copy-paste code manually</TD>
<TD>Claude reads, writes, activates autonomously</TD>
</TR>
<TR>
<TD>No transport awareness</TD>
<TD>Creates & assigns transports via ADT</TD>
</TR>
</TBODY>
</TABLE>
<P> </P>
</DIV>
<DIV><SPAN>The </SPAN><SPAN>MCP (Model Context Protocol) server </SPAN><SPAN>gives Claude Code a live connection to your SAP system's ADT API - the same backend Eclipse uses. Claude stops guessing and starts knowing.</SPAN></DIV>
<DIV><U>Step 3.1 - Enable the MCP Server (One Toggle)</U></DIV>
<DIV><SPAN>This is where the zero-config part comes in. You don't need to install anything extra, clone a Node.js repo, or edit JSON files manually.</SPAN></DIV>
<DIV><SPAN>Press '</SPAN><SPAN>Ctrl+Shift+P'</SPAN><SPAN> → search </SPAN><SPAN>ABAP FS MCP</SPAN><SPAN> → select it → </SPAN><SPAN>enable Autostart</SPAN><SPAN>.</SPAN></DIV>
<DIV><SPAN>That's it. The ABAP FS extension spins up a local MCP server on your machine (default port </SPAN><SPAN>4847</SPAN><SPAN>). You'll see a VS Code notification confirming it's running:</SPAN></DIV>
<DIV><SPAN>></SPAN> <SPAN>ABAP MCP Server running on port 4847. External AI clients can connect to <A href="http://localhost:4847/mcp" target="_blank" rel="noopener nofollow noreferrer">http://localhost:4847/mcp</A></SPAN></DIV>
<P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_1-1782407943013.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426157i77F6CF90695CAE23/image-size/medium?v=v2&px=400" role="button" title="Nibedita_1-1782407943013.png" alt="Nibedita_1-1782407943013.png" /></span></P>
<P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_3-1782408012661.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426159i6ACAF21EEF81B20B/image-size/large?v=v2&px=999" role="button" title="Nibedita_3-1782408012661.png" alt="Nibedita_3-1782408012661.png" /></span></P>
<DIV><U>Step 3.2 - Register the MCP Server with Claude Code</U></DIV>
<DIV><SPAN>Now tell Claude Code where to find the ABAP tools. Run this in the VS Code integrated terminal:</SPAN></DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_4-1782408077760.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426160i344FEAB84125DB56/image-size/medium?v=v2&px=400" role="button" title="Nibedita_4-1782408077760.png" alt="Nibedita_4-1782408077760.png" /></span></DIV>
<DIV><SPAN>This registers the local MCP server with Claude Code. The configuration is saved to your '</SPAN><SPAN>.claude.json'</SPAN><SPAN> file and persists across sessions - you only need to do this once.</SPAN></DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_5-1782408144482.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426161iAAA2FF48C822A39A/image-size/large?v=v2&px=999" role="button" title="Nibedita_5-1782408144482.png" alt="Nibedita_5-1782408144482.png" /></span><U><SPAN>Step 3.3 - Verify the Connection</SPAN></U>
<P> </P>
</DIV>
<DIV>open the terminal and run this command once the MCP server is added </DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_6-1782408296420.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426162i6D1260B1466BD8FB/image-size/medium?v=v2&px=400" role="button" title="Nibedita_6-1782408296420.png" alt="Nibedita_6-1782408296420.png" /></span><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_7-1782408317004.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426163iA1AF4313EE379DC9/image-size/medium?v=v2&px=400" role="button" title="Nibedita_7-1782408317004.png" alt="Nibedita_7-1782408317004.png" /></span></DIV>
<DIV><SPAN>You should see:</SPAN></DIV>
<DIV><SPAN>Claude Code will confirm when the server is registered:</SPAN></DIV>
<DIV><SPAN>></SPAN> <SPAN>abap-remote-fs has been added with HTTP transport at <A href="http://localhost:4847/mcp" target="_blank" rel="noopener nofollow noreferrer">http://localhost:4847/mcp</A>"*</SPAN></DIV>
<DIV><SPAN>The Complete Architecture</SPAN></DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_8-1782408719813.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426164i55C1D75023E52737/image-size/medium?v=v2&px=400" role="button" title="Nibedita_8-1782408719813.png" alt="Nibedita_8-1782408719813.png" /></span></DIV>
<DIV><SPAN>Claude Code can now autonomously:</SPAN></DIV>
<DIV><SPAN>-</SPAN><SPAN> Search and read any ABAP object on the live SAP system</SPAN></DIV>
<DIV><SPAN>-</SPAN><SPAN> write → syntax check → activate → unlock objects</SPAN></DIV>
<DIV><SPAN>-</SPAN><SPAN> Create transport requests and assign objects</SPAN></DIV>
<DIV><SPAN>-</SPAN><SPAN> Run ATC checks and read short dumps - all from a plain-English prompt</SPAN></DIV>
<DIV><SPAN>></SPAN> <SPAN>Golden - In <STRONG>Auto mode</STRONG>, Claude will write, syntax check, and activate without pausing - that's the power of the agentic workflow. If you want to review before anything is activated, switch to <STRONG>Plan mode</STRONG> <STRONG> shift+tab </STRONG>to cycle modes) Claude will show you the full plan and wait for your approval. For production-adjacent systems, always run in Plan or Step mode.</SPAN></DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_0-1782409842588.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426167iCC621FF9DB99E99C/image-size/medium?v=v2&px=400" role="button" title="Nibedita_0-1782409842588.png" alt="Nibedita_0-1782409842588.png" /></span></DIV>
<DIV><STRONG><SPAN>Part 4 - Live Demo: One Prompt, One Real ABAP Program on SAP</SPAN></STRONG></DIV>
<DIV><SPAN><EM>Disclaimer: This is my first time setting up all this and explore, so i just started with a very simple scenario. Going forward will create RAP objects and other complex artifacts and see the efficiency.</EM></SPAN><STRONG><SPAN><BR /></SPAN></STRONG></DIV>
<DIV><SPAN>Let me show you what all of this enables. Here's the exact prompt I used:</SPAN></DIV>
<DIV><SPAN>></SPAN> <SPAN>Create a new ABAP executable program ZCL_DEMO_REPORT_01 in my ZVS_DEMO package. Fetch data from MARA for a user-specified Material Number (select-option) and display Material Number, Type, and Created By in an ALV grid. Write in ABAP 7.5 syntax.</SPAN></DIV>
<DIV><SPAN>One prompt. No templates. No copy-paste. Here's what Claude did.</SPAN></DIV>
<DIV><STRONG>Act 1 - Claude Plans Before It Codes</STRONG></DIV>
<DIV><SPAN>Claude didn't immediately start writing code. It:</SPAN></DIV>
<DIV><SPAN>1.</SPAN><SPAN> Confirmed the target package ('</SPAN><SPAN>ZVS_DEMO'</SPAN><SPAN>) exists on the system</SPAN></DIV>
<DIV><SPAN>2.</SPAN><SPAN> Detected that the program creation triggered a </SPAN><SPAN>**transport request dialog**</SPAN><SPAN> — and recognised it was the likely source of a cancellation</SPAN></DIV>
<DIV><SPAN>3.</SPAN><SPAN> Called the SAP ADT API via Bash to </SPAN><SPAN>**list existing open transports**</SPAN></DIV>
<DIV><SPAN>4.</SPAN><SPAN> Selected the correct transport and retried the creation</SPAN></DIV>
<DIV><SPAN>There was a little bit delay on my end to confirm the transport. and it gave me this message.</SPAN></DIV>
<DIV><FONT color="#FFCC00"><SPAN>></SPAN> <SPAN>Package confirmed. The cancellation is likely a transport request dialog. Let me check for existing transports, then retry.</SPAN></FONT></DIV>
<DIV><SPAN>This is the part that impresses ABAP developers most. Claude handled a real SAP workflow quirk .</SPAN></DIV>
<DIV><STRONG>Act 2 - The Program Appears on SAP</STRONG></DIV>
<DIV><SPAN>Claude then created the program on the live system. You can watch its autonomous todo list mid-execution:</SPAN></DIV>
<DIV><SPAN>-</SPAN> <SPAN>Create ABAP program ZCL_DEMO_REPORT_01 in ZVS_DEMO package via MCP</SPAN></DIV>
<DIV><SPAN>-</SPAN><SPAN> Get workspace URI for the new program</SPAN></DIV>
<DIV><SPAN>-</SPAN><SPAN> Write ABAP source code into the program</SPAN></DIV>
<DIV><SPAN>-</SPAN><SPAN> Activate the program and check diagnostics</SPAN></DIV>
<DIV><SPAN>'ZCL_DEMO_REPORT_01'</SPAN><SPAN> appeared in the VS Code Explorer sidebar - a real, registered ABAP program on the SAP system, not a local file.</SPAN></DIV>
<DIV><SPAN>You can see initially there was no program created in my package </SPAN></DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_1-1782413574177.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426191iA0F27FED74F8F588/image-size/medium?v=v2&px=400" role="button" title="Nibedita_1-1782413574177.png" alt="Nibedita_1-1782413574177.png" /></span></DIV>
<DIV>After few seconds, the program is created </DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_2-1782413600566.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426194i035E9269F5F4C109/image-size/large?v=v2&px=999" role="button" title="Nibedita_2-1782413600566.png" alt="Nibedita_2-1782413600566.png" /></span>
<P> </P>
</DIV>
<DIV><U>Act 3 - Full ABAP 7.5 Source Code Written</U></DIV>
<DIV><SPAN>With the object created, Claude fetched the workspace URI and wrote the complete source code directly into the SAP program. What it generated:</SPAN></DIV>
<DIV><SPAN>No placeholder code. Real, working ABAP in the correct syntax release, referencing actual MARA field types from the live system.</SPAN></DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_0-1782414225801.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426211i3C44D98AAB8220CA/image-size/medium?v=v2&px=400" role="button" title="Nibedita_0-1782414225801.png" alt="Nibedita_0-1782414225801.png" /></span></DIV>
<DIV><U>Act 4 - Running the Program</U></DIV>
<DIV><SPAN>After activation, there are two ways to run it:</SPAN></DIV>
<DIV><SPAN>Option A - Classic SAP GUI:</SPAN><SPAN>Log in to SAP GUI →run the program → Execute</SPAN></DIV>
<DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nibedita_1-1782414368796.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/426214i3DE9B385C56A9072/image-size/medium?v=v2&px=400" role="button" title="Nibedita_1-1782414368796.png" alt="Nibedita_1-1782414368796.png" /></span></DIV>
<DIV><SPAN>Option B - Embedded SAP Web GUI</SPAN><SPAN>(what I used): VS Code can open the SAP Web GUI directly in a browser tab, embedded inside the IDE. No separate login or window switching required.</SPAN></DIV>
<DIV><SPAN>Enter selection criteria:</SPAN></DIV>
<DIV><SPAN>The selection screen appeared with the Matnr </SPAN><SPAN> field exactly as specified. I entered a range of </SPAN><SPAN>11</SPAN><SPAN>to </SPAN><SPAN>21</SPAN><SPAN>. The value help (F4) shows the available materials in the system</SPAN></DIV>
<DIV><SPAN>Material Number, Material Type, and Created By - exactly what was asked for. Live data from MARA. Report running.</SPAN></DIV>
<DIV> </DIV>
<DIV><U>Summary:</U></DIV>
<DIV><STRONG>|Claude understands SAP context|</STRONG><SPAN><STRONG> </STRONG>It identified the transport dialog, queried existing transports via ADT, and handled a real SAP workflow quirk autonomously </SPAN></DIV>
<DIV><STRONG>| It created a real SAP object|</STRONG><SPAN> '</SPAN><SPAN>ZCL_DEMO_REPORT_01'</SPAN><SPAN> exists on the live system, created via ADT REST API through MCP - not a file on disk </SPAN></DIV>
<DIV><STRONG>| Production-quality ABAP 7.5</STRONG><SPAN><STRONG> |</STRONG> TYPE declarations referencing actual MARA field types, correct naming conventions, modern SQL syntax </SPAN></DIV>
<DIV><STRONG>| Minutes, not hours</STRONG><SPAN><STRONG>|</STRONG> The developer's job shifts to reviewing - not writing skeletons, hunting transport dialogs, or looking up field types </SPAN></DIV>
<DIV><STRONG>| Fully iterative</STRONG><SPAN><STRONG>|</STRONG> Once created, you can ask Claude to add authority checks, error handling, ALV field catalogues, or additional filters - each iteration in seconds </SPAN></DIV>
<DIV><STRONG>| You stay in control</STRONG><SPAN><STRONG> |</STRONG> Claude's todo list is transparent - you see every step it plans. You review the code. You decide what activates </SPAN></DIV>
<DIV> </DIV>
<DIV><STRONG>Where to Go from Here?</STRONG></DIV>
<DIV><SPAN>Here are five things to try once you have the setup working:</SPAN></DIV>
<DIV><SPAN>1.</SPAN> <SPAN>Understand inherited code - </SPAN><SPAN>Explain the purpose and flow of report Z_*_REPORT. Include tables accessed, authority checks, deprecated patterns like SELECT .</SPAN></DIV>
<DIV><SPAN>2.</SPAN> <SPAN>Generate a CDS view -</SPAN><SPAN> </SPAN><SPAN>Create a CDS view hierarchy for Sales Order analysis: interface view joining VBAK+VBAP, projection view with Fiori Elements. UI annotations for a List Report.</SPAN></DIV>
<DIV><SPAN>3.</SPAN> <SPAN>Build a Travel Request POC</SPAN><SPAN> - RAP Business Object with CRUD, approve/reject action, draft handling, OData V4 binding, Fiori Elements UI.</SPAN></DIV>
<DIV><SPAN>4.</SPAN> <SPAN>Write ABAP Unit tests -</SPAN><SPAN> </SPAN><SPAN>Generate a unit test class </SPAN></DIV>
<DIV><SPAN>5.</SPAN> <SPAN>Code review and modernization - </SPAN><SPAN>Review this class for Clean ABAP violations, missing authority checks, SELECT * usage, and SELECT inside LOOP. Propose S/4-equivalent replacements.</SPAN></DIV>
<DIV> </DIV>
<DIV><SPAN><STRONG>The bottom line</STRONG>: <STRONG>The integration that used to require manual Node.js setup, JSON editing, and external package management now takes a single Ctrl+Shift+P toggle and one terminal command.</STRONG> </SPAN></DIV>
<DIV> </DIV>
<DIV><SPAN>The ABAP Remote Filesystem team has done the hard work. Claude Code does the coding. You do the review.</SPAN></DIV>
<DIV><SPAN>Give it a try - and let me know in the comments what use case you tackle first.</SPAN></DIV>
<DIV> </DIV>
<DIV><EM>A personal note : This is my first time diving deeper into vibe coding and MCP concepts. I come from a classic ABAP background, and everything covered here - from the VS Code setup to the MCP server to the live demo - I explored and built from scratch over the past few weeks. The scenario is intentionally simple. The goal was to get the fundamentals right, document them honestly, and share what works. There is a lot more ground to cover - RAP generation at scale, Clean Core extensibility patterns, ATC pre-checks via Claude Code, and deeper agentic workflows. I'll be going further in the posts ahead. If you're also just getting started with this, I hope this gives you a solid, working foundation to build on. And if you're already further ahead - I'd love to hear what you've learnt in the comments.</EM></DIV>
<DIV> </DIV>
<DIV><EM>Note: All screenshots in this post are taken from a live S/4HANA development system. Code generated by Claude Code should always be reviewed and tested in a sandbox environment before activation in any productive system.</EM></DIV>2026-07-05T13:39:48.252000+02:00https://community.sap.com/t5/technology-blog-posts-by-sap/building-a-rap-application-with-external-sap-hana-cloud-using-cds-external/ba-p/14428145Building a RAP Application with External SAP HANA Cloud using CDS External Entities – Part 12026-07-08T10:49:55.174000+02:00Sivakumar_Subramaniamhttps://community.sap.com/t5/user/viewprofilepage/user-id/188613<H1 id="toc-hId-1689246492">Why External Entities?</H1><P>CDS external entities provide a modern way to handle secondary database connections in ABAP Cloud. They allow applications to retrieve and modify data from other databases using SQL. Sounds interesting? This blog post covers how to create a RAP application in SAP BTP ABAP Environment with a secondary HANA database connection.</P><P> </P><H1 id="toc-hId-1492732987">Business scenario:</H1><P><BR /><SPAN>Many organizations already have business data stored in a separate </SPAN><STRONG>SAP HANA Cloud database</STRONG><SPAN> and want to build modern </SPAN><STRONG>RAP (ABAP RESTful Application Programming Model)</STRONG><SPAN> applications on SAP BTP ABAP Environment without replicating that data into the ABAP system.</SPAN></P><DIV><P>The blog demonstrates this using a <STRONG>Loyalty Management</STRONG> application.</P><H4 id="toc-hId-1683467639">Scenario</H4><UL><LI>Customer loyalty information (Memberships) is stored in an external SAP HANA Cloud database.</LI><LI>Transaction data related to each membership is also stored in the same external database.</LI><LI>The business wants a Fiori application where users can:<UL><LI>Create loyalty memberships</LI><LI>Maintain loyalty transactions</LI><LI>Update and delete records</LI><LI>View accumulated loyalty points</LI><LI>Persist all changes directly in the external HANA database</LI></UL></LI></UL></DIV><P><A href="https://community.sap.com/source-Ids-list" target="1_ytw4qqjq" rel="nofollow noopener noreferrer"> </A></P><H1 id="toc-hId-1099705977">Prerequisites:</H1><OL><LI>SAP BTP Sub-Account</LI><LI>SAP HANA Cloud Instance</LI><LI>SAP BTP ABAP Environment</LI></OL><H1 id="toc-hId-903192472">Steps:</H1><OL><LI>Setup SAP HANA Cloud instance</LI><LI>Create Schema and Tables</LI><LI>Configure external connection to External HANA database from SAP BTP ABAP Environment using External Entities</LI><LI>Create External Entities</LI></OL><H1 id="toc-hId-706678967">Setup SAP HANA Cloud instance</H1><P>Let’s start on with the creation of <A href="https://help.sap.com/docs/hana-cloud/sap-hana-cloud-administration-guide/subscribing-to-sap-hana-cloud-administration-tools" target="_blank" rel="noopener noreferrer">SAP HANA Cloud instance</A>.</P><OL><LI>Open SAP BTP cockpit and add the following Entitlements.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Sivakumar_Subramaniam_1-1784629294230.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/435449iC66B60271A4BCA58/image-size/large?v=v2&px=999" role="button" title="Sivakumar_Subramaniam_1-1784629294230.png" alt="Sivakumar_Subramaniam_1-1784629294230.png" /></span><BR /><BR /><BR /></LI><LI>Create HANA cloud subscription.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="2.jpg" style="width: 800px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/427802iC14D37786CA6E788/image-size/large?v=v2&px=999" role="button" title="2.jpg" alt="2.jpg" /></span><BR /><BR /></LI><LI>Create HANA Cloud Instance<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="3.jpg" style="width: 800px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/427804iBB423502FA834C80/image-size/large?v=v2&px=999" role="button" title="3.jpg" alt="3.jpg" /></span><BR /><BR />Specify Instance name, Set DBADMIN password and choose Allow all IP address<BR /><div class="lia-spoiler-container"><a class="lia-spoiler-link" href="#" rel="nofollow noopener noreferrer">Spoiler</a><noscript> (Highlight to read)</noscript><div class="lia-spoiler-border"><div class="lia-spoiler-content"><STRONG>Disclaimer on Database IP Access Configuration</STRONG><BR />Allowing unrestricted access (e.g., permitting all IP addresses such as 0.0.0.0/0) to a database that contains production data introduces significant security risks. This approach should only be used in strictly controlled environments.</div><noscript><div class="lia-spoiler-noscript-container"><div class="lia-spoiler-noscript-content">Disclaimer on Database IP Access ConfigurationAllowing unrestricted access (e.g., permitting all IP addresses such as 0.0.0.0/0) to a database that contains production data introduces significant security risks. This approach should only be used in strictly controlled environments.</div></div></noscript></div></div><DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="4.jpg" style="width: 800px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/427806i71BE31BF802E68C1/image-size/large?v=v2&px=999" role="button" title="4.jpg" alt="4.jpg" /></span></DIV><BR /><BR /></LI><LI>Once the Instance status turns into Running state and click on Actions three dots and Open in SAP HANA Database Explorer. <BR />Provide the DBADMIN credentials from the previous step to connect to the HANA database.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="5.jpg" style="width: 800px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/427807iD85EE7115FA464A0/image-size/large?v=v2&px=999" role="button" title="5.jpg" alt="5.jpg" /></span><BR /><BR /></LI></OL><P class="lia-indent-padding-left-30px" style="padding-left : 30px;"> </P><H1 id="toc-hId-510165462">Create Schema and Tables<BR /><BR /></H1><DIV>Open SQL Console and perform the following steps to create the schema and tables.</DIV><UL><LI>Create Schema<BR /><BR /></LI></UL><pre class="lia-code-sample language-sql"><code>CREATE SCHEMA LOYALTY;</code></pre><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="6.jpg" style="width: 801px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/427810i35D6C0266FEEC4C1/image-size/large?v=v2&px=999" role="button" title="6.jpg" alt="6.jpg" /></span></P><UL><LI>Create Membership table: zlm_membship_ee <SPAN> .</SPAN></LI></UL><P class="lia-indent-padding-left-90px" style="padding-left : 90px;">Stores membership details<BR />Primary key: client + membershipuuid</P><pre class="lia-code-sample language-sql"><code>create column table loyalty."zlm_membship_ee" (
"client" nvarchar (000003) default '000' not null,
"membershipuuid" varbinary (000016) default x'00000000000000000000000000000000' not null ,
"membershipid" nvarchar (000010) default '0000000000' not null,
"customer" nvarchar (000010) default '' not null,
"createdby" nvarchar (000012) default '' not null,
"createdat" decimal (000021, 000007) default 0 not null,
"lastchangedby" nvarchar (000012) default '' not null,
"locallastchangedat" decimal (000021, 000007) default 0 not null,
"lastchangedat" decimal (000021, 000007) default 0 not null,
primary key ("client", "membershipuuid" )
) column loadable
</code></pre><UL><LI>Create Transactions table: zlm_transctns_ee</LI></UL><P class="lia-indent-padding-left-90px" style="padding-left : 90px;">Stores transactions linked to membership.<BR />Contains transaction value and loyalty points.</P><pre class="lia-code-sample language-sql"><code>create column table loyalty."zlm_transctns_ee" (
"client" nvarchar (000003) default '000' not null,
"transactionuuid" varbinary (000016) default x'00000000000000000000000000000000' not null ,
"membershipuuid" varbinary (000016) default x'00000000000000000000000000000000' not null ,
"transactiondate" NVARCHAR (000008) DEFAULT '00000000' NOT NULL,
"transactionvalue" DECIMAL (000010, 000002) DEFAULT 0 NOT NULL,
"transactioncurrency" NVARCHAR (000005) DEFAULT '' NOT NULL,
"loyaltypoints" BIGINT DEFAULT 0 NOT NULL,
"createdby" nvarchar (000012) default '' not null,
"createdat" decimal (000021, 000007) default 0 not null,
"lastchangedby" nvarchar (000012) default '' not null,
"locallastchangedat" decimal (000021, 000007) default 0 not null,
"lastchangedat" decimal (000021, 000007) default 0 not null,
primary key ("client", "transactionuuid" )
) column loadable
</code></pre><H1 id="toc-hId-313651957"><BR />Configure connectivity to an external SAP HANA database from Steampunk for data access using External Entities<BR /><BR /></H1><OL><LI>Establish outbound SQL access using an external entity using ABAP Development Tools for Eclipse<BR /><BR /><OL class="lia-list-style-type-lower-roman"><LI>Define and activate a logical external schema whose configuration specifies the connection details for the outbound communication. Create a <A href="https://help.sap.com/docs/ABAP_PLATFORM_NEW/c238d694b825421f940829321ffa326a/cfaa37a4c0054c5cad00c03f7774a7ac.html" target="_blank" rel="noopener noreferrer">logical external schema</A> in ABAP Development Tools (ADT) using the creation wizard.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="7.jpg" style="width: 801px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/427911i20CE33AAB5695F36/image-size/large?v=v2&px=999" role="button" title="7.jpg" alt="7.jpg" /></span><BR /><BR /></LI><LI> Create an Outbound Service of the type Outbound SQL Access for your logical external schema.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="8.jpg" style="width: 799px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/427912iF67DAB3CD7A5D5CC/image-size/large?v=v2&px=999" role="button" title="8.jpg" alt="8.jpg" /></span><BR /><BR /></LI><LI>Create a Communication Scenario.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="9.jpg" style="width: 801px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/427913iF26524F7C38B4E00/image-size/large?v=v2&px=999" role="button" title="9.jpg" alt="9.jpg" /></span><BR /><BR /></LI><LI>Include the outbound service in the communication scenario.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="10.jpg" style="width: 801px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/427914i8F7176169F86D171/image-size/large?v=v2&px=999" role="button" title="10.jpg" alt="10.jpg" /></span><BR /><BR /></LI></OL></LI><LI>Configure External Connection<BR />In the Fiori Launchpad, Logon as Administrator and perform the following steps.<OL class="lia-list-style-type-lower-roman"><LI>Create a Communication Arrangement for scenario ZLM_COM_EXT_SCHEMA_EE.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="11.jpg" style="width: 800px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/427915i88E761244CA7D646/image-size/large?v=v2&px=999" role="button" title="11.jpg" alt="11.jpg" /></span><BR /><BR /><BR /><BR /></LI><LI> Create a Communication System<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="12.jpg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/427916i778ED34E800C4909/image-size/large?v=v2&px=999" role="button" title="12.jpg" alt="12.jpg" /></span><BR /><BR /><BR />Toggle Remote SQL Access and choose Adapter Name as HANA (ODBC) <BR />Adapter Configuration :Driver=<A href="http://libodbchdb.so/" target="_blank" rel="noopener nofollow noreferrer">libodbcHDB.so</A>;ServerNode=<A href="https://*.hanacloud.ondemand.com/" target="_blank" rel="noopener nofollow noreferrer">*.hanacloud.ondemand.com</A>(URL of the External Database):443;<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="13.jpg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/427917i64AB6D94EF3E270D/image-size/large?v=v2&px=999" role="button" title="13.jpg" alt="13.jpg" /></span><BR /><BR /><BR /></LI><LI>Create an Outbound User. Specify the HANA DB user which contains the necessary authorizations for accessing the External Schema.<BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="14.jpg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/427918i91602AC106B25A84/image-size/large?v=v2&px=999" role="button" title="14.jpg" alt="14.jpg" /></span><BR /><BR /><BR /><BR /></LI></OL></LI></OL><H1 id="toc-hId-117138452">Create CDS External Entities</H1><P>Two types:<BR />1. Writable External Entity → Used for INSERT/UPDATE/DELETE<BR />2. Static External Entity → Used for SELECT (read only)<BR /><BR />These entities map external tables to ABAP CDS.</P><P>In ABAP Development Tools for Eclipse: As an ABAP Developer, here’s what you need to do to establish outbound SQL access using a CDS external entity.</P><UL class="lia-list-style-type-lower-roman"><LI>Define and activate an external entity that represents the external database object.As we are going to perform CUD operation on external database, we need to create Writable External Entity for table zlm_membship_ee which will be referred by external name zlm_membship_ee.</LI></UL><pre class="lia-code-sample language-abap"><code>@EndUserText.label: 'Writable EE for HANA tab zlm_membship_ee'
define writable external entity zlm_membship_cud_ee external name "zlm_membship_ee"
{
key client : abap.char(3) external name "client";
key membershipuuid : sysuuid_x16 external name "membershipuuid";
membershipid : zlm_membershipid_ee external name "membershipid";
customer : zlm_customer_ee external name "customer";
@Semantics.user.createdBy: true
createdby : abp_creation_user external name "createdby";
@Semantics.systemDateTime.createdAt: true
createdat : abp_creation_tstmpl external name "createdat";
@Semantics.user.lastChangedBy: true
lastchangedby : abp_lastchange_user external name "lastchangedby";
@Semantics.systemDateTime.localInstanceLastChangedAt: true
locallastchangedat : abp_locinst_lastchange_tstmpl external name "locallastchangedat";
@Semantics.systemDateTime.lastChangedAt: true
lastchangedat : abp_lastchange_tstmpl external name "lastchangedat";
}
with federated data provided at runtime
</code></pre><UL class="lia-list-style-type-lower-roman"><LI>We need to create Writable External Entity for table zlm_transctns_ee</LI></UL><pre class="lia-code-sample language-abap"><code>@EndUserText.label: 'Writable EE for HANAtab zlm_transctns_ee'
define writable external entity zlm_transctns_cud_ee external name "zlm_transctns_ee"
{
key client : abap.char(3) external name "client";
key transactionuuid : sysuuid_x16 external name "transactionuuid";
membershipuuid : sysuuid_x16 external name "membershipuuid";
transactiondate : zlm_transactiondate_ee external name "transactiondate";
@Semantics.amount.currencyCode : 'transactioncurrency'
transactionvalue : zlm_transactionvalue_ee external name "transactionvalue";
transactioncurrency : zlm_transactioncurrency_ee external name "transactioncurrency";
loyaltypoints : zlm_loyaltypoints_ee external name "loyaltypoints";
@Semantics.user.createdBy: true
createdby : abp_creation_user external name "createdby";
@Semantics.systemDateTime.createdAt: true
createdat : abp_creation_tstmpl external name "createdat";
@Semantics.user.lastChangedBy: true
lastchangedby : abp_lastchange_user external name "lastchangedby";
@Semantics.systemDateTime.localInstanceLastChangedAt: true
locallastchangedat : abp_locinst_lastchange_tstmpl external name "locallastchangedat";
@Semantics.systemDateTime.lastChangedAt: true
lastchangedat : abp_lastchange_tstmpl external name "lastchangedat";
}
with federated data provided at runtime
</code></pre><UL><LI>To securely map a remote physical database object so it can be queried directly, we need to use STATIC EXTERNAL ENTITIES to fetch data from table zlm_membship_ee .</LI></UL><pre class="lia-code-sample language-abap"><code>@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Static EE for HANA tab zlm_membship_ee'
define external entity zlm_membship_ee external name "zlm_membship_ee"
{
key client : abap.char(3) external name "client";
key membershipuuid : sysuuid_x16 external name "membershipuuid";
membershipid : zlm_membershipid_ee external name "membershipid";
customer : zlm_customer_ee external name "customer";
@Semantics.user.createdBy: true
createdby : abp_creation_user external name "createdby";
@Semantics.systemDateTime.createdAt: true
createdat : abp_creation_tstmpl external name "createdat";
@Semantics.user.lastChangedBy: true
lastchangedby : abp_lastchange_user external name "lastchangedby";
@Semantics.systemDateTime.localInstanceLastChangedAt: true
locallastchangedat : abp_locinst_lastchange_tstmpl external name "locallastchangedat";
@Semantics.systemDateTime.lastChangedAt: true
lastchangedat : abp_lastchange_tstmpl external name "lastchangedat";
}
with federated data provided by zlm_ext_schema_ee
</code></pre><UL><LI>We need another STATIC EXTERNAL ENTITY for table zlm_transctns_ee</LI></UL><pre class="lia-code-sample language-abap"><code>@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Static EE for HANA tab zlm_transctns_ee'
define external entity zlm_transctns_ee external name "zlm_transctns_ee"
{
key client : abap.char(3) external name "client";
key transactionuuid : sysuuid_x16 external name "transactionuuid";
membershipuuid : sysuuid_x16 external name "membershipuuid";
transactiondate : zlm_transactiondate_ee external name "transactiondate";
@Semantics.amount.currencyCode : 'transactioncurrency'
transactionvalue : zlm_transactionvalue_ee external name "transactionvalue";
transactioncurrency : zlm_transactioncurrency_ee external name "transactioncurrency";
loyaltypoints : zlm_loyaltypoints_ee external name "loyaltypoints";
@Semantics.user.createdBy: true
createdby : abp_creation_user external name "createdby";
@Semantics.systemDateTime.createdAt: true
createdat : abp_creation_tstmpl external name "createdat";
@Semantics.user.lastChangedBy: true
lastchangedby : abp_lastchange_user external name "lastchangedby";
@Semantics.systemDateTime.localInstanceLastChangedAt: true
locallastchangedat : abp_locinst_lastchange_tstmpl external name "locallastchangedat";
@Semantics.systemDateTime.lastChangedAt: true
lastchangedat : abp_lastchange_tstmpl external name "lastchangedat";
}
with federated data provided by zlm_ext_schema_ee
</code></pre><H1 id="toc-hId--79375053">Key Takeaways.</H1><P>External entities enable real-time integration with external databases without replication.<BR /><BR /></P><DIV>In <A title="Building a RAP Application with External SAP HANA Cloud using CDS External Entities – Part 2" href="https://community.sap.com/t5/technology-blog-posts-by-sap/building-a-rap-application-with-external-sap-hana-cloud-using-cds-external/ba-p/14430950" target="_self">Part 2</A> of this series, we will build a RAP application using the data model created here.</DIV><P> </P><H1 id="toc-hId-493851525"> </H1><H1 id="toc-hId-297338020"> </H1><P> </P><P> </P><P> </P><P> </P>2026-07-08T10:49:55.174000+02:00https://community.sap.com/t5/abap-blog-posts/why-stock-fields-return-zero-in-custom-cds-views-on-marc-and-how-to-resolve/ba-p/14417444Why Stock Fields Return Zero in Custom CDS Views on MARC - and How to Resolve It2026-07-08T11:22:05.761000+02:00subhasmit_12369https://community.sap.com/t5/user/viewprofilepage/user-id/855662<P><STRONG>Why Stock Fields Return Zero in Custom CDS Views on MARC - and How to Resolve It</STRONG><BR /><BR />I was building a custom CDS view on the <STRONG>MARC</STRONG> table (Plant Data for Material) to extract data into <STRONG>SAP Datasphere</STRONG> using <STRONG>Change Data Capture (CDC)</STRONG> for delta loads.</P>
<P>After activating the view, I checked the data and found something odd. The field <STRONG>TRAME</STRONG> (Stock in Transit) had a proper value in the MARC table, but in my CDS view the same field was completely empty.</P>
<P>To give a concrete example, for one material and plant the MARC table showed <STRONG>TRAME = 50.000</STRONG>, but my CDS view showed <STRONG>TRAME = 0.000</STRONG> for the same key. All the master data fields were perfectly fine. Only the stock field was wrong.</P>
<P>That single clue — master data correct, stock field zero — is what pointed me to the real cause.</P>
<P><STRONG><BR />Where the data actually lives in S/4HANA</STRONG></P>
<P>In the older SAP ECC system, stock quantities were physically saved in many tables, and the same figure was often repeated in several places. This created redundancy and slowed things down.</P>
<P>In S/4HANA, SAP redesigned this part of the system with the <STRONG>New Simplified Data Model (NSDM)</STRONG>. The idea is straightforward: all stock movements are written into a single table called <STRONG>MATDOC</STRONG>, and the stock figures are <STRONG>calculated when you ask for them</STRONG> instead of being stored everywhere.</P>
<P>Because of this change, MARC became a so-called <STRONG>hybrid table</STRONG>. It still physically stores the material master and planning data, but the <STRONG>stock quantity fields are no longer filled in the table itself</STRONG>. Fields like TRAME, UMLMC, GLGMG and BWESB are now worked out on the fly from MATDOC whenever they are read.</P>
<P>So in S/4HANA, the TRAME column inside the physical MARC table is basically empty. The real stock-in-transit figure is calculated from MATDOC only at the moment it is needed.<BR /><BR /><STRONG>Why SE16 showed the value but my CDS did not</STRONG></P>
<P>This is the most important point of the whole story. SE16 and my CDS view were reading the same table through two completely different paths.</P>
<P>When you open MARC in <STRONG>SE16</STRONG>, the read goes through the normal application layer. SAP automatically <STRONG>redirects</STRONG> that read to a proxy object behind MARC, which performs the MATDOC calculation and returns the correct TRAME value. That is why SE16 happily showed 50.000.</P>
<P>My CDS view, on the other hand, was written as select from marc. A CDS view runs straight on the database and reads the <STRONG>physical MARC table directly</STRONG>. It never passes through the redirect, so it picked up the empty physical column and returned 0.000.</P>
<P>In one sentence:</P>
<P>SE16 reads MARC through the proxy and gets the calculated value. A CDS that selects directly from MARC reads the raw table and gets nothing. That difference in the read path was the entire reason the data "did not come."<BR /><BR /></P>
<P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="subhasmit_12369_0-1781252226540.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/421086iD5A8F7D68C03AB8B/image-size/medium?v=v2&px=400" role="button" title="subhasmit_12369_0-1781252226540.png" alt="subhasmit_12369_0-1781252226540.png" /></span></P>
<P><STRONG><BR />My first fix — and why it failed</STRONG><BR /><BR />My first idea was simple. If the proxy returns the correct value, why not read from the proxy instead of the table? So I changed the source of my view to the proxy object:<BR /><BR /><STRONG>Before (TRAME comes as zero):<BR /><BR /></STRONG>@AbapCatalog.sqlViewName: 'ZCDS_MARC_DEX'</P>
<P>@AbapCatalog.compiler.compareFilter: true</P>
<P>@AbapCatalog.preserveKey: true</P>
<P>@AccessControl.authorizationCheck: #NOT_REQUIRED</P>
<P>@EndUserText.label: 'Plant Data for Material'</P>
<P>@Metadata.ignorePropagatedAnnotations: true</P>
<P><a href="https://community.sap.com/t5/user/viewprofilepage/user-id/15206">@analytics</a>.dataExtraction:{enabled: true,</P>
<P>delta.changeDataCapture:{mapping:[</P>
<P>{table:'marc',role:#MAIN,</P>
<P>viewElement:['Matnr','Werks'],</P>
<P>tableElement:['matnr','werks']}]}}</P>
<P>define view ZCDS_MARC_DEX_CDC as select from marc</P>
<P>{</P>
<P> key matnr as Matnr,</P>
<P> key werks as Werks,</P>
<P> pstat as Pstat,</P>
<P> lvorm as Lvorm,</P>
<P> bwtty as Bwtty,</P>
<P> xchar as Xchar,</P>
<P> trame as Trame,</P>
<P><STRONG>... remaining MARC fields ...<BR /><BR /></STRONG><STRONG>After (TRAME correct and CDC activates):<BR /><BR /></STRONG>@AbapCatalog.sqlViewName: 'ZCDS_MARC_DEX'</P>
<P>@AbapCatalog.compiler.compareFilter: true</P>
<P>@AbapCatalog.preserveKey: true</P>
<P>@AccessControl.authorizationCheck: #NOT_REQUIRED</P>
<P>@EndUserText.label: 'Plant Data for Material'</P>
<P>@Metadata.ignorePropagatedAnnotations: true </P>
<P><a href="https://community.sap.com/t5/user/viewprofilepage/user-id/15206">@analytics</a>:{</P>
<P>dataExtraction.enabled: true,</P>
<P>dataExtraction.delta.changeDataCapture:{</P>
<P>mapping:[</P>
<P> {</P>
<P> table:'marc',</P>
<P> role:#MAIN,</P>
<P> viewElement:['Matnr','Werks'],</P>
<P> tableElement:['matnr','werks']</P>
<P> }]</P>
<P>}</P>
<P>}</P>
<P><STRONG>define view ZCDS_MARC_DEX_CDC as select from nsdm_e_marc</STRONG></P>
<P>{</P>
<P> key matnr as Matnr,</P>
<P> key werks as Werks,</P>
<P> pstat as Pstat,</P>
<P> lvorm as Lvorm,</P>
<P> bwtty as Bwtty, </P>
<P> xchar as Xchar,</P>
<P> trame as Trame,</P>
<P><STRONG>... remaining MARC fields ...<BR /></STRONG><BR />The only real change is the data source: from marc to nsdm_e_marc. The CDC mapping still refers to the physical table marc</P>
<P><STRONG><BR />This is not only a MARC problem</STRONG></P>
<P>The same behaviour happens with <STRONG>all NSDM stock tables</STRONG> in S/4HANA. If your CDS reads stock fields straight from any of these, you can get zeros:</P>
<UL>
<LI>MARC – plant stock fields (TRAME, UMLMC, GLGMG, BWESB)</LI>
<LI>MARD – storage location stock</LI>
<LI>MCHB – batch stock</LI>
<LI>MKOL – special / consignment stock</LI>
<LI>MSKA – sales order stock</LI>
<LI>MSKU – customer special stock</LI>
<LI>MSLB – stock with vendor (subcontracting)</LI>
<LI>MSPR, MSSA, MSSQ – project and sales order stock totals</LI>
<LI>MSTB, MSTE, MSTQ – stock in transit tables</LI>
</UL>
<P><BR />A simple rule of thumb: if a table held <STRONG>stock quantities</STRONG> in ECC, in S/4HANA those quantities are now calculated, and a direct CDS read will return zero. Use the table's<STRONG> proxy</STRONG> instead.<BR /><BR /><STRONG>How to find the correct proxy in your own system</STRONG></P>
<P>You do not have to guess the name. For any table (example: MARC):</P>
<OL>
<LI>Open the table in <STRONG>SE11</STRONG>.</LI>
<LI>Choose menu <STRONG>Extras → Replacement Object</STRONG> to see the assigned proxy (for MARC it is NSDM_E_MARC).</LI>
</OL>
<P><STRONG>Example</STRONG> – "<STRONG>MARC"</STRONG> Replacement Object</P>
<P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="subhasmit_12369_1-1781252226545.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/421085iF97E468158DFCD53/image-size/medium?v=v2&px=400" role="button" title="subhasmit_12369_1-1781252226545.png" alt="subhasmit_12369_1-1781252226545.png" /></span></P>
<P class=""><STRONG>Conclusion</STRONG></P>
<P class="">What first looked like a bug in my CDS view turned out to be normal S/4HANA behaviour. Under the New Simplified Data Model, stock quantity fields are no longer stored in tables like MARC — they are calculated from MATDOC only when they are read. SE16 shows the correct value because it goes through the replacement object, while a CDS view that reads the table directly picks up the empty physical column and returns zero.</P>
<P class="">The fix itself is small but important: source the CDS view from the replacement object (for MARC, NSDM_E_MARC) instead of the base table. After that one change, TRAME returned the correct value. And because this is standard NSDM behaviour, the same approach works for every stock table in the family — whenever a stock field comes back as zero, the first thing to check is whether you are reading the base table directly instead of its replacement object.</P>
<P class="">The bigger lesson I took away is to always confirm where a field's data actually lives before building a CDS view on top of a table. A quick look at SE11 → Extras → Replacement Object tells you whether a table is a hybrid table and which object you should really be reading from. That single check can save a lot of confusing "the value is there in SE16 but missing in my view" situations.</P>2026-07-08T11:22:05.761000+02:00https://community.sap.com/t5/abap-blog-posts/building-a-production-ready-custom-atc-check-enforcing-abap-unit-coverage/ba-p/14432249Building a Production-Ready Custom ATC Check: Enforcing ABAP Unit Coverage2026-07-09T05:13:31.489000+02:00douglasFarcichttps://community.sap.com/t5/user/viewprofilepage/user-id/1539144<H2 id="toc-hId-1819074951">Introduction</H2><P>Many development teams encourage ABAP Unit adoption, but enforcing minimum test coverage is still a challenge.</P><P>During a recent project, I needed a way to prevent the release of new developments that did not meet a minimum coverage threshold.</P><P>Since I couldn't find a standard ATC check that fulfilled this requirement, I decided to build a custom ATC validation.</P><P>The final solution became a lightweight and configurable quality gate that can be integrated directly into existing SCI and ATC processes.</P><H2 id="toc-hId-1622561446">Inspiration</H2><P>Before starting the implementation, I analyzed several open-source ATC extensions, especially the <A href="https://github.com/SAP/code-pal-for-abap" target="_blank" rel="noopener nofollow noreferrer">SAP Code Pal for ABAP</A> project.</P><P>Code Pal is an excellent reference for understanding how custom checks can be integrated into the ATC framework and how configurable validations can be implemented.</P><P>However, my goal was not to build a generic quality framework. Instead, I wanted a lightweight solution focused on a single requirement: enforcing a minimum ABAP Unit test coverage threshold.</P><P>For this reason, I implemented a simplified check that leverages the standard SCI/ATC framework and ABAP Unit coverage APIs while remaining easy to maintain and extend.</P><H2 id="toc-hId-1426047941">Understanding the Solution</H2><P>The solution is composed of three main components:</P><UL><LI>A custom ATC category</LI><LI>A custom ATC check</LI><LI>A configurable SCI/ATC variant</LI></UL><P>The execution flow is illustrated below:</P><PRE><CODE>SCI / ATC
↓
Custom Check
↓
ABAP Unit Coverage Analysis
↓
Threshold Validation
↓
ATC Finding</CODE></PRE><H2 id="toc-hId-1229534436">Creating a Custom Check Category</H2><P>The first step is to create a custom category that will group all checks.</P><P>Create a class that inherits from <CODE>CL_CI_CATEGORY_ROOT</CODE>.</P><PRE><CODE>METHOD constructor.
super->constructor( ).
description = TEXT-t01.
category = me->ci_category.
ENDMETHOD.</CODE></PRE><P>This category will later appear in the SCI administration screen and will act as a container for all custom validations.</P><H2 id="toc-hId-1033020931">Creating the Check Class</H2><P>Next, create the actual validation check by inheriting from <CODE>CL_CI_TEST_ROOT</CODE>.</P><P>In the constructor, define the basic metadata of the check:</P><UL><LI>Description</LI><LI>Category</LI><LI>Display position</LI><LI>Version</LI><LI>Error messages</LI></UL><PRE><CODE>METHOD constructor.
super->constructor( ).
description = `Minimum ABAP Unit Coverage`.
category = `Your Custom Category`.
position = `010`.
version += 1.
APPEND VALUE #(
sign = `I`
option = `EQ`
low = `1PRG`
) TO me->typelist.
APPEND VALUE #(
test = me->myname
code = `CI001`
kind = me->c_error
text = 'Insufficient coverage: &1% (min. &2%)'
) TO me->scimessages.
ENDMETHOD.</CODE></PRE><P>Once activated and registered in SCI, the category and the check should appear in the SCI management screen.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="New checks" style="width: 577px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/428570i96B9C90A7CA90DD3/image-size/large?v=v2&px=999" role="button" title="Captura de tela 2026-07-02 121428.png" alt="New checks" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">New checks</span></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Category and new check" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/428576i978B294095678741/image-size/large?v=v2&px=999" role="button" title="Captura de tela 2026-07-02 123343.png" alt="Category and new check" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Category and new check</span></span></P><H2 id="toc-hId-836507426">Adding Configuration Parameters</H2><P>One of the main goals of this implementation was to make the validation configurable.</P><P>Instead of hardcoding values, the minimum coverage threshold and object filters are maintained through the SCI variant.</P><P>To achieve this, I redefined the method <CODE>IF_CI_TEST~QUERY_ATTRIBUTES</CODE>.</P><P>This allows us to build a custom parameter screen such as:</P><UL><LI>Minimum Coverage (%)</LI><LI>Created After</LI><LI>Object Type</LI><LI>BAdI Implementations Only</LI><LI>RAP Behavior Implementations Only</LI></UL><PRE><CODE>METHOD if_ci_test~query_attributes.
DATA(attributes) = VALUE sci_atttab(
...
).
DATA(break) =
cl_ci_query_attributes=>generic(
p_name = me->myname
p_title = me->description
p_attributes = attributes
p_display = p_display ).
ENDMETHOD.</CODE></PRE><P>The resulting configuration screen looks like this:</P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Screen" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/428577iF47EA6BCEB7CE874/image-size/large?v=v2&px=999" role="button" title="Captura de tela 2026-07-02 123840.png" alt="Screen" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Screen</span></span></STRONG></P><H2 id="toc-hId-639993921">Persisting Variant Parameters</H2><P>The values entered by users need to be stored and restored whenever the variant is executed.</P><P>This is done by redefining the methods <CODE>GET_ATTRIBUTES</CODE> and <CODE>PUT_ATTRIBUTES</CODE>.</P><PRE><CODE>METHOD get_attributes.
EXPORT attributes_filled = attributes_filled
TO DATA BUFFER p_attributes.
ENDMETHOD.
METHOD put_attributes.
IMPORT attributes_filled = attributes_filled
FROM DATA BUFFER p_attributes.
ENDMETHOD.</CODE></PRE><H2 id="toc-hId-443480416">Implementing the Validation Logic</H2><P>The heart of every ATC check is the <CODE>RUN</CODE> method.</P><P>This method is executed for every analyzed object.</P><PRE><CODE>METHOD run.
CHECK me->program_name IS NOT INITIAL.
CHECK me->get( ) = me->c_true.
CHECK me->object_type IN me->attributes_filled-object_type.
CHECK me->is_after_minimum_creation_date( ) >=
me->attributes_filled-date_from.
DATA(percentage) = me->get_coverage( ).
IF percentage < me->attributes_filled-coverage_minimun.
inform(
p_sub_obj_type = me->c_type_include
p_sub_obj_name = me->program_name
p_kind = me->c_error
p_test = me->myname
p_code = `CI001`
p_param_1 = |{ percentage NUMBER = USER }|
p_param_2 = |{ me->attributes_filled-coverage_minimun NUMBER = USER }|
).
ENDIF.
ENDMETHOD.</CODE></PRE><H2 id="toc-hId-246966911">Measuring ABAP Unit Coverage</H2><P>One of the most interesting parts of this implementation was discovering that ABAP Unit coverage can be measured programmatically.</P><P>The class <CODE>CL_AUCV_TASK</CODE> provides the necessary APIs.</P><PRE><CODE>METHOD get_coverage.
DATA(aunit) =
cl_aucv_task=>create(
i_measure_coverage = abap_true ).
...
percentage =
branch_coverage->get_percentage( ).
ENDMETHOD.</CODE></PRE><P>This allows the ATC check to compare the actual coverage with the threshold configured in the SCI variant.</P><H2 id="toc-hId-50453406">Executing the Check</H2><P>After creating an SCI variant and selecting the custom check, simply configure the desired threshold.</P><P>For example:</P><UL><LI>Created After = 01.01.2025</LI><LI>Minimum Coverage = 85%</LI><LI>Object Type = CLAS</LI></UL><P><SPAN>First, let's measure the ABAP Unit coverage of a sample object</SPAN>:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="ABAP Unit" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/428581i308F285AFF4971FE/image-size/large?v=v2&px=999" role="button" title="Captura de tela 2026-07-02 124232.png" alt="ABAP Unit" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">ABAP Unit</span></span></P><P>When ATC is executed, findings are generated whenever the object's coverage is below the required percentage.</P><P><STRONG><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="ATC Result" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/428586iB81063B71CD50566/image-size/large?v=v2&px=999" role="button" title="Captura de tela 2026-07-02 130129.png" alt="ATC Result" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">ATC Result</span></span></STRONG></P><H2 id="toc-hId-201194258">Lessons Learned</H2><UL><LI>ATC is far more extensible than it initially appears.</LI><LI>Custom checks can be used to implement real governance requirements.</LI><LI>ABAP Unit coverage can be measured programmatically.</LI><LI>Configurable checks simplify gradual adoption.</LI><LI>Quality gates are an effective way to increase test adoption.</LI></UL><H2 id="toc-hId-4680753">Final Thoughts</H2><P>By combining the SCI framework, ATC extensibility and ABAP Unit coverage APIs, it is possible to build lightweight but powerful quality controls directly inside the SAP development process.</P><P>In addition to ATC execution, I also integrated this validation into the transport release process, ensuring that new developments cannot be released when they fail to meet the required coverage threshold.</P><P>Have you ever implemented a custom ATC validation in your landscape? Feel free to share your experience in the comments.</P>2026-07-09T05:13:31.489000+02:00https://community.sap.com/t5/enterprise-resource-planning-blog-posts-by-members/extending-the-fiori-app-display-supplier-list-f1861-a-practical-approach/ba-p/14423978Extending the Fiori App Display Supplier List (F1861): A Practical Approach Using CDS Views2026-07-09T19:17:38.648000+02:00douglasFarcichttps://community.sap.com/t5/user/viewprofilepage/user-id/1539144<H2 id="toc-hId-1818188040">Introduction</H2><P>Extending standard SAP Fiori applications is a common requirement in S/4HANA projects.</P><P>In a recent scenario, I needed to include additional supplier fields from table LFA1 into the standard app <A href="https://help.sap.com/docs/SAP_S4HANA_ON-PREMISE/3cb1182b4a184bdd93f8d62e3f1f0741/53d8475856c4a107e10000000a441470.html?locale=en-US&state=PRODUCTION&version=2025.001" target="_self" rel="noopener noreferrer">Display Supplier List (F1861)</A>. However, even though the fields existed in the backend, they were not available in the Fiori application.</P><H2 id="toc-hId-1621674535">The Challenge</H2><P>At first glance, extending a standard app may seem straightforward, but when dealing with CDS-based applications, simply adding fields at database level is not enough.</P><P>The F1861 app relies on CDS views and requires specific extension steps to properly expose additional fields.</P><H2 id="toc-hId-1425161030">SAP Note</H2><P>According to SAP Note <A href="https://me.sap.com/notes/3200905/E" target="_self" rel="noopener noreferrer">3200905</A>, extending standard CDS-based applications requires following a specific approach to ensure that custom fields are correctly exposed in both UI and analytical layers.</P><P><EM><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="3200905 - Display Supplier List: Standard extensibility delivered by View Entity" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/424437i8D06381C42111145/image-size/large?v=v2&px=999" role="button" title="Captura de tela 2026-06-21 121325.png" alt="3200905 - Display Supplier List: Standard extensibility delivered by View Entity" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">3200905 - Display Supplier List: Standard extensibility delivered by View Entity</span></span></EM></P><H2 id="toc-hId-1228647525">Approach Overview</H2><P>To address this, the following approach was implemented:</P><UL><LI>Extend the CDS view used as data source (C_Supplier)</LI><LI>Extend the consumption CDS view (C_SupplierList)</LI><LI>Apply UI annotations via Metadata Extension</LI></UL><H2 id="toc-hId-1032134020">Implementation</H2><P>The standard interface view <STRONG>C_Supplier</STRONG> was extended to include custom fields from table LFA1.</P><PRE>extend view C_Supplier with ZEXT_C_SUPPLIER
association [1..1] to lfa1 as _Supplier on $projection.supplier = _Supplier.lifnr
{
_Supplier.ort02 as ExtDistrictName,
_Supplier.brsch as ExtIndustry,
cast( _Supplier.gbdat as zext_gbdat preserving type ) as ExtBirthDate, // Custom data element used – standard conversion exit PDATE is not supported in CDS
_Supplier.txjcd as ExtTaxJurisdiction,
_Supplier.regss as SupplIsSocialInsuranceRegtrd,
_Supplier.actss as SocialInsuranceActivityCode,
_Supplier.cnae as ExtTaxEconomicActivityCode
}</PRE><P>A custom data element was created for the birth date field, as the standard conversion exit (PDATE) is not supported in CDS views. This allowed proper handling of the field without relying on conversion exits.</P><P>Next, the consumption view <STRONG>C_SupplierList</STRONG> was extended:</P><PRE>extend view C_SupplierList with ZEXT_C_SUPPLIERLIST
{
cast( '' as ort02_gp ) as ExtDistrictName,
cast( '' as brsch ) as ExtIndustry,
cast( '' as zext_gbdat ) as ExtBirthDate,
cast( '' as txjcd ) as ExtTaxJurisdiction,
cast( '' as j_1aregss preserving type ) as SupplIsSocialInsuranceRegtrd,
cast( '' as j_1aactss ) as SocialInsuranceActivityCode,
cast( '' as j_1bcnae ) as ExtTaxEconomicActivityCode
}</PRE><P>A metadata extension was then used to control the visibility of fields in the UI:</P><PRE>@Metadata.layer: #CORE
annotate view C_SupplierList with
{
@UI: { hidden: true }
BPTaxType;
@UI: { hidden: true }
VATRegistration;
@UI: { hidden: true }
TaxTypeName;
}</PRE><P>This approach ensures that the extension remains upgrade-safe and aligned with SAP extensibility guidelines.</P><H2 id="toc-hId-835620515">Result</H2><P>After the extensions and annotations, the custom fields were successfully displayed in the F1861 app.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Display Supplier List (new fields)" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/424439i9EE50296BB6A0583/image-size/large?v=v2&px=999" role="button" title="Captura de tela 2026-06-21 122331.png" alt="Display Supplier List (new fields)" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Display Supplier List (new fields)</span></span></P><H2 id="toc-hId-639107010">Challenges Faced</H2><P>Some challenges were encountered during the implementation:</P><UL><LI>Fields not appearing due to missing annotations</LI><LI>Issues with CDS associations</LI><LI>Inconsistent behavior when extending standard views</LI><LI>Limitations when reusing associations locally</LI></UL><H2 id="toc-hId-442593505">Key Learnings</H2><P>This scenario highlights several important aspects when working with SAP extensibility:</P><UL><LI>Understanding the CDS view hierarchy is essential</LI><LI>Metadata Extensions are required for UI exposure</LI><LI>SAP Notes often contain critical implementation details</LI></UL><H2 id="toc-hId-246080000">Final Thoughts</H2><P>This scenario demonstrates how standard SAP applications can be extended in a structured way, without modifying the core system, following clean core principles.</P><P>I would be interested to hear how other teams are handling Fiori extensibility scenarios.</P><P><span class="lia-unicode-emoji" title=":backhand_index_pointing_right:">👉</span>Feel free to share your approach or exchange ideas.</P>2026-07-09T19:17:38.648000+02:00https://community.sap.com/t5/enterprise-resource-planning-blog-posts-by-members/how-to-find-the-right-enhancement-spot-in-fiori-app-f3516-a-practical/ba-p/14424822How to Find the Right Enhancement Spot in Fiori App F3516: A Practical Validation Scenario2026-07-09T20:20:02.489000+02:00douglasFarcichttps://community.sap.com/t5/user/viewprofilepage/user-id/1539144<H2 id="toc-hId-1818216709">Introduction</H2><P>Validations are a common requirement in SAP Fiori applications. However, identifying the correct enhancement spot for a given app can be challenging.</P><H2 id="toc-hId-1621703204">The Challenge</H2><P>In this scenario, a validation was required in the Fiori app <A href="https://fioriappslibrary.hana.ondemand.com/sap/fix/externalViewer/#/detail/Apps('F3516')" target="_self" rel="nofollow noopener noreferrer">Manage Profit Centers (Version 2) - F3516</A> to ensure that the segment value followed specific business rules.</P><P>The main challenge was not implementing the validation itself, but identifying the correct enhancement point in the backend.</P><H2 id="toc-hId-1425189699">How the Enhancement Spot Was Identified</H2><P>A practical approach I often use is to identify the technical package behind the Fiori application.</P><P>This can be done by navigating to the Fiori Apps Library, checking the Implementation Information section, and identifying the OData service used by the application.</P><P>From there, the OData service can be searched in the ABAP environment (Eclipse), allowing identification of the corresponding package.</P><P>In this case, within the application package ODATA_PROFIT_CENTER_V2, an enhancement package with a very intuitive name was found:</P><P><STRONG>ODATA_PROFIT_CENTER_V2_ENH (Enhancements for Manage Profit Center)</STRONG></P><P><EM><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="CLASS CL_FIN_PC_VALIDATION_IMPL_EX" style="width: 553px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/424863i13EBC0D707524707/image-size/large?v=v2&px=999" role="button" title="Captura de tela 2026-06-22 143847.png" alt="CLASS CL_FIN_PC_VALIDATION_IMPL_EX" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">CLASS CL_FIN_PC_VALIDATION_IMPL_EX</span></span></EM></P><P><SPAN>Within this package, it was possible to identify available enhancement implementations. Among the options, the following example class was used as a reference:</SPAN></P><PRE>class CL_FIN_PC_VALIDATION_IMPL_EX definition
public
final
create public.
public section.
interfaces IF_BADI_INTERFACE.
interfaces IF_BADI_FIN_PC_VALIDATION.
protected section.
private section.
ENDCLASS.</PRE><PRE>CLASS CL_FIN_PC_VALIDATION_IMPL_EX IMPLEMENTATION.
method IF_BADI_FIN_PC_VALIDATION~EXECUTE.
data: ls_validationmessage like line of ct_messages.
ls_validationmessage-msgid = 'FAC_MPC_PCTR'.
ls_validationmessage-msgno = '022'.
ls_validationmessage-msgty = 'E'.
ls_validationmessage-msgv1 = 'The Field '.
ls_validationmessage-msgv2 = 'Profit Center Category '.
ls_validationmessage-msgv3 = 'contains invalid value '.
insert ls_validationmessage into table ct_messages.
endmethod.
ENDCLASS.</PRE><H2 id="toc-hId-1228676194">Implementation</H2><P>The validation logic was implemented to ensure that segment values starting with "0" are not allowed:</P><PRE>METHOD if_badi_fin_pc_validation~execute.
CONSTANTS: BEGIN OF segment_values,
geral TYPE fb_segment VALUE `GERAL`,
ato TYPE fb_segment VALUE `ATO`,
nao_ato TYPE fb_segment VALUE `NAO_ATO`,
END OF segment_values.
CHECK is_profit_center-profitcenterforedit+09(01) CA `012`.
DATA(segment) = SWITCH fb_segment( is_profit_center-profitcenterforedit+09(01) WHEN `0` THEN segment_values-geral
WHEN `1` THEN segment_values-ato
WHEN `2` THEN segment_values-nao_ato ).
IF is_profit_center-segment <> segment.
INSERT VALUE #( msgid = `ZFIN`
msgty = `E`
msgno = 001
msgv1 = segment ) INTO TABLE ct_messages.
ENDIF.
ENDMETHOD.</PRE><P>This validation logic was implemented within the BAdI execution method, ensuring that the business rule is enforced during the save process.</P><H2 id="toc-hId-1032162689">Result</H2><P>When the validation is triggered, the system prevents saving and displays an error message to the user.</P><P><EM><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Fiori error message" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/424871i441163AF38D917E9/image-size/large?v=v2&px=999" role="button" title="Captura de tela 2026-06-22 152237.png" alt="Fiori error message" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Fiori error message</span></span></EM></P><H2 id="toc-hId-835649184">Key Insight</H2><P>The most critical part of this implementation was identifying the correct enhancement point.</P><P>Once the correct spot was found, the validation itself was straightforward.</P><P>This reinforces that, in many SAP extensibility scenarios, the main challenge is not writing the logic itself, but navigating the framework to identify where that logic should be implemented.</P><H2 id="toc-hId-639135679">Final Thoughts</H2><P>This scenario highlights that, in many cases, the real challenge is not the implementation itself, but understanding where and how to implement it within the SAP framework.</P><P><span class="lia-unicode-emoji" title=":backhand_index_pointing_right:">👉</span>I would be interested to hear how others approach similar challenges.</P>2026-07-09T20:20:02.489000+02:00https://community.sap.com/t5/technology-blog-posts-by-members/making-interface-methods-optional-in-abap-default-ignore-vs-default-fail/ba-p/14420629Making Interface Methods Optional in ABAP: DEFAULT IGNORE vs DEFAULT FAIL2026-07-09T20:20:51.302000+02:00nvtnexthttps://community.sap.com/t5/user/viewprofilepage/user-id/1867561<H2 id="toc-hId-1818095630">Introduction</H2><P>If you've worked with OO ABAP for a while, you've probably hit this situation: you define an interface with a handful of methods, and suddenly every single class that implements it is forced to write a method body even for stuff that class doesn't care about. Multiply that across a dozen implementing classes and you end up with a pile of empty, do-nothing method stubs just to keep the compiler happy.</P><P>ABAP actually has a clean way around this, and it's one of those features that doesn't get talked about enough, the DEFAULT IGNORE and DEFAULT FAIL additions on interface method declarations. Once you know about them, you'll wonder how you lived without them.</P><P>Picture an interface for handling pricing logic. Something like:</P><pre class="lia-code-sample language-abap"><code>INTERFACE zif_pricing.
METHODS check_pricing_needed.
METHODS run_calculation
DEFAULT IGNORE.
METHODS fetch_base_amount
RETURNING VALUE(rv_amount) TYPE p
DEFAULT FAIL.
ENDINTERFACE.</code></pre><P>Not every class that plugs into zif_pricing will need all three methods. Maybe check_pricing_needed is genuinely required everywhere, but run_calculation only matters for a subset of classes, and fetch_base_amount is something you want classes to be forced to think about if they ever try to use it.</P><P>Rather than making every implementer write empty stubs, you can tell ABAP what should happen at runtime if a method is left unimplemented. That's what these two additions do, they shift the "what if this isn't implemented" decision from compile-time enforcement to a runtime behavior you control.</P><H3 id="toc-hId-1750664844">DEFAULT IGNORE: silently do nothing</H3><P>Tag a method with DEFAULT IGNORE and here's the deal: if a class skips implementing it, calling that method just... does nothing. No error, no dump, nothing. It behaves exactly as if someone had written an empty METHOD ... ENDMETHOD. block. Any returning parameter just comes back with its initial value, and the program keeps going like nothing happened.</P><P>This is great for the genuinely optional stuff things where "not implemented" and "nothing to do here" mean the same thing. Logging hooks, audit trail updates, optional enhancement points, extra notifications anywhere a no op is a perfectly acceptable outcome.</P><H3 id="toc-hId-1554151339">DEFAULT FAIL: blow up loudly instead</H3><P>DEFAULT FAIL is the opposite philosophy. If the implementing class doesn't provide a body for that method, calling it raises a runtime exception, specifically CX_SY_DYN_CALL_ILLEGAL_METHOD. Leave that exception unhandled and you'll get a short dump (CALL_METHOD_NOT_IMPLEMENTED).</P><P>This sounds harsh until you think about why you'd want it. There's a real difference between "this method isn't relevant for this class" and "this class genuinely needs this logic but someone forgot to write it." DEFAULT FAIL exists for the second case it converts a silent gap in your business logic into something that screams at you the moment it's hit, instead of quietly limping along and producing wrong results downstream.</P><P>Tax calculations, price determination, approval logic, validation anything where skipping the logic isn't a valid outcome, just a bug waiting to be found is a good candidate for DEFAULT FAIL.</P><H3 id="toc-hId-1357637834">Walking through it</H3><P>Define the interface with the optional methods marked accordingly:</P><pre class="lia-code-sample language-abap"><code>INTERFACE zif_pricing.
METHODS check_pricing_needed.
METHODS run_calculation
DEFAULT IGNORE.
METHODS fetch_base_amount
RETURNING VALUE(rv_amount) TYPE p
DEFAULT FAIL.
ENDINTERFACE.</code></pre><P>Implement it in a class, but only bother with the mandatory method:</P><pre class="lia-code-sample language-abap"><code>CLASS zcl_pricing DEFINITION.
PUBLIC SECTION.
INTERFACES zif_pricing.
ENDCLASS.
CLASS zcl_pricing IMPLEMENTATION.
METHOD zif_pricing~check_pricing_needed.
" actual business logic goes here
ENDMETHOD.
ENDCLASS.</code></pre><P>Notice there's no METHOD zif_pricing~run_calculation or METHOD zif_pricing~fetch_base_amount anywhere in this class and that's completely fine. The compiler only insists on an implementation for methods that don't carry a DEFAULT addition.</P><P>Call the IGNORE method and watch nothing bad happen:</P><pre class="lia-code-sample language-abap"><code>DATA(lo_pricing) = NEW zcl_pricing( ).
lo_pricing->zif_pricing~run_calculation( ).</code></pre><P>Since this one was never implemented but is marked DEFAULT IGNORE, the call just passes through quietly same as calling an empty method.</P><P>Call the FAIL method and you'll get an exception:</P><pre class="lia-code-sample language-abap"><code>DATA(lv_amount) = lo_pricing->zif_pricing~fetch_base_amount( ).</code></pre><P>Because fetch_base_amount is DEFAULT FAIL and was never implemented, this line throws CX_SY_DYN_CALL_ILLEGAL_METHOD. Leave it unhandled and the program dumps.</P><P>Handle it properly instead of letting it dump:</P><pre class="lia-code-sample language-abap"><code>TRY.
DATA(lv_amount) = lo_pricing->zif_pricing~fetch_base_amount( ).
CATCH cx_sy_dyn_call_illegal_method INTO DATA(lx_err).
MESSAGE lx_err->get_text( ) TYPE 'I'.
ENDTRY.</code></pre><P>Wrapping the call in a TRY/CATCH lets you turn that hard failure into a controlled message instead of a dump in production.</P><H3 id="toc-hId-1161124329">Why bother with DEFAULT FAIL at all — isn't IGNORE always safer?</H3><P>It feels safer on the surface, but that's actually the trap. Say you've got:</P><pre class="lia-code-sample language-abap"><code>METHODS send_notification DEFAULT IGNORE.</code></pre><P>If a class forgets to implement this, calling send_notification( ) just silently does nothing. No email goes out, no alert fires and the calling code has no idea anything went wrong. That's the kind of bug that sits undetected for months because everything looks fine from the outside.</P><P>Mark it DEFAULT FAIL instead, and a forgotten implementation gets caught the first time it's actually exercised, not three releases later when someone's wondering why customers never got their notification emails.</P><H4 id="toc-hId-1093693543">Rule of thumb for picking one</H4><P>Go with IGNORE when "not implemented" and "nothing happens" are an acceptable, sensible default logging, auditing, optional enrichment, extension hooks.</P><P>Go with FAIL when skipping the logic would produce incorrect or incomplete business behavior pricing, tax, approvals, workflow triggers, validations. Anywhere being wrong silently is worse than crashing loudly.</P><H4 id="toc-hId-897180038">A few things to keep in mind</H4><UL><LI>These additions only apply inside interface declarations you can't slap DEFAULT IGNORE or DEFAULT FAIL on a regular class method.</LI><LI>Constructors and test methods can't be made optional this way.</LI><LI>Both work fine whether the method is instance bound or static.</LI><LI>They're also usable in BAdI interface definitions, which is honestly where I think they shine the most BAdIs love having a long list of methods where only a couple are relevant to any given implementation.</LI></UL><H3 id="toc-hId-571583814">Bottom line</H3><P>DEFAULT IGNORE and DEFAULT FAIL give you a way to design genuinely flexible interfaces without sacrificing safety. Instead of forcing every implementer to write boilerplate empty methods, you decide upfront, right in the interface definition, what "not implemented" should mean for each method a harmless no op, or a loud, catchable failure. Used well, it keeps your interfaces lean and your bugs visible instead of buried.</P>2026-07-09T20:20:51.302000+02:00https://community.sap.com/t5/developer-news/sap-developer-news-july-9th-2026/ba-p/14436806SAP Developer News, July 9th, 20262026-07-09T21:00:00.015000+02:00qmacrohttps://community.sap.com/t5/user/viewprofilepage/user-id/53<H2 id="toc-hId-1819199754"><div class="video-embed-center video-embed"><iframe class="embedly-embed" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FrCaDZ93y1Kw%3Ffeature%3Doembed&display_name=YouTube&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DrCaDZ93y1Kw&image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FrCaDZ93y1Kw%2Fhqdefault.jpg&type=text%2Fhtml&schema=youtube" width="600" height="337" scrolling="no" title="WeAreDevelopers, cds 10, ABAP Cleaner, Code Connect streams, MCP Gateway, DYK25 | SAP Developer News" frameborder="0" allow="autoplay; fullscreen; encrypted-media; picture-in-picture" allowfullscreen="true"></iframe></div></H2><H2 id="toc-hId-1622686249">ITEMS</H2><P><STRONG>Live from WeAreDevelopers</STRONG></P><P>- WeAreDevelopers World Congress <A href="https://www.wearedevelopers.com/world-congress" target="_blank" rel="noopener nofollow noreferrer">https://www.wearedevelopers.com/world-congress</A></P><P><STRONG>CAP June 2026 release (cds 10)</STRONG></P><P>- Release notes <A href="https://cap.cloud.sap/docs/releases/2026/jun26" target="_blank" rel="noopener nofollow noreferrer">https://cap.cloud.sap/docs/releases/2026/jun26</A></P><P><STRONG>ABAP Cleaner in VS Code!</STRONG></P><P>- <A href="https://marketplace.visualstudio.com/items?itemName=SAPOSS.abap-cleaner" target="_blank" rel="noopener nofollow noreferrer">https://marketplace.visualstudio.com/items?itemName=SAPOSS.abap-cleaner</A></P><P><STRONG>Live streams at Code Connect next week</STRONG></P><P>- Code Connect <A href="https://code-connect.dev/" target="_blank" rel="noopener nofollow noreferrer">https://code-connect.dev/</A><BR />- UI5con <A href="https://openui5.org/ui5con/" target="_blank" rel="noopener nofollow noreferrer">https://openui5.org/ui5con/</A><BR />- UI5con agenda <A href="https://openui5.org/ui5con/program.html" target="_blank" rel="noopener nofollow noreferrer">https://openui5.org/ui5con/program.html</A><BR />- UI5con 2026 Live from the Main Stage <A href="https://www.youtube.com/live/CMPudw4scSE" target="_blank" rel="noopener nofollow noreferrer">https://www.youtube.com/live/CMPudw4scSE</A><BR />- reCAP <A href="https://recap-conf.dev/" target="_blank" rel="noopener nofollow noreferrer">https://recap-conf.dev/</A><BR />- reCAP agenda <A href="https://recap-conf.dev/program.html" target="_blank" rel="noopener nofollow noreferrer">https://recap-conf.dev/program.html</A><BR />- reCAP Live from the Main Stage <A href="https://broadcast.sap.com/go/reCAP" target="_blank" rel="noopener noreferrer">https://broadcast.sap.com/go/reCAP</A><BR />- reCAP 2026 - Streaming Sidetrack <A href="https://teams.microsoft.com/meet/347149883889697?p=ZkR4erzGjpPRtZ6zJh" target="_blank" rel="noopener nofollow noreferrer">https://teams.microsoft.com/meet/347149883889697?p=ZkR4erzGjpPRtZ6zJh</A></P><P><STRONG>Additional CAP highlights and MCP Gateway</STRONG></P><P>- Building MCP Servers with SAP Integration Suite: What to Design, Not Just How to Connect <A href="https://community.sap.com/t5/technology-blog-posts-by-sap/building-mcp-servers-with-sap-integration-suite-what-to-design-not-just-how/ba-p/14435261" target="_blank">https://community.sap.com/t5/technology-blog-posts-by-sap/building-mcp-servers-with-sap-integration-suite-what-to-design-not-just-how/ba-p/14435261</A><BR />- Design APIs and MCP servers <A href="https://help.sap.com/docs/integration-suite/isuite-integrations-and-apis/design-apis?locale=en-US" target="_blank" rel="noopener noreferrer">https://help.sap.com/docs/integration-suite/isuite-integrations-and-apis/design-apis?locale=en-US</A><BR />- Release calendar for SAP Integration Suite <A href="https://me.sap.com/notes/3418154" target="_blank" rel="noopener noreferrer">https://me.sap.com/notes/3418154</A></P><P><STRONG>Did You Know? #25 cds add test</STRONG></P><P>- The cds add command <A href="https://cap.cloud.sap/docs/tools/cds-cli#cds-add" target="_blank" rel="noopener nofollow noreferrer">https://cap.cloud.sap/docs/tools/cds-cli#cds-add</A></P><H2 id="toc-hId-1426172744">CHAPTER TITLES</H2><P>00:00 Intro<BR />00:07 Live from WeAreDevelopers<BR />02:16 CAP June 2026 release (cds 10)<BR />13:14 ABAP Cleaner in VS Code!<BR />14:37 Live streams at Code Connect next week<BR />15:05 Additional CAP highlights and MCP Gateway<BR />17:20 DYK #25 cds add test</P><H2 id="toc-hId-1229659239">TRANSCRIPT</H2><P>[Intro]<BR />This is the Developer News for July 9th 2026.</P><P>[Tom, Sheena, Shilpa, Witalij]<BR />Hi, we're coming to you this week from WeAreDevelopers conference in Berlin, which is a little bit of a difference for us developer advocates because we're actually mostly attending a conference instead of delivering one. So it's our opportunity to connect with other developers, particularly non-SAP developers from all around the world. I'm giving a session on Friday with Michael Ameling, where I'll be doing a preview of the new developers.sap.com that's all AI-powered - we'll show you more of in the coming weeks. What are the rest of you looking forward to?</P><P>Yeah we just now attended one session on Microsoft Fabric, it was really exciting, and we also got to know the latest advanced technologies that we can look forward to. So it was really exciting to be part of that session. The line was a little too long to get into the session.</P><P>That is the challenging part, to get into the sessions, but for me the interesting part is AI and agents because, it is not a surprise, but to be outside of the SAP ecosystem is what I'm interested in too, and get to learn more of what's happening outside of SAP.</P><P>So have you tried to find any sessions without AI or agents in the name?</P><P>No, all agents. I think that was the qualifier, probably. OK, and for me it's actually not the first time I'm attending this conference. I was here in 2019 and it is really good to be back here. This time SAP has a big presence here, we are actually one of the sponsors, we have our place on the show floor, we have our sessions as Thomas mentioned, he's going to do one with Michael Ameling but as well we have some other SAP colleagues delivering sessions based on the experience from their work, working with UI for example, and with user experience in this exciting AI era. So all in all, "no coffee, no code" but unfortunately the line for coffee is the longest one here, so if you don't see me coding this week, that's just because I cannot stand in this line and get my coffee.</P><P>[DJ]<BR />cds 10 is out! That is, the next major release of the SAP Cloud Application Programming Model, also known as cds 10, was published last week.</P><P>This particular major release marks many milestones and is packed full of goodness.</P><P>Within the limitations of these news items, I can only give a brief overview, and you should definitely head over to the release notes which are very readable and full of details.</P><P>Some of the features and highlights are marked as Alpha or Beta ... so please pay attention to these status badges when working through the content.</P><P>Now, like other releases, the notes for this release are organised into different categories. There's the main major release upgrade category of course, a set of important highlights, notes on changes and improvements for both the Node.js and Java runtimes, and some updates for multitenancy services as well.</P><P>So, let's start with the very essence of this major release - the upgrade and migration context, and what tht implies.</P><P>Each of the packages that make up the entire framework have had major release version upgrades.<BR />As the release notes say, don't mix old and new major versions. Instead, embrace change and try out the new cds upgrade tool which can help you.</P><P>The runtime support is also changing, with both Node.js and Java.</P><P>And before leaving this upgrade context, I must highlight the facilities that the CAP team have put together for this essential part of the software lifecycle - upgrades and migration. There's a new Migration Guide to help you get to cds 10 ... and a bleeding edge new 'cds upgrade' facility, in Alpha, to help with upgrades.</P><P>So next, let's have a look at some of the highlights, of which there are many in this release. Some of them are either in Alpha or Beta status, but they're there!</P><P>Let me enumerate them briefly. There's now support for aggregate data in hierarchies, useful for product catalogs, org charts, bills of materials and similar scenarios. It's available right now with the Java runtime, and support for Node.js is coming soon.</P><P>For VS Code users there's a new Project Explorer to help you visually navigate through your project and model's structures.</P><P>Now, while this has been hinted at before this advent of cds 10, there's a new protocol which I'm going to describe as "CAP native", and that's now available, and it's called HCQL - CQL conveyed over HTTP. Well suited for CAP-to-CAP integrations, and available just by adding an @hcql annotation, in the true CAP tradition of magic-made-simple.</P><P>There are early AI related goodies too, in the form of CAP-level (Calesi-style) agents, and also a CAP skills library, because, as we know, focusing on intent and best practice in development is essential.</P><P>There's a new Data Inspector, which comes in the form of a plugin and allows the controlled inspection of data in the entities exposed by your services.</P><P>Now, event queues in CAP have also been given lots of love, in the form of a new scheduling API, improved processing, and an overhaul of the documentation.</P><P>Now, last December we saw the first public Beta of the 'cds export' command which we can use to create API client packages from CDS service definitions. With this cds 10 release, that command is now generally available.</P><P>Now there are some more highlights in this cds 10 release, but my good friend and colleague Antonio is going to cover those in another news item in this news episode, so stay tuned!</P><P>Let me now turn to the Node.js runtime context where there are also plenty of items for us to celebrate.</P><P>First up, consolidated service APIs. What does that mean? Well, the generic CRUD (Create Read Update Delete) handler now returns the same shape of data for all write operations. That means app, db and HCQL-proxied remote services all look and behave the same way, which is great for uniform and minimised handler code variations.</P><P>Now, AI agents are great, but one thing they don't know much about is Fiori draft data. So working with active data has been simplified and consolidated - making it easier for everyone, us humans and our AI overlords, to work in a draft-first context.</P><P>A massive piece of work that the team has undertaken over the last months, culminating in what we have with cds 10, is a significant move towards a greater embrace of modern tools and native libraries. Very briefly - the testing framework Vitest is now used in favour of Jest, which will be abandoned longer term. ECMAScript Modules (that's ESM to you and me) is the official standardised system for packages and reuse, and CAP is now embracing that as the default module system. Third party dependencies are being dropped in favour of native or built-in alternatives. For example this calendar year already has seen a move to a Node-native SQLite driver (which replaces better-sqlite3) and to the Node-native Fetch API (which replaces Axios, and in development scenarios, also removes the need for the SAP Cloud SDK).</P><P>This work to embrace modern techniques, native libraries and the newest stable standards is fantastic. An important "side effect" is also something we can celebrate - a significantly reduced set of dependencies (and thus a smaller install footprint and code surface area).</P><P>Now last but certainly not least in the Node.js category is some news on the Telemetry plugin, which is now at version 2 after a major update which also brings support for OpenTelemetry SDK 2.0.</P><P>Next, let's look at the Java runtime category, which has now reached major version 5. Lots of new features, including, importantly, support for Spring Boot 4.</P><P>There are some new minimum versions of major dependencies that you need to take care of.</P><P>With CAP Java 5 there are some changes that are not backwards compatible (as in any major release), but the migration is made easier for us with a specific migration guide and OpenRewrite recipes for automated code adjustments.</P><P>Now, there are changes to CDS property defaults to align them with recommended settings for production use.</P><P>The API methods that were deprecated in the previous major release and marked as 'forRemoval' ... have now been removed.</P><P>CAP Java 5 now defaults to JDK 25, which is a long-term-support version. The SapMachine 25 JDK with the SAP Java buildpack is recommended.</P><P>With this new major CAP Java release, search is harmonised with both CAP Node.js and RAP, and by default uses the SAP HANA search syntax (for which there is now full support). Fuzzy search is also now enabled by default on SAP HANA, with improved support for UUIDs and large strings, and available in hierarchy queries.</P><P>Now, there's also much faster typed data access available. Instead of using a dynamic proxy to handle the underlying data map for accessor interfaces, it's now possible to have implementation classes generated. This resulting in up to 10 times the performance.</P><P>Previously, CAP Java used Apache's Olingo library for OData support. Following Olingo's retirement last year, there's now built-in support for OData, that's no mean feat! That of course also means fewer dependencies and it also brings improved performance.</P><P>There's also support for creating active versions of draft-enabled entities, similar to what we learned about earlier in the Node.js runtime context.</P><P>There are also plenty more features that come with CAP Java 5. Check them out in the release notes.</P><P>But to round out the release notes overview for this cds 10 version, there are a couple of points of note in the context of MTX services. First, there's now a stricter annotation validation for extensions. And second, migration support to go from <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/2302137">@SAP</a>/cds-mtx to <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/2302137">@SAP</a>/cds-mtxs has been removed.</P><P>That pretty much wraps up things for this June 2026 major release, congratulations to the entire CAP team for a huge set of new features and improvements. And don't forget to check out Antonio's item in this news episode for those other highlights.</P><P>[Rich]<BR />Hey friends, Rich Heilman here. I hope everyone is staying cool, staying out of the heat. Good news for ABAP developers this week. ABAP Cleaner is now available as a VS Code extension, bringing its powerful code formatting capabilities out of Eclipse and into the modern editor of choice for many developers. So, what does it do? ABAP Cleaner applies over 100 rules to your code with a single keyboard shortcut. Automatically cleaning up formatting, modernising syntax, and even flagging unused variables. The result is clean and consistent code across your entire team without anyone having to argue about style. You can run it as a quick one-shot format, or drop into interactive mode to choose exactly which rules apply to your codebase. If your team already has a configuration setup in Eclipse, you can import those rule variants directly. No need to start from scratch. The setup does a Java runtime and a bit of environment variable configuration, but once it's running, you get the same functionality that ABAP developers have relied on in ADT in Eclipse - now in a much lighter, faster editor. If you're doing ABAP development in VS Code, this one's worth installing. Check it out today.</P><P>[Ajay]<BR />Hello everyone. Code Connect is next week, from 13th to 16th July 2026. For all of you who cannot join us in person, there are live streams available for UI5con and reCAP, from the main stage. Please check out the agenda and streaming links available for UI5con and reCAP and join us online during the Code Connect event. Links to the live streams and agendas will be available in the description.</P><P>[Antonio]<BR />¡Hola, SAP Developers. As you already know, the June 2026 CAP release is huge. DJ has already shared many of the highlights and I just want to mention a couple more. There is a new AI plugin, in Alpha, which simplifies integration with SAP AI Core. It will automatically resolve service bindings, manage resource groups, and AI model deployments. And it provides a standard AI Core service to interact with AI Core programatically. The new Data Privacy plugin, in Beta, for Node.js, which provides out of the box integration with the SAP Data Privacy Integration Service. Based on the personal data and ILM annotations in the data model the plugin will automatically expose two endpoints that can be consumed by the service. Now, related to the integration space, CAP Node.js now supports the Event Mesh capability in SAP Integration Suite, as an alternative to the standalone SAP Event Mesh, meaning that you can now easily use it as an event broken in your CAP applications. There is the new MCP Protocol Adapter, which allows exposing existing CAP services to AI agents and LLM powered as just another protocol. Just install the plugin and annotate services with <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1914304">@McP</a>, et voila, your CAP service exposes MCP functionality. Extremely powerful and easy to implement. I already used it in a CAP service that I'm developing while I was getting familiar with the new feature of SAP Integration Suite. Yes, what we've all been waiting for - the new MCP Gateway is now available as part of Integration Suite. It is part of the new Integration Cell Runtime which is a cloud native runtime purposely built for designing, deploying and operating APIs and MCP servers. It is GA now and being rolled out in the Enhanced and Premium editions of SAP Integration Suite. Not just that, but it is also available in the BTP Trial environment. What are yoiu waiting for? Go check it out. Hasta luego!</P><P>[Ajay]<BR />Did you know that cds add does generate the best practices of the test implementation of your CAP service? One can rapidly create a sample CAP project with cds init bookshop --add sample. Run cds add test in the terminal to add test suite files for all the defined CAP services in your existing project. It creates the latest boilerplate files and structures required for you to get started with your test implementation in a jiffy. For each services it generates a sample test for the GET request for an entity and a test for any action defined in the service. This also adds the test dependencies to your project. It uses the Node test runner for the tests. Install your dependencies and just run npm t to execute your tests. The generated test implementation does need to be tweaked for the valid test data. CAP also provides a command npx cds test to mute the verbose server output and lets you focus only on the failing tests. Use -u to unmute the server output when you do not need them. Enjoy your CAP tests!</P><P> </P><P> </P>2026-07-09T21:00:00.015000+02:00https://community.sap.com/t5/abap-blog-posts/from-segw-to-odata-publish-expose-your-cds-view-as-odata-in-s-4hana/ba-p/14417142From SEGW to @OData.publish: Expose Your CDS View as OData in S/4HANA2026-07-09T21:00:02.399000+02:00rupalipunekar1234https://community.sap.com/t5/user/viewprofilepage/user-id/718463<H2 id="toc-hId-1817375896"><U>Introduction:</U></H2><DIV>This Blog2 is continuation of blog 1, refer below link:</DIV><DIV><A title="From SE11 to CDS: Build Your First CDS View in Eclipse ADT (S/4HANA Guide)" href="https://community.sap.com/t5/abap-blog-posts/from-se11-to-cds-build-your-first-cds-view-in-eclipse-adt-s-4hana-guide/ba-p/14406144" target="_self">Link to blog1</A> </DIV><DIV> </DIV><DIV>In Blog1, we created a CDS view using tables Sales Order Header (VBAK) and Sales Order Items (VBAP). <SPAN><SPAN>Now, in this Blog, we will make this data available for outside world. </SPAN></SPAN><DIV>In S/4HANA, CDS views are not just used for reporting - they can also be exposed as OData service, which allows them to be consumed by external systems, SAP Fiori applications, API and integrations.<DIV> <DIV><SPAN><SPAN>As an ABAP developer I have always used transaction code SEGW to manually create OData services. But now with CDS, this process is much simpler and faster.</SPAN></SPAN><H2 id="toc-hId-1620862391"> </H2><H2 id="toc-hId-1424348886"><U><SPAN>Lets see how to expose CDS view as OData : Step by Step:</SPAN></U></H2><H3 id="toc-hId-1356918100">Step 1: Add OData Annotation</H3><DIV>Open your CDS view and add anootation <SPAN><a href="https://community.sap.com/t5/user/viewprofilepage/user-id/1599241">@odata</a>.publish: true</SPAN></DIV><DIV><SPAN>Example below</SPAN></DIV></DIV></DIV></DIV></DIV><pre class="lia-code-sample language-abap"><code>@AbapCatalog.sqlViewName: 'ZSALEORDREP'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Creating my 1st CDS view'
@OData.publish: true
define view ZCDS_ORDVIEW
as select from vbak as Header
association [1..*] to vbap as Item
on Header.vbeln = Item.vbeln
{
key Header.vbeln as SalesOrder,
Header.erdat as CreationDate,
Header.netwr as NetAmount,
Header.waerk as Currency,
case Header.auart
when '00' then 'Standard Order'
else 'Other Order Type'
end as OrderTypeDescription,
Item
}</code></pre><DIV><H3 id="toc-hId-1160404595">Step 2: Activate the CDS View</H3><P>Press ctrl + F3 or icon activate to activate the CDS view. Once activated, SAP will generate the OData service with name <cdsviewname>_CDS.</P><P>In our example OData service name generated is ZCDS_ORDVIEW_CDS .</P><DIV><H3 id="toc-hId-963891090">Step 3: Activate the Service in SAP Gateway</H3><P>Even though the service is generated, it must be activated in gateway system. Login to your gateway system and follow below steps:</P><OL><LI>Go to transaction /n<STRONG>/IWFND/MAINT_SERVICE</STRONG></LI><LI>Click <STRONG>Add Service</STRONG></LI><LI>Enter system alias as: your system name</LI><LI>Search service: ZCDS_ORDVIEW_CDS .</LI><LI>Once its found, select the service and click button 'Add selected Services'.</LI><LI>Assign a package. In my case I used local package $TMP.</LI></OL><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-06-22 153411.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/424909iF359AEE02A44EF62/image-size/large?v=v2&px=999" role="button" title="Screenshot 2026-06-22 153411.png" alt="Screenshot 2026-06-22 153411.png" /></span><BR /><DIV class=""> </DIV><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Picture1.png" style="width: 936px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/421309i09268BF3C711DCBE/image-size/large?v=v2&px=999" role="button" title="Picture1.png" alt="Picture1.png" /></span></P><DIV class=""> </DIV><DIV class=""> </DIV><H3 id="toc-hId-767377585">Step 4: Test the OData Service</H3><DIV>To test the OData service, in gateway system run transaction code <STRONG>/n/IWFND/MAINT_SERVICE</STRONG> then it will list down all the services name under technical service name. Select your service ZCDS_ORDVIEW_CDS and click button SAP Client Gateway. This will open new screen SAP gateway client. Refer below screenshots:</DIV><DIV> </DIV><DIV class=""><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="rupalipunekar1234_0-1781306915883.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/421311iFD3F2441F7B714A1/image-size/large?v=v2&px=999" role="button" title="rupalipunekar1234_0-1781306915883.png" alt="rupalipunekar1234_0-1781306915883.png" /></span></DIV><DIV class=""> </DIV><DIV class=""><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="rupalipunekar1234_1-1781306931673.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/421312i70FBF8D0E4C5D5CA/image-size/large?v=v2&px=999" role="button" title="rupalipunekar1234_1-1781306931673.png" alt="rupalipunekar1234_1-1781306931673.png" /></span><P>$metadata shows full structure like Fields, types, associations</P><P>Example: Use the following URL to filter a specific sales order: /sap/opu/odata/sap/ZCDS_ORDVIEW_CDS/ZCDS_ORDVIEW?$filter=SalesOrder eq '00XXXXX178' Note: Ensure there are no spaces around the '=' in the $filter parameter.</P></DIV><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-06-22 154904.png" style="width: 961px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/424919i72F132C72FB2D53B/image-size/large?v=v2&px=999" role="button" title="Screenshot 2026-06-22 154904.png" alt="Screenshot 2026-06-22 154904.png" /></span><BR /><P> /sap/opu/odata/sap/ZCDS_ORDVIEW_CDS/ZCDS_ORDVIEW/$count</P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="rupalipunekar1234_3-1781306987058.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/421314i1CA15F7D26752100/image-size/large?v=v2&px=999" role="button" title="rupalipunekar1234_3-1781306987058.png" alt="rupalipunekar1234_3-1781306987058.png" /></span><P>You can also use different OData query options like Top 5 records: ...?$top=5, Sort data: ...?$orderby=CreationDate desc etc. These options help in optimizing data retrieval and are widely used in Fiori applications.</P><DIV><P>To test using URL, use below format. For testing I have used Postman :</P><P><SPAN><A target="_blank" rel="noopener">https://<host>/sap/opu/odata/sap/ZCDS_ORDVIEW_CDS/ZCDS_ORDVIEW?$top=</A>5</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2026-06-22 153620.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/424911i00FBCC29AB27D908/image-size/large?v=v2&px=999" role="button" title="Screenshot 2026-06-22 153620.png" alt="Screenshot 2026-06-22 153620.png" /></span></P><DIV> </DIV><DIV>The OData service can also be tested outside of SAP using tools like: - Browser, Postman or Curl Example: https://<host>/sap/opu/odata/sap/ZCDS_ORDVIEW_CDS/ZCDS_ORDVIEW?$top=5</DIV><P>When you add <CODE>@OData.publish: true</CODE>:</P><UL><LI>SAP automatically creates an OData service</LI><LI>Associations become navigation properties</LI><LI>CDS fields are exposed as OData properties</LI><LI>No manual service modeling is required</LI></UL><P>This is why CDS is preferred in modern development.</P><DIV><DIV><H2 id="toc-hId-441781361">Conclusion</H2><P>Exposing CDS view as an OData service shows how simple and powerful modern ABAP development has become. With just a single annotation, you can turn your data model into a consumable service ready for applications, APIs, and integrations. What once required manual effort in SEGW can now be achieved in minutes using CDS. This not only improves productivity but also ensures consistency between your data model and service layer.</P><DIV><H2 id="toc-hId-245267856">What’s Next?</H2><P>In the next step, we’ll enhance this CDS view with <STRONG>UI annotations</STRONG> and generate a <STRONG>Fiori application without writing frontend code</STRONG>.</P><H2 id="toc-hId-48754351">Let’s Discuss</H2><P class="lia-align-justify" style="text-align : justify;">Have you started exposing CDS views as OData services?</P><P class="lia-align-justify" style="text-align : justify;">Are you still using SEGW in your projects?</P><P class="lia-align-justify" style="text-align : justify;">Share your thoughts and experiences.</P></DIV></DIV></DIV></DIV></DIV></DIV>2026-07-09T21:00:02.399000+02:00https://community.sap.com/t5/technology-blog-posts-by-sap/building-a-conversational-ai-agent-in-s-4hana-without-leaving-the-abap/ba-p/14438104Building a Conversational AI Agent in S/4HANA — Without Leaving the ABAP Stack2026-07-10T20:00:49.797000+02:00david_lincourthttps://community.sap.com/t5/user/viewprofilepage/user-id/187510<P><EM>An experiment with two things at once: the yaai open-source ABAP addon and SAP AI Core as the LLM provider. The goal was to see whether a non-coder could wire an LLM directly into SAP S/4HANA — no external APIs, no middleware, and no writing a single line of code.</EM></P><HR /><H2 id="toc-hId-1819252607">How This Started</H2><P>I had two things I wanted to experiment with:</P><OL><LI><STRONG><A href="https://github.com/christianjianelli/yaai" target="_blank" rel="noopener nofollow noreferrer">yaai</A></STRONG> — an open-source ABAP addon by Christian Jianelli that lets you call LLMs from ABAP and register ABAP methods as tools a model can invoke. I wanted to understand what this actually meant in practice, not in theory.</LI><LI><STRONG>SAP AI Core</STRONG> — SAP's managed LLM platform on BTP. I had access to a running deployment and wanted to see how it behaved as the backend for an ABAP-native agent.</LI></OL><P>For the business scenario, I needed something simple — not because the scenario mattered, but because I wanted the complexity to come from the integration, not the domain. Batch management in <STRONG>SAP S/4HANA </STRONG>was the first thing that came to mind: logistics personnel ask the same questions every day (<EM>What's the shelf life expiration date on this batch? Which batches are about to expire?</EM>), the answers are all in standard SAP S/4HANA, and the data model is well understood.</P><P>All the ABAP code was written using <STRONG>Claude for Coding inside Visual Studio Code</STRONG>. I described what I needed, reviewed what came back, tested it in the SAP system, and fed errors back in. I did not write a single line of code. All this in <U>less than a day!</U>! My contribution was knowing what I wanted, understanding SAP well enough to validate the results, and a great deal of cutting and pasting.</P><BLOCKQUOTE><EM>All source code is available at <A href="https://github.com/davidlincourt-eng/yaai-batch-agent" target="_blank" rel="noopener nofollow noreferrer">github.com/davidlincourt-eng/yaai-batch-agent</A></EM></BLOCKQUOTE><HR /><H2 id="toc-hId-1622739102">What yaai Actually Is</H2><P><A href="https://github.com/christianjianelli/yaai" target="_blank" rel="noopener nofollow noreferrer">yaai</A> is a set of ABAP classes that lets you:</P><UL><LI>Call LLM APIs (OpenAI, Anthropic, Google, Mistral, Ollama, and SAP AI Core) from ABAP</LI><LI>Register any ABAP instance method as a "tool" the model can invoke during a conversation</LI><LI>Maintain multi-turn conversation history</LI><LI>Use system instructions to give the model a persona and scope</LI><LI>Run agents with tool calling through a UI</LI></UL><P>It comes with a companion application, <A href="https://github.com/christianjianelli/yaai_cockpit" target="_blank" rel="noopener nofollow noreferrer">yaai_cockpit</A>, which is a SAPUI5 app you deploy to your SAP S/4HANA system. It gives you a browser-based UI for configuring agents, registering tools, uploading prompt documents, and chatting with the agent — all without touching code.</P><HR /><H2 id="toc-hId-1426225597">Architecture in One Diagram</H2><PRE><CODE>User (browser)
│
▼
yaai_cockpit (SAPUI5, served from SAP S/4HANA)
│ /sap/yaai/agent (ICF REST)
▼
YCL_AAI_AGENT ──► ZCL_YAAI_AICORE_CONN ──► SAP AI Core (gpt-4.1)
│ (OAuth2 token) │
│ tool call │
▼ ▼
ZCL_YAAI_BATCH_TOOLS ZCL_YAAI_BATCH_TOOLS_PROXY
(reads MCH1, MARA, INOB, AUSP) (STRING → typed ABAP params)</CODE></PRE><P>Everything runs inside the SAP S/4HANA work process. The LLM decides what to ask; ABAP fetches the answer from the database; the cockpit shows the conversation.</P><HR /><H2 id="toc-hId-1229712092">The Key Advantage: No Published APIs</H2><P>In a conventional integration architecture, making SAP S/4HANA batch data available to an AI application means leveraging the S/4HANA primary standard API for the Batch Master Record (OData service API_BATCH_SRV). It allows external systems to synchronously read, create, and change batch data an OData or REST API.</P><P>With the yaai approach, <STRONG>the LLM calls ABAP methods directly, inside the same SAP S/4HANA system</STRONG>. In this case, there is a standard API... but it's not aways the case. That means there is no API to publish, no external endpoint to secure, and no data ever leaves the system boundary to reach the model uncontrolled. The LLM receives only what the tool method returns — a formatted string — not raw table data.</P><P>This removes an entire layer of integration and keeps the data access logic in the one place where it has always been: ABAP.</P><HR /><H2 id="toc-hId-1033198587">An Important Caveat: Security</H2><P>This experiment does not implement authorisation checks. The ABAP tool methods (<CODE>ZCL_YAAI_BATCH_TOOLS</CODE>) read directly from the SAP S/4HANA database without verifying that the calling user has the appropriate roles or authorisations.</P><P>In a production scenario this is a significant gap. The tool classes should enforce the same authorisation checks that the equivalent SAP S/4HANA transactions enforce — using <CODE>AUTHORITY-CHECK</CODE> statements against the relevant authorisation objects (e.g. <CODE>M_MSEG_WMB</CODE> for batch display). Without this, any user who can access the cockpit chat can query any batch in any plant, regardless of their SAP role.</P><P><STRONG>This is a proof of concept. Before deploying to a production or regulated SAP S/4HANA environment, authorisation checks must be added to every tool method.</STRONG></P><HR /><H2 id="toc-hId-836685082">What the Agent Can Answer</H2><P>Once deployed, a user can ask questions in plain language:</P><P>User question Tool called What happens</P><TABLE><TBODY><TR><TD><EM>"What is the SLED for batch 0000000045 of material TG22 in plant 1710?"</EM></TD><TD><CODE>GET_BATCH_HEADER</CODE></TD><TD>Reads <CODE>MCH1</CODE> for <CODE>VFDAT</CODE></TD></TR><TR><TD><EM>"What classification characteristics does that batch have?"</EM></TD><TD><CODE>GET_BATCH_CLASSIFICATION</CODE></TD><TD>Navigates <CODE>INOB → AUSP → CABN</CODE></TD></TR><TR><TD><EM>"Which batches of TG22 expire in the next 30 days?"</EM></TD><TD><CODE>FIND_EXPIRING_BATCHES</CODE></TD><TD>Queries <CODE>MCH1</CODE> with date window</TD></TR><TR><TD><EM>"List all expired batches for TG22 in plant 1710"</EM></TD><TD><CODE>FIND_EXPIRED_BATCHES</CODE></TD><TD>Filters <CODE>MCH1</CODE> where <CODE>VFDAT < today</CODE></TD></TR><TR><TD><EM>"Can you book a meeting for me?"</EM></TD><TD>—</TD><TD>Refused (system instructions scope it)</TD></TR></TBODY></TABLE><HR /><H2 id="toc-hId-640171577">Building It: The Five Moving Parts</H2><H3 id="toc-hId-572740791">1. The Connection Layer — ZCL_YAAI_AICORE_CONN</H3><P>SAP AI Core uses OAuth2 client credentials. Rather than storing a static API key, <CODE>ZCL_YAAI_AICORE_CONN</CODE> fetches a fresh Bearer token from XSUAA on every call and injects the required <CODE>AI-Resource-Group</CODE> header. The token is valid for ~12 hours; since it's fetched per-call, <STRONG>there is no manual key rotation</STRONG>.</P><P>Credentials are stored in TVARVC (transaction STVARV) — never hardcoded. See <A href="https://github.com/davidlincourt-eng/yaai-batch-agent/blob/main/batch_agent/SETUP_GUIDE.md#step-0--store-ai-core-credentials-in-tvarvc-stvarv" target="_blank" rel="noopener nofollow noreferrer">Step 0 of the Setup Guide</A> for the exact entries required.</P><HR /><H3 id="toc-hId-376227286">2. The Tool Classes — ZCL_YAAI_BATCH_TOOLS and its Proxy</H3><P>The business logic reads from SAP S/4HANA tables:</P><PRE><CODE>" Read batch header — SLED lives in MCH1, not MCHA
SELECT SINGLE matnr, charg, vfdat, hsdat, lwedt
FROM mch1
INTO @DATA(ls_mch1)
WHERE matnr = @i_matnr
AND charg = @i_charg.</CODE></PRE><BLOCKQUOTE><STRONG>Note:</STRONG> <CODE>VFDAT</CODE> (shelf life expiration date) is stored in <CODE>MCH1</CODE> (cross-plant batch table), not in <CODE>MCHA</CODE> (plant-level batch table). This is a common source of confusion — <CODE>MCHA.VFDAT</CODE> is always blank. Claude for Coding got this wrong on the first attempt and had to be corrected.</BLOCKQUOTE><P>Because the LLM passes parameters as strings, a proxy class (<CODE>ZCL_YAAI_BATCH_TOOLS_PROXY</CODE>) handles type conversion before delegating to the real class. This is a yaai pattern that prevents runtime conversion dumps when the model sends <CODE>"30"</CODE> where ABAP expects <CODE>TYPE i</CODE>.</P><!-- SCREENSHOT: SE24 showing ZCL_YAAI_BATCH_TOOLS class with the five methods visible --><P>The full source code for both classes is in the repository: <A href="https://github.com/davidlincourt-eng/yaai-batch-agent/blob/main/batch_agent/zcl_yaai_batch_tools.abap" target="_blank" rel="noopener nofollow noreferrer">ZCL_YAAI_BATCH_TOOLS</A> and <A href="https://github.com/davidlincourt-eng/yaai-batch-agent/blob/main/batch_agent/zcl_yaai_batch_tools_proxy.abap" target="_blank" rel="noopener nofollow noreferrer">ZCL_YAAI_BATCH_TOOLS_PROXY</A>.</P><HR /><H3 id="toc-hId-179713781">3. The Agent Persona — System Instructions and Tool Guide</H3><P>Two markdown files uploaded to the cockpit define how the agent behaves:</P><UL><LI><STRONG>System instructions</STRONG> — sets the persona ("SAP S/4HANA Batch Management Assistant"), defines scope, and enforces formatting rules (dates as DD.MM.YYYY, "not maintained" for blank characteristics)</LI><LI><STRONG>Tool usage guide</STRONG> — tells the LLM exactly which tool to call for which type of question, with a decision tree and parameter examples</LI></UL><P>This is the prompt engineering layer. The better these documents are, the more reliably the agent picks the right tool for a given question.</P><!-- SCREENSHOT: Cockpit Documents section showing the two uploaded .md files --><P>The two documents are in the repository: <A href="https://github.com/davidlincourt-eng/yaai-batch-agent/blob/main/batch_agent/docs/01_system_instructions.md" target="_blank" rel="noopener nofollow noreferrer">system instructions</A> and <A href="https://github.com/davidlincourt-eng/yaai-batch-agent/blob/main/batch_agent/docs/02_tool_usage_guide.md" target="_blank" rel="noopener nofollow noreferrer">tool usage guide</A>.</P><HR /><H3 id="toc-hId--92031093">4. The Cockpit — Configuring the Agent</H3><P>The yaai_cockpit provides a browser UI for wiring everything together: registering the LLM API endpoint, defining tools, uploading documents, and creating the agent — all without touching code.</P><!-- SCREENSHOT: Cockpit LLM APIs screen showing the OPENAI entry pointing to the AI Core deployment URL --><!-- SCREENSHOT: Cockpit Tools screen showing all five tool registrations --><!-- SCREENSHOT: Cockpit Agent detail screen showing tools and documents assigned --><P>The complete step-by-step cockpit configuration — LLM API setup, tool registration, document upload, and agent creation — is covered in <A href="https://github.com/davidlincourt-eng/yaai-batch-agent/blob/main/batch_agent/SETUP_GUIDE.md#step-3--configure-llm-api-cockpit--llm-apis" target="_blank" rel="noopener nofollow noreferrer">Steps 3 through 7 of the Setup Guide</A>.</P><HR /><H3 id="toc-hId--288544598">5. The Conversation</H3><P>With everything wired up, the agent is accessible via the cockpit's built-in chat panel or through any custom UI that calls the <CODE>/sap/yaai/agent</CODE> ICF endpoint on the SAP S/4HANA system. To see the conversation in action, the <A href="https://github.com/davidlincourt-eng/yaai-batch-agent" target="_blank" rel="noopener nofollow noreferrer">project repository</A> includes the full setup guide of the agent responding to batch management questions.</P><!-- SCREENSHOT: Cockpit chat panel — user asks &amp;quot;What is the SLED for batch 0000000045 of material TG22 in plant 1710?&amp;quot; --><P>Here is an example of a conversation in the Cockpit<BR /><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="chatbot_cockpit.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431740iCD6A7E19D9977CB2/image-size/medium?v=v2&px=400" role="button" title="chatbot_cockpit.png" alt="chatbot_cockpit.png" /></span></P><P> </P><!-- SCREENSHOT: Cockpit chat response showing the SLED date formatted as DD.MM.YYYY --><!-- SCREENSHOT: Cockpit chat — user asks &amp;quot;List all expired batches for TG22 in plant 1710&amp;quot; --><!-- SCREENSHOT: Cockpit chat response showing a list of expired batches with days-ago count --><!-- SCREENSHOT: Cockpit sequence diagram showing the tool call flow: User → Agent → FIND_EXPIRED_BATCHES → Agent → User --><HR /><H2 id="toc-hId--191655096">What Had to Be Fixed Along the Way</H2><P>Getting yaai to work with SAP AI Core required a few patches to the yaai framework classes. These were not in the original yaai documentation — they came out of debugging, and Claude for Coding was essential for working through them:</P><P>Issue Fix</P><TABLE><TBODY><TR><TD>AI Core returns 400 for Anthropic model deployments</TD><TD>Use a GPT deployment — SAP AI Core routes Anthropic and GPT through different API formats</TD></TR><TR><TD><CODE>"We're having a little trouble..."</CODE> fallback from yaai</TD><TD>yaai defaults to the Responses API (<CODE>/v1/responses</CODE>); SAP AI Core only supports Chat Completions — add <CODE>use_completions( abap_true )</CODE></TD></TR><TR><TD>Cockpit chat sends no response despite successful HTTP round-trip</TD><TD><CODE>YCL_AAI_ASYNC_CHAT_OPENAI</CODE> uses a static connection with no OAuth2 token and no <CODE>AI-Resource-Group</CODE> header — replace with <CODE>ZCL_YAAI_AICORE_CONN</CODE></TD></TR><TR><TD>STVARV uppercases credentials</TD><TD>Enable the <STRONG>Lowercase</STRONG> checkbox on each TVARVC entry — XSUAA credentials are case-sensitive</TD></TR><TR><TD>SLED always blank in responses</TD><TD><CODE>MCHA.VFDAT</CODE> is empty; shelf life dates live in <CODE>MCH1</CODE></TD></TR></TBODY></TABLE><HR /><H2 id="toc-hId--388168601">Reflections on the Experiment</H2><P>Two questions going in; two answers coming out.</P><P><STRONG>Does yaai work?</STRONG> Yes. The tool calling pattern is solid, the cockpit makes agent configuration accessible without code, and the conversation history and system instructions work as advertised. The framework is genuinely usable.</P><P><STRONG>Does SAP AI Core work as the backend?</STRONG> Yes, with caveats. It required patching two yaai framework classes and some non-obvious configuration (the <CODE>use_completions</CODE> flag, the <CODE>AI-Resource-Group</CODE> header, the OAuth2 token flow). None of these were documented anywhere — they came out of debugging. Once resolved, the integration was stable and the token refresh is fully automatic.</P><P><STRONG>Does the "no coder" approach work?</STRONG> Also yes, with one important qualification. I wrote zero lines of ABAP. Every class, every method, every fix was generated by Claude for Coding in Visual Studio Code. My job was to:</P><UL><LI>Describe the SAP S/4HANA data model and what I wanted the agent to do</LI><LI>Paste the code into SE24 and SE38 and run the syntax check</LI><LI>Copy error messages back to Claude and iterate</LI><LI>Know enough about SAP to recognise when the output was wrong</LI></UL><P>That last point matters more than it sounds. The <CODE>MCH1</CODE> vs <CODE>MCHA</CODE> issue — where shelf life dates are stored in the cross-plant batch table, not the plant-level one — was caught because I knew the data model well enough to question a blank SLED. Code generation quality was high enough that most errors were integration issues rather than logic errors. But you still need domain knowledge to validate the output.</P><P>The skill that mattered most was not coding. It was knowing SAP well enough to know what to ask for and whether the answer made sense.</P><HR /><H2 id="toc-hId--584682106">What's Next</H2><P>This experiment proves the pattern works. Natural extensions include:</P><P><STRONG>Security hardening</STRONG> — <CODE>AUTHORITY-CHECK</CODE> in every tool method is the immediate priority before this goes anywhere near a real system.</P><P><STRONG>More tools</STRONG> — The same pattern applies to stock quantities (<CODE>MCHB</CODE>), quality inspection lots (<CODE>QALS</CODE>), goods movements (<CODE>MSEG</CODE>), or any SAP S/4HANA data accessible from ABAP.</P><P><STRONG>RAG integration</STRONG> — yaai supports Retrieval-Augmented Generation. Storage regulations, handling instructions, or compliance documents stored as markdown can be injected into the model context automatically.</P><P><STRONG>Custom UI</STRONG> — The <CODE>/sap/yaai/agent</CODE> REST endpoint is available to any SAPUI5 or web application hosted on the SAP S/4HANA system. The cockpit chat is a reference implementation, not the only option.</P><HR /><H2 id="toc-hId--781195611">Resources</H2><UL><LI><A href="https://github.com/christianjianelli/yaai" target="_blank" rel="noopener nofollow noreferrer">yaai on GitHub</A> — the open-source ABAP AI addon by Christian Jianelli</LI><LI><A href="https://github.com/christianjianelli/yaai_cockpit" target="_blank" rel="noopener nofollow noreferrer">yaai_cockpit on GitHub</A> — the management and chat UI</LI><LI><A href="https://github.com/davidlincourt-eng/yaai-batch-agent" target="_blank" rel="noopener nofollow noreferrer">Full source code and setup guide</A> — everything from this experiment, including certificates, ABAP classes, step-by-step instructions, and screenshots</LI><LI><A href="https://help.sap.com/docs/sap-ai-core" target="_blank" rel="noopener noreferrer">SAP AI Core documentation</A> — the BTP LLM platform used as the model provider</LI></UL><HR /><H2 id="toc-hId--977709116">Thank You</H2><P>A big thank you to <STRONG>Christian Jianelli</STRONG> for building yaai and yaai_cockpit and making them freely available. Christian also helped me directly with the initial setup of both libraries — without that support this experiment would have taken considerably longer to get off the ground. The yaai project is a genuine contribution to the ABAP community and I hope this post encourages others to experiment with it.</P><P>If you want to see where yaai is headed, Christian's latest blog post is a great read: <A href="https://community.sap.com/t5/technology-blog-posts-by-members/yaai-abap-ai-tools-evolving-toward-agentic-ai/ba-p/14380980" target="_blank">yaai — ABAP AI Tools: Evolving Toward Agentic AI</A> on the SAP Community.</P>2026-07-10T20:00:49.797000+02:00https://community.sap.com/t5/technology-blog-posts-by-sap/start-remote-process-actions-in-btp-abap-via-task-chains-from-sap/ba-p/14440248Start remote Process/Actions in BTP ABAP via Task Chains from SAP Datasphere2026-07-14T16:00:19.634000+02:00stefan_geiselhart2https://community.sap.com/t5/user/viewprofilepage/user-id/200897<P>Modern cloud architectures allow for versatile and open interoperability. So does SAP Datasphere and SAP BTP ABAP, too. This example outlines some essentials how Datasphere can kick-off actions defined on the ABAP Cloud side, beyond system boundaries.</P><P>Starting a Task/Process in BTP ABAP remotely from SAP Datasphere using Task Chains opens up new scenarios for interoperability and integration. The goal is to orchestrate remote tasks initiated by SAP Datasphere — securely, programmatically, and fully automated.</P><P><U>We will cover the below points:</U></P><UL><LI>Creating a Task Chain in Datasphere including an API Call to ABAP Cloud</LI><LI>Connection in Datasphere to ABAP Cloud (for direct API call)</LI><LI>Setting up Communication System & Arrangement in ABAP Cloud</LI><LI>Executing the Task Chain in Datasphere: Trigger actions in ABAP Cloud</LI></UL><P> </P><H1 id="toc-hId-1690856170">1 Architecture Overview</H1><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Architecture" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/432878i8F8239641A83E39B/image-size/large?v=v2&px=999" role="button" title="abap_dsp_integration.png" alt="Architecture" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Architecture</span></span></P><P>The SAP Datasphere Task Chain API Task: Datasphere acts as the caller. ABAP Cloud exposes an endpoint (inbound Web Api) to trigger an action.</P><P>Option (2) and (3) complete the picture of possible solution approaches. Main differences as well as pros & cons are outlined further down in one of the last sections.</P><P><I>The Solution Architecture displays 3 different options:</I></P><UL><LI><STRONG>(1) Use Direct API Integration</STRONG> </LI><UL><LI>Straightforward</LI><LI>Minimal cost and complexity</LI><LI>Perfect for nightly batch orchestration, event-driven data loads, or simple API-driven analytical data refresh</LI></UL><LI><STRONG>(2) Integration Suite</STRONG></LI><UL><LI>Integration involves complex message transformations, protocol mediation, multiple target systems, or when centralized API governance and monitoring across the enterprise are required.</LI><LI>Especially appropriate where iFlow reusability justifies the additional cost and setup effort or when integration suite is already in place and a common tool.</LI></UL><LI><STRONG>(3) CAP Application </STRONG></LI><UL><LI>Custom application logic is needed beyond what a direct API call/iFlow can provide</LI><LI>E.g. multi-source data aggregation, advanced parsing, enrichments</LI><LI>Additional persistence required</LI><LI>Well-suited for reusable microservice-style integrations on BTP</LI></UL></UL><P> </P><H1 id="toc-hId-1494342665">2 Prerequisites</H1><P>You need</P><OL><LI>SAP Datasphere tenant with developer + admin access</LI><LI>Task Chain to design the flow of events</LI><LI>SAP BTP ABAP Environment (ABAP Cloud) with developer access</LI><LI>BTP ABAP: Authorization for OAuth clients, Communication Arrangements, ABAP development of Web APIs</LI></OL><P> </P><H1 id="toc-hId-1297829160"> 3 Creating Communication Artifacts in ABAP Cloud</H1><P><I>Navigation: </I>ABAP Environment Web Access → Communication Management → Communication Systems/Arrangements</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="AC01.png" style="width: 671px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/432907iB6C9E9BC32BA5CD0/image-size/large?v=v2&px=999" role="button" title="AC01.png" alt="AC01.png" /></span></P><P>Communication Arrangement</P><P> </P><DIV class=""><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Communication Arrangement" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/432919iAEFA982FB72455BD/image-size/large?v=v2&px=999" role="button" title="AC_arr_02.png" alt="Communication Arrangement" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Communication Arrangement</span></span></DIV><P>Communication System</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="comm_system2.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/433139i221029C9DC96B65D/image-size/large?v=v2&px=999" role="button" title="comm_system2.png" alt="comm_system2.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Communication System 1" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/432920i37EA414883B4DF96/image-size/large?v=v2&px=999" role="button" title="AC_cs_03.png" alt="Communication System 1" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Communication System 1</span></span></P><P><STRONG>Communication/Connection User:</STRONG></P><P>Create a User for Inbound Communication and use the same in the subsequent step on Datasphere level for the creation of a generic HTTP connection.</P><P> </P><H1 id="toc-hId-1101315655">4 ABAP Cloud Artifacts</H1><P>For the sake of simplicity I won't go into the details of all of the development artifacts and configuration settings.</P><P>For sure, you will create:</P><UL><LI>Inbound Service</LI><LI>Service Binding</LI><LI>Communication Scenario BTP ABAP</LI><LI>Service Definition</LI><LI>Entity</LI><LI>Class implementation</LI></UL><P>An example of an action definition processData (ZI_DEMO_SERVICE):</P><pre class="lia-code-sample language-abap"><code>managed implementation in class zbp_i_demo_service unique;
define behavior for ZI_DEMO_SERVICE alias DemoService
persistent table zdemoservice
lock master
{
field ( readonly ) Id;
field ( numbering : managed ) Id;
create;
update;
delete;
action processData result [1] zdemoservice;
mapping for zdemoservice
{
Id = id;
Name = name;
Description = description;
Status = status;
CreatedBy = created_by;
CreatedAt = created_at;
LastChangedBy = last_changed_by;
LastChangedAt = last_changed_at;
LocalLastChanged = local_last_changed;
}
}</code></pre><P>An example of an ABAP Class with an action implementation:</P><pre class="lia-code-sample language-abap"><code>CLASS lhc_DemoService DEFINITION INHERITING FROM cl_abap_behavior_handler.
PUBLIC SECTION.
PRIVATE SECTION.
METHODS processData FOR MODIFY
IMPORTING keys FOR ACTION DemoService~processData result result.
ENDCLASS.
CLASS lhc_DemoService IMPLEMENTATION.
METHOD processData.
" Your business logic implementation her
ENDMETHOD.
ENDCLASS.</code></pre><P>Service Definition:</P><pre class="lia-code-sample language-abap"><code>@EndUserText.label: 'Demo Service Definition'
define service ZUI_DEMO_SERVICE {
expose ZC_DEMO_SERVICE as DemoService;
}</code></pre><P>Inbound Service:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="inbound_serv.png" style="width: 464px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/432934i5E0A8AD179502CAF/image-size/large?v=v2&px=999" role="button" title="inbound_serv.png" alt="inbound_serv.png" /></span></P><P>Communication Scenario:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="comm_scen.png" style="width: 856px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/432932i4BA90F026F4EDA33/image-size/large?v=v2&px=999" role="button" title="comm_scen.png" alt="comm_scen.png" /></span></P><P> </P><H1 id="toc-hId-904802150">5 Create a Connection</H1><P>The first step is creating a generic HTTP connection to the endpoint exposed by ABAP Cloud. In order to do so, consider the following details. Take the connection host from the BTP ABAP instance key. The credentials must be taken from the connection user as defined in the communication arrangement.</P><P> </P><DIV class=""><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="connection_dsp.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/432911iDB1F955E4271E5E1/image-size/medium?v=v2&px=400" role="button" title="connection_dsp.png" alt="connection_dsp.png" /></span></DIV><P>An alternative to Username/Password is an OAuth based authentication mechanism. </P><P> </P><H1 id="toc-hId-708288645">6 Creating a Task Chain in SAP Datasphere</H1><P>The first step is defining a Task Chain that encapsulates the processing logic you want to execute .</P><P>In the given example:</P><UL><LI>The Task Chain starts with a API Task</LI><LI>Sends an email in case of success</LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Task Chain" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/432899i09D40BB9BF22D881/image-size/medium?v=v2&px=400" role="button" title="TC01.png" alt="Task Chain" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Task Chain</span></span></P><P><I>In the API Task details, define the following:</I></P><UL><LI><I>Method POST</I></LI><LI><I>API Path - the path to the service endpoint of your ABAP Web API that you want to trigger</I></LI><LI><I>Mode Synchronous</I></LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="API Task Details 1" style="width: 440px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/432900iFF0930533C259D5F/image-size/large?v=v2&px=999" role="button" title="TC02.png" alt="API Task Details 1" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">API Task Details 1</span></span></P><DIV class=""> </DIV><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="TC03.png" style="width: 460px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/432937iF3BCF25B02797E5E/image-size/large?v=v2&px=999" role="button" title="TC03.png" alt="TC03.png" /></span></P><P>Make sure to fetch the CSRF Token. The URL which I've used is simply the $metadata path of the service endpoint:</P><P><A href="https://%3cABAP_HOST%3e.abap.eu10.hana.ondemand.com/sap/opu/odata/sap/ZUI_DEMO_SERVICE_O4/$metadata" target="_blank" rel="noopener nofollow noreferrer">https://<ABAP_HOST>.abap.eu10.hana.ondemand.com/sap/opu/odata/sap/ZUI_DEMO_SERVICE_O4/$metadata</A></P><P> </P><H1 id="toc-hId-511775140">7 Execution Results</H1><P>The Task Chain in Datasphere successfully executed the ABAP Web API call:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Task Chain API successfully executed" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/432916i7B2C20887B641D53/image-size/large?v=v2&px=999" role="button" title="TC_EXEC.png" alt="Task Chain API successfully executed" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Task Chain API successfully executed</span></span></P><P>For monitoring and troubleshooting purpose, individual API calls can be traced from BTP ABAP side. The HTTP trace can be turned on for granular levels.</P><P> </P><H1 id="toc-hId-315261635">8 Solution Options - Comparisons</H1><P>The following comparison outlines the key aspects per solution/architecture option as depicted in the initial architecture diagram. I have prototyped all of the below and all options are working flawlessly. Especially w.r.t. to the CAP based solution, there is a wide open room to play with.</P><P> </P><TABLE><TBODY><TR><TD><P>Option</P></TD><TD><P>Pros (+)</P></TD><TD><P>Cons (-)</P></TD></TR><TR><TD><P><STRONG>(1) Direct API</STRONG></P></TD><TD><UL><LI>Simplest setup & fewest components & lowest cost</LI><LI>No middleware latency</LI><LI>Lightweight and developer-friendly</LI></UL></TD><TD><UL><LI>Limited transformation capability</LI><LI>Less suitable for multi-step or conditional routing logic</LI></UL></TD></TR><TR><TD><P><STRONG>(2) Integration Suite</STRONG></P></TD><TD><UL><LI>Supports complex transformations, multiple protocols and error handling in iFlows</LI><LI>Centralized API governance via API Management</LI><LI>Recommended for complex mediated flows</LI></UL></TD><TD><UL><LI>Two-step connectivity required (Integration Suite + Datasphere)</LI><LI>Additional licensing cost</LI><LI>Higher setup and maintenance effort</LI></UL></TD></TR><TR><TD><P><STRONG>(3) CAP CF App</STRONG></P></TD><TD><UL><LI>Maximum flexibility for custom logic (parsing, filtering, enrichment, retry)</LI><LI>CAP integrates natively with HANA Cloud/Datasphere HDI</LI><LI>Supports secure credential management</LI><LI>Reusable microservice pattern</LI></UL></TD><TD><UL><LI>Requires application development and BTP CF deployment skills</LI><LI>Higher operational overhead</LI><LI>More BTP resource consumption</LI><LI>CAP app lifecycle must be managed independently</LI></UL></TD></TR></TBODY></TABLE><P> </P><H1 id="toc-hId-118748130">9 Conclusion/Outlook & Further aspects:</H1><P>Overview of the major building blocks:</P><TABLE><TBODY><TR><TD><P>Capability</P></TD><TD><P>Result</P></TD></TR><TR><TD><P>No hardcoded secrets</P></TD><TD><P>via Communication Arrangements/System</P></TD></TR><TR><TD><P>Remote orchestration</P></TD><TD><P>Creating an end-to-end orchestrated chain of tasks, bidirectional if required</P></TD></TR><TR><TD><P>Cloud-native ABAP</P></TD><TD><P>Using appropriate ABAP Class APIs</P></TD></TR><TR><TD><P>Datasphere automation</P></TD><TD><P>Using Task Chain API</P></TD></TR></TBODY></TABLE><P> </P><P><STRONG>Use Cases that the implementation enables:</STRONG></P><UL><LI>Nightly batch orchestration</LI><LI>Event-driven data loads</LI><LI>Cross-system workflows (this was our ultimate focus)</LI><LI>API-driven (transactional/analytical) data refresh</LI></UL><P><STRONG>Limitations:</STRONG></P><UL><LI>The Task Chain/API Task can't be parameterized dynamically with runtime parameters to e.g. initiate calls that have a variable payload in header or body</LI><LI>Moreover, the write-back/storing of HTTP responses is limited too</LI></UL><P><STRONG>References:</STRONG></P><UL><LI>SAP Datasphere Task Chain API Documentation: <A href="https://api.sap.com/api/DatasphereTasks/overview" target="_blank" rel="noopener noreferrer">https://api.sap.com/api/DatasphereTasks/overview</A></LI><LI>SAP Datasphere Task Chain Help Page: <A href="https://help.sap.com/docs/SAP_DATASPHERE/c8a54ee704e94e15926551293243fd1d/274f2736465c4c48a091c675880502a2.html?locale=en-US" target="_blank" rel="noopener noreferrer">https://help.sap.com/docs/SAP_DATASPHERE/c8a54ee704e94e15926551293243fd1d/274f2736465c4c48a091c67588...</A></LI></UL><P>This blog entry complements my other blog on <A href="https://community.sap.com/t5/technology-blog-posts-by-sap/triggering-sap-datasphere-bdc-task-chains-from-sap-btp-abap-cloud-using-the/ba-p/14325528" target="_blank">Triggering SAP Datasphere/BDC Task Chains from SAP BTP ABAP Cloud using the Task Chain REST API</A>.</P><P>In case of questions feel free to raise them and please leave a comment if you found something incorrect - thanks for any help on that. I'm hoping this blog can support somebody out there and may facilitate some problem solving.</P>2026-07-14T16:00:19.634000+02:00https://community.sap.com/t5/technology-blog-posts-by-members/clean-core-levels-a-d-how-to-classify-your-custom-abap-and-what-to-do-with/ba-p/14437956Clean Core Levels A–D: how to classify your custom ABAP — and what to do with each grade2026-07-15T04:47:46.379000+02:00FelixFrenzel_CleanCore-2026https://community.sap.com/t5/user/viewprofilepage/user-id/2317473<P><EM>Disclosure: I'm the author of this post and the creator of Clean-Core.io, a free, non-commercial community tool I mention once near the end. This post is educational; the tool is optional.</EM></P><H2 id="toc-hId-1819230661">Overview</H2><P>With the 2025 update to the ABAP extensibility guide, SAP evolved the familiar 3-tier extensibility model into the <STRONG>clean core level concept</STRONG> — a four-grade classification of custom extensions: A, B, C, D. Instead of a blunt "clean vs. not clean", it tells you <EM>how closely</EM> each extension aligns with Clean Core, and it maps directly to ABAP Test Cockpit (ATC) behaviour:</P><P> </P><P>Level Usage of SAP objects in custom development ATC behaviour</P><TABLE border="1" cellspacing="0" cellpadding="6"><TBODY><TR><TD><STRONG>A</STRONG></TD><TD>Released SAP APIs (local & remote) and extension points</TD><TD>No message</TD></TR><TR><TD><STRONG>B</STRONG></TD><TD>Classic SAP APIs and extension points (SAP-recommended)</TD><TD>Priority 3 · info</TD></TR><TR><TD><STRONG>C</STRONG></TD><TD>Internal SAP APIs (conditionally clean via the changelog-for-SAP-objects check)</TD><TD>Priority 2 · warning</TD></TR><TR><TD><STRONG>D</STRONG></TD><TD>Not-recommended objects & extension technologies (modifications, implicit enhancements)</TD><TD>Priority 1 · error</TD></TR></TBODY></TABLE><P>Level A is the cleanest — on-stack ABAP Cloud or side-by-side on SAP BTP. Levels B–D describe classic ABAP, from SAP-recommended (B) down to not-recommended (D).</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="cleancore-blog-1-levels-A-D.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431680i45083165E5B3DA03/image-size/large?v=v2&px=999" role="button" title="cleancore-blog-1-levels-A-D.png" alt="cleancore-blog-1-levels-A-D.png" /></span></P><H2 id="toc-hId-1622717156">Why this matters now</H2><P>Every custom object you carry into S/4HANA has to be defensible. The move from a binary "clean/not clean" to A–D is a gift — it lets you transform at your own pace, prioritising the worst first instead of trying to reach "100% clean" overnight.</P><H2 id="toc-hId-1426203651">The real problem</H2><P>Knowing the model is easy. <STRONG>Grading thousands of custom objects against it is not.</STRONG> ATC flags readiness object-by-object, and the Cloudification Repository tells you which standard objects are released — but turning that into a per-object A/B/C/D verdict plus a remediation path, across a grown Z-landscape, is still mostly manual and inconsistent between teams.</P><H2 id="toc-hId-1229690146">A practical classification flow</H2><OL><LI><STRONG>Identify</STRONG> the custom object and what it touches (tables, APIs, function modules, enhancements).</LI><LI><STRONG>Look up</STRONG> each dependency: released API/extension point → A; classic-but-official API → B; internal SAP object → C; modification / not-recommended access → D.</LI><LI><STRONG>Decide remediation</STRONG> per grade: A keep · B keep, plan to lift later · C verify via the changelog-for-SAP-objects approach and wrap behind a released interface · D replace before the upgrade.</LI></OL><H2 id="toc-hId-1033176641">A worked example</H2><P>A classic <CODE>Z_CUSTOMER_REPORT</CODE>:</P><PRE>SELECT kunnr, name1 FROM kna1 INTO TABLE @lt_cust. " direct read of an internal standard table</PRE><P><STRONG>Classify:</STRONG> direct access to <CODE>KNA1</CODE> (an internal SAP object, not a released API) → Level C (ATC: warning). A direct <EM>write</EM> would be Level D (ATC: error).</P><P><STRONG>Remediate:</STRONG> map to the released CDS view <CODE>I_Customer</CODE> → the same logic becomes Level A (ATC: no message):</P><PRE>SELECT Customer, CustomerName FROM I_Customer INTO TABLE @lt_cust.</PRE><P>One dependency, one grade, one clear next step. Repeat across the landscape and you get a prioritised backlog: fix D first (upgrade blockers), lift C, schedule B, keep A.</P><H2 id="toc-hId-836663136">How I approached tooling this (optional)</H2><P>To avoid doing this by hand, I built Clean-Core.io — a free, non-commercial community tool. It runs a deterministic evidence engine first (parsing the code, mapping dependencies against the catalog), then AI on top, and derives an A–D grade per detected object — aligned to the clean core level concept and its ATC priorities. It is complementary to ATC/ADT, not a replacement, and every output is a draft for a qualified architect to review. Free: clean-core.io (link in the comments).</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="cleancore-blog-2-tool-panel.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431681i7192225E85F6F450/image-size/large?v=v2&px=999" role="button" title="cleancore-blog-2-tool-panel.png" alt="cleancore-blog-2-tool-panel.png" /></span></P><H2 id="toc-hId-640149631">Conclusion</H2><P>The move from 3-tier to A–D isn't a relabel — it's a better mental model for prioritising custom-code remediation. Give each dependency an explicit grade, start with your Level D objects, and turn "we have a lot of Z-code" into a defensible, upgrade-ready plan.</P><P><STRONG>How are you classifying your custom code against the new A–D levels today — by hand, ATC, or something else? I'd genuinely like to compare approaches in the comments.</STRONG></P>2026-07-15T04:47:46.379000+02:00https://community.sap.com/t5/technology-blog-posts-by-members/the-sap-fiscal-calendar-end-to-end-how-it-gets-populated-how-data-loads-in/ba-p/14441058The SAP Fiscal Calendar, End to End: How It Gets Populated, How Data Loads in BW, and Where the ABAP2026-07-15T11:53:20.719000+02:00amartya_ghosh2023https://community.sap.com/t5/user/viewprofilepage/user-id/838081<P>Every FI posting, every CO report and every BW query leans on the fiscal period — yet very few of us ever stop to trace where that period actually comes from and how it travels through the landscape. There is no "fiscal calendar load" job anywhere. So how does the fiscal calendar get populated, how does it function through every data load, and where does ABAP actually run in all of this? The short answer: it is born as configuration in ECC, derived onto every document at posting time, physically copied into BW as global settings, stamped onto every record BW extracts — and for the time characteristics themselves, served virtually by ABAP classes with no master data load at all. Let's walk through each stage.</P><H1 id="toc-hId-1690884070"><STRONG>Stage 1 — It starts as configuration, not data (OB29)</STRONG></H1><P>Fiscal calendars in ECC are controlled by the <STRONG>Fiscal Year Variant</STRONG>, configured via transaction <STRONG>OB29</STRONG> and used across FI, CO and MM. Nobody uploads fiscal calendar data — the moment a variant is defined and its periods maintained in OB29, the system populates a small family of Customizing tables behind the scenes:</P><TABLE width="602"><TBODY><TR><TD width="160"><P><STRONG>Table</STRONG></P></TD><TD width="442"><P><STRONG>Purpose</STRONG></P></TD></TR><TR><TD width="160"><P>T009</P></TD><TD width="442"><P>Fiscal year variant (header) — variant ID, number of posting periods, year-dependent flag, calendar year flag</P></TD></TR><TR><TD width="160"><P>T009B</P></TD><TD width="442"><P>Period dates per fiscal year variant — start/end date for each posting period (and special periods)</P></TD></TR><TR><TD width="160"><P>T009C</P></TD><TD width="442"><P>Assignment of company code shortened fiscal year (used when a fiscal year is shortened, e.g., mid-year go-live)</P></TD></TR><TR><TD width="160"><P>T009T</P></TD><TD width="442"><P>Fiscal year variant texts (descriptions)</P></TD></TR><TR><TD width="160"><P>T009Y</P></TD><TD width="442"><P>Fiscal year variant — year-dependent version (if the calendar-year-dependent flag is set, periods can differ by year)</P></TD></TR></TBODY></TABLE><P> </P><P>Two variants you will meet on almost every project: <STRONG>K4</STRONG> (calendar year — 12 posting periods plus 4 special periods, where period 001 = January) and <STRONG>V3</STRONG> (April to March — the standard variant for India and several other countries, where period 001 = April). K4 barely needs T009B at all because periods equal calendar months; V3 is where the real mechanics of the table come into play.</P><H2 id="toc-hId-1623453284"><STRONG>The year shift — the small entry that makes non-calendar fiscal years work</STRONG></H2><P>For a variant like V3, each month entry in T009B carries not only a period number but also a <STRONG>year shift (annual displacement) of -1, 0 or +1</STRONG>. This is the entry that tells the system which fiscal year a calendar month belongs to. Under V3, April through December carry shift 0 — a posting on 15.05.2026 lands in period 002 of fiscal year 2026. But January through March carry shift -1 — a posting on 15.01.2027 lands in period 010 of fiscal year 2026, because it still belongs to the fiscal year that started in April 2026. This one column is the entire secret behind non-calendar fiscal years, and it is exactly what downstream systems consume rather than recalculate.</P><P>One neighbouring concept worth separating out: the fiscal calendar is not the <STRONG>factory calendar</STRONG> (table TFACS, maintained via SCAL). The factory calendar defines working days and holidays for logistics and scheduling; the fiscal calendar defines posting periods for accounting. Both travel to BW as global settings, but they answer completely different questions.</P><H1 id="toc-hId-1297857060"><STRONG>Stage 2 — How the calendar reaches documents (assignment and derivation)</STRONG></H1><P>Configuration alone doesn't put a fiscal period on anything. The variant first has to be assigned, and then the period is derived at posting time.</P><TABLE width="602"><TBODY><TR><TD width="160"><P><STRONG>Table / Field</STRONG></P></TD><TD width="442"><P><STRONG>Context</STRONG></P></TD></TR><TR><TD width="160"><P>T001-PERIV</P></TD><TD width="442"><P>Company code's assigned fiscal year variant</P></TD></TR><TR><TD width="160"><P>CSKS / CEPC etc.</P></TD><TD width="442"><P>Controlling objects inherit the fiscal year variant from the company code</P></TD></TR><TR><TD width="160"><P>BKPF-MONAT / GJAHR</P></TD><TD width="442"><P>Posting period and fiscal year on FI documents, derived using T009B logic</P></TD></TR></TBODY></TABLE><P> </P><P>The derivation itself is simple: given a <STRONG>posting date plus the fiscal year variant</STRONG>, the system looks up T009B (applying the year shift) to determine which period the date falls into — periods 1 to 12, plus special periods 13 to 16 for adjustments and audit. This is done via standard function modules such as <EM>FIRST_DAY_IN_PERIOD_GET, LAST_DAY_IN_PERIOD_GET and DATE_TO_PERIOD_CONVERT</EM>. The result (MONAT, GJAHR) is stamped onto the document. Special periods are never derived from a date — periods 13 to 16 are entered manually by the user during year-end closing, which is why a posting date in March can sit in period 013.</P><P>In other words, the fiscal period on a document is not stored calendar data — it is computed once at posting time from the T009B rules and then persisted on the document itself. This detail is exactly what makes the BW side behave the way it does.</P><H1 id="toc-hId-1101343555"><STRONG>Stage 3 — How the fiscal calendar physically reaches BW: Transfer Global Settings</STRONG></H1><P>Here is the part most people miss. BW does not query ECC's T009 tables remotely — it holds its <STRONG>own local copy</STRONG> of them. When a source system is connected, the administrator runs <STRONG>Transfer Global Settings</STRONG> (in RSA1, right-click the source system). This function copies the source system's global Customizing — fiscal year variants (T009/T009B), currencies (TCUR*), units of measure (T006*) and factory calendars — into identically structured tables inside the BW system itself.</P><P>So the fiscal calendar is populated in BW not through a DataSource or an InfoProvider, but as replicated Customizing sitting quietly in BW's own T009/T009B. BW never uses these tables as reporting data — it uses them as the rulebook for time conversion and for query runtime logic, which we'll see below. This is also why the transfer has to be repeated whenever the variant configuration changes in the source: BW's copy does not update itself.</P><H1 id="toc-hId-904830050"><STRONG>Stage 4 — How the data load actually works in BW</STRONG></H1><P>With the rulebook in place, let's follow a transaction record end to end and see where fiscal time gets attached.</P><H2 id="toc-hId-837399264"><STRONG>Step 1: Extraction — the data arrives already stamped</STRONG></H2><P>Business Content extractors in FI/CO (for example the General Ledger line-item extractors) read the documents where MONAT and GJAHR were already stamped at posting time. So the DataSource delivers fields like <STRONG>FISCVARNT and FISCPER pre-populated by ECC</STRONG> — the extractor is simply forwarding the result of the T009B derivation that happened when the document was posted. Nothing fiscal is computed during extraction.</P><H2 id="toc-hId-640885759"><STRONG>Step 2: Staging and transformation — the classic load path</STRONG></H2><P>The record then follows the standard BW flow: DataSource → InfoPackage into the PSA → Transformation → DTP → target (DSO/ADSO or InfoCube). The transformation is where the source fields are mapped to the Time InfoObjects — FISCVARNT to 0FISCVARNT, FISCPER to 0FISCPER, the posting date to 0CALDAY, and so on.</P><H2 id="toc-hId-444372254"><STRONG>Step 3: Automatic time conversion — where BW's local T009B earns its keep</STRONG></H2><P>Time characteristics enjoy a special privilege in BW transformations: <STRONG>automatic time conversion and derivation</STRONG>. If the source supplies only a date (0CALDAY) plus the fiscal year variant, BW can derive 0FISCPER, 0FISCPER3 and 0FISCYEAR automatically — and it performs that derivation using its local copy of T009B, transferred in Stage 3. The same mechanism derives 0CALMONTH, 0CALQUARTER and 0CALYEAR from 0CALDAY. This is precisely why a stale Transfer Global Settings shows up as wrong fiscal periods in BW: the derivation is only as correct as the local rulebook.</P><H2 id="toc-hId-247858749"><STRONG>Step 4: Storage — where fiscal time finally lives in BW</STRONG></H2><P>Once loaded, the values settle into BW's own structures. In InfoCubes, each cube's time dimension table stores 0FISCPER, 0CALDAY and friends as dimension values, linked through SID tables; in DSOs/ADSOs they are simply fields on the record. If fiscal period hierarchies are built, they are stored like any hierarchy (e.g., /BI0/HFISCPER). From this point on, fiscal period is just another characteristic value — with one defined mapping into calendar dates, used mainly for display, sorting and hierarchy purposes.</P><TABLE width="602"><TBODY><TR><TD width="160"><P><STRONG>InfoObject</STRONG></P></TD><TD width="442"><P><STRONG>Purpose</STRONG></P></TD></TR><TR><TD width="160"><P>0FISCVARNT</P></TD><TD width="442"><P>Fiscal year variant (carried over from ECC's T009)</P></TD></TR><TR><TD width="160"><P>0FISCPER</P></TD><TD width="442"><P>Fiscal year/period combined (e.g., "2026001")</P></TD></TR><TR><TD width="160"><P>0FISCPER3</P></TD><TD width="442"><P>Fiscal period alone (3-char, e.g., "001")</P></TD></TR><TR><TD width="160"><P>0FISCYEAR</P></TD><TD width="442"><P>Fiscal year alone</P></TD></TR><TR><TD width="160"><P>0CALDAY</P></TD><TD width="442"><P>Calendar day</P></TD></TR><TR><TD width="160"><P>0CALMONTH</P></TD><TD width="442"><P>Calendar month (YYYYMM)</P></TD></TR><TR><TD width="160"><P>0CALWEEK</P></TD><TD width="442"><P>Calendar week</P></TD></TR><TR><TD width="160"><P>0CALQUARTER</P></TD><TD width="442"><P>Calendar quarter</P></TD></TR><TR><TD width="160"><P>0CALYEAR</P></TD><TD width="442"><P>Calendar year</P></TD></TR></TBODY></TABLE><P> </P><P>Two modelling details worth knowing here. First, <STRONG>0FISCPER is compounded to 0FISCVARNT</STRONG> — a period value like "001" is meaningless on its own, because period 001 is January under K4 but April under V3. The compounding forces every fiscal period value to carry its variant, which is why 0FISCVARNT must always be present (mapped or set as a constant) whenever 0FISCPER is filled in a transformation. Second, 0FISCPER is stored internally in the format YYYYPPP (e.g., 2026001) but displayed in external format (e.g., 001.2026) — a detail that regularly surprises people writing routines or filters against the raw value.</P><H1 id="toc-hId--77737475"><STRONG>Where does ABAP actually run during a BW load?</STRONG></H1><P>A common mental model is "BW has classes, and data loads from those ABAP classes." The reality is more precise, and worth getting right: the load is driven by BW objects — DataSources, InfoPackages, Transformations, DTPs — and ABAP classes are the machinery that BW generates or ships to execute some of them. The classes are the engine room, not the source of the data.</P><P>On the extraction side, the code is mostly <STRONG>function modules, not classes</STRONG>: Business Content extractors run extraction function modules through the Service API (SAPI), and generic extractors built in RSO2 are based on a table/view, an InfoSet or a function module.</P><P>On the transformation side, classes genuinely appear — but they are <STRONG>generated by the system</STRONG>. When a transformation is activated, BW generates an ABAP program containing a local class, and every routine you write — start routine, end routine, field routine, expert routine — becomes a method of that generated class, working on parameters like SOURCE_PACKAGE and RESULT_PACKAGE. You write the method body; BW generates and owns the class around it. The DTP then executes this generated program at load time. Underneath all of it, the DTP framework, request handling and ADSO activation are implemented in SAP standard classes (the CL_RS* family) — framework code you never touch.</P><P>And a note for newer stacks: in BW/4HANA, a transformation without ABAP routines can be HANA-optimized — pushed down and executed entirely inside HANA as a calculation scenario, with no ABAP class running during the load at all. This is exactly why avoiding ABAP routines is a standard performance recommendation in that generation.</P><H1 id="toc-hId-495489103"><STRONG>Why time characteristics have no master data load — virtual master data read classes</STRONG></H1><P>Open 0FISCYEAR in InfoObject maintenance and look at the Master data/texts tab, and you'll find the most elegant piece of this whole story. The setting <STRONG>Master Data Access</STRONG> is not "Default" — it is "Own Implementation", pointing to a <STRONG>master data read class: CL_RSMD_RS_0FISCYEAR</STRONG>.</P><P>"Default" would mean the InfoObject has physical master data tables (/BI0/P*, /BI0/T*) filled by data loads. "Own Implementation" means the opposite: the InfoObject has no stored master data at all. Whenever anyone needs its values — a query run, an F4 value help, a text display — the system calls this class at runtime and the values are generated on the fly. There is no DTP, no PSA, and no master data table filling up with a row for every year that has ever existed.</P><P>Why did SAP design it this way? Because fiscal years and periods are rule-based, not data-based. The set of valid fiscal years is trivially derivable, and fiscal periods are fully determined by the T009/T009B rules that BW already holds locally via Transfer Global Settings. Loading them as master data would mean materializing an infinite, rule-generated list. So SAP ships the time characteristics — 0FISCYEAR, 0FISCPER, 0CALDAY, 0CALMONTH and friends, each with its own CL_RSMD_RS_* class — with virtual master data access instead. The calendar was never data to begin with, and here that principle is implemented literally in code.</P><P>The distinction to keep sharp: transaction data still loads exactly as described in Stage 4 — the value "2026" arrives stamped on every record. It is only the master data of the time characteristics (the list of valid values, their texts, their ordering) that is never loaded, because the read class serves it virtually. Compare this with 0MATERIAL or 0CUSTOMER, whose master data is genuinely business-defined and must be loaded from the source via attribute and text DataSources. Time characteristics are the special case where SAP replaced the load with a class.</P><H1 id="toc-hId-298975598"><STRONG>Stage 5 — What happens at query runtime</STRONG></H1><P>The local T009B copy and the read classes come together at query runtime. The OLAP engine consults them whenever fiscal logic is needed: deriving the current fiscal period from today's date for a variable, calculating period offsets (previous period, same period last year), building year-to-date ranges, serving F4 value helps for fiscal years and periods, and sorting periods correctly — including keeping special periods 013–016 in their proper place after period 012. None of this would work if BW treated 0FISCPER as a plain text value; it works because BW knows, from its replicated T009B and its time-characteristic read classes, how periods relate to dates and to each other.</P><H1 id="toc-hId-102462093"><STRONG>The distinction that matters: source of truth vs consumer</STRONG></H1><P>Putting the stages together, the population story becomes very clear. ECC is the single source of truth: the fiscal calendar is populated there once, as Customizing in OB29, and applied millions of times, as period derivation on every posting. BW's fiscal calendar is populated twice over — once as replicated Customizing via Transfer Global Settings (the rulebook), and continuously as already-stamped values on every extracted record (the data). Its time characteristics need no master data load at all, because their read classes generate values from the rules. At no point does BW independently recalculate what ECC decided.</P><P>This has a practical consequence: if the variant configuration changes in ECC — a new period arrangement, a shortened fiscal year via T009C, a newly maintained year for a year-dependent variant — BW does not pick it up on its own. The global settings must be re-transferred, and only records loaded afterwards reflect the new rules. So when fiscal periods in BW look wrong, check in this order: was the period maintained in OB29 for the new year, were global settings re-transferred, and is the transformation mapping or deriving the time characteristics as expected. It is almost always one of these three — not a calculation error in BW.</P><TABLE width="602"><TBODY><TR><TD width="147"><P><STRONG>Aspect</STRONG></P></TD><TD width="228"><P><STRONG>ECC</STRONG></P></TD><TD width="228"><P><STRONG>BW</STRONG></P></TD></TR><TR><TD width="147"><P>Master config table</P></TD><TD width="228"><P>T009 (variant), T009B (period dates), maintained via OB29</P></TD><TD width="228"><P>Local replicated copy of T009/T009B via Transfer Global Settings — used for derivation, never for reporting</P></TD></TR><TR><TD width="147"><P>Characteristic / field</P></TD><TD width="228"><P>PERIV, MONAT, GJAHR</P></TD><TD width="228"><P>0FISCVARNT, 0FISCPER, 0FISCYEAR</P></TD></TR><TR><TD width="147"><P>Master data load</P></TD><TD width="228"><P>Not applicable — configuration, not data</P></TD><TD width="228"><P>None for time characteristics — served virtually by CL_RSMD_RS_* read classes ("Own Implementation")</P></TD></TR><TR><TD width="147"><P>Role</P></TD><TD width="228"><P>Source of truth — derives the period at posting time</P></TD><TD width="228"><P>Consumer — stores fiscal period as a reporting characteristic and derives only via the replicated rulebook</P></TD></TR><TR><TD width="147"><P>Special periods</P></TD><TD width="228"><P>Periods 13–16 (adjustment periods) supported in T009B, entered manually at closing</P></TD><TD width="228"><P>0FISCPER supports adjustment periods as additional period values, sorted after period 012</P></TD></TR></TBODY></TABLE><P> </P><H1 id="toc-hId--94051412"><STRONG>A note on newer stacks</STRONG></H1><P>In newer generations — BW/4HANA, or embedded analytics on S/4HANA — the same fiscal calendar is exposed through CDS views such as <EM>I_FiscalYearVariant</EM> and <EM>I_FiscalYearPeriod</EM>, rather than through the raw pool tables. The underlying logic is still the familiar T009-based configuration; only the access layer has been modernized.</P><H1 id="toc-hId--290564917"><STRONG>Wrapping up</STRONG></H1><P>So the next time someone asks "where does the fiscal period actually come from, and how does it work in BW?", the answer fits in a few lines: it is born as Customizing in OB29 (T009/T009B, with the year shift doing the heavy lifting for non-calendar years), derived onto every document at posting time, copied into BW as global settings, delivered pre-stamped on every extracted record, re-derived in transformations only when needed — always against BW's local rulebook — and served virtually at query runtime by master data read classes that generate fiscal values from rules instead of loading them. There is no fiscal calendar "load" because the calendar was never data to begin with — it is configuration that every downstream layer consumes, and in BW that principle goes so deep that even the master data is a class, not a table.</P><P>If you found this useful, I'd be glad to hear how fiscal year variants are handled in your landscape — especially anyone dealing with year-dependent variants or shortened fiscal years, where the population story gets more interesting.</P>2026-07-15T11:53:20.719000+02:00https://community.sap.com/t5/abap-blog-posts/ensuring-quality-in-badi-implementations-with-abap-unit/ba-p/14425727Ensuring Quality in BADI Implementations with ABAP Unit2026-07-16T11:16:13.843000+02:00douglasFarcichttps://community.sap.com/t5/user/viewprofilepage/user-id/1539144<H2 id="toc-hId-1818245544">Introduction</H2><P>In a previous article, I described how to identify and implement the BADI <A href="https://community.sap.com/t5/enterprise-resource-planning-blog-posts-by-members/how-to-find-the-right-enhancement-spot-in-fiori-app-f3516-a-practical/ba-p/14424822" target="_blank">FIN_PROFIT_CENTER_VALIDATION</A> to enforce business rules during Profit Center maintenance.</P><P>However, implementing a solution is only part of the job. Once the enhancement is in production, new requirements, bug fixes, and refactoring activities can easily introduce regressions if the validation logic is not properly tested.</P><P>This is where <STRONG>ABAP Unit</STRONG> becomes essential. By creating automated tests for enhancement implementations, we can verify business rules consistently and gain confidence when evolving the solution over time.</P><P>In this article, I will share a practical example of how I tested a BADI implementation using ABAP Unit based on a real-world validation scenario.</P><H2 id="toc-hId-1621732039">Why Testing a BAdI Matters</H2><P>BADI implementations often contain critical business logic. In many projects, this logic evolves gradually as new requirements are added. Without automated tests, every change introduces a risk of unexpected side effects.</P><P>The validation implemented in FIN_PROFIT_CENTER_VALIDATION ensures that the <STRONG>Segment</STRONG> value remains consistent with the last digit of the Profit Center. Whenever this rule is violated, an error message must be generated and the maintenance process must be blocked.</P><P>The business rule is relatively simple:</P><TABLE border="1"><TBODY><TR><TD><STRONG>Last Digit</STRONG></TD><TD><STRONG>Expected Segment</STRONG></TD></TR><TR><TD>0</TD><TD>GERAL</TD></TR><TR><TD>1</TD><TD>ATO</TD></TR><TR><TD>2</TD><TD>NAO_ATO</TD></TR></TBODY></TABLE><P>Although the rule itself is straightforward, it is a perfect candidate for automated testing because it contains clearly defined inputs and expected outcomes.</P><H2 id="toc-hId-1425218534">Test Class Design</H2><P>Before creating individual test cases, I structured the test class to maximize readability and reduce duplication. The objective was to make each test focus only on the business rule being verified.</P><P>The class uses standard <STRONG>setup</STRONG> and <STRONG>teardown</STRONG> methods to create and release the class under test. This guarantees that each test executes in isolation and avoids side effects from previous executions.</P><PRE><CODE>METHOD setup.
CREATE OBJECT me->f_cut.
ENDMETHOD.
METHOD teardown.
FREE me->f_cut.
REFRESH me->messages.
ENDMETHOD.</CODE></PRE><P>The BADI method expects a <CODE>FIN_ENH_PROFIT_CENTER</CODE> structure as input and returns validation messages through the <CODE>CT_MESSAGES</CODE> parameter. Since several test cases share the same execution flow, I introduced a helper method named <CODE>ASSERT_NO_VALIDATION_ERROR</CODE>.</P><P>This helper method prepares test data, executes the BADI, handles unexpected runtime exceptions, and verifies that no validation message was raised.</P><PRE><CODE>METHOD assert_no_validation_error.
" Given
DATA(profit_center_data) = VALUE fin_enh_profit_center( validityenddate = `19000101`
controllingareaforedit = `SI01`
profitcenterforedit = profitcenter
validityenddateforedit = `99991231`
validitystartdate = `20260623`
profitcentername = `Z999999999`
profitctrresponsiblepersonname = `DFARCIC`
profitcentercreationdate = `20260623`
profitcentercreatedbyuser = `DFARCIC`
profitcenterstandardhierarchy = `0101`
segment = segment ).
" When
TRY.
me->f_cut->if_badi_fin_pc_validation~execute( EXPORTING is_profit_center = profit_center_data
CHANGING ct_messages = me->messages ).
CATCH cx_ble_runtime_error INTO DATA(lx_error).
cl_abap_unit_assert=>fail( msg = lx_error->get_text( ) ).
ENDTRY.
" Then
cl_abap_unit_assert=>assert_initial( act = me->messages ).
ENDMETHOD.</CODE></PRE><P>Using a helper method significantly reduced code duplication and allowed the individual test methods to remain concise and focused on their specific scenario.</P><H2 id="toc-hId-1228705029">Implementing the Test Scenario</H2><P>To validate the implementation comprehensively, I created tests covering three different categories of behavior.</P><P>The first category verifies situations where the last digit of the Profit Center is not one of the supported values (0, 1, or 2). In these cases, the validation should simply be ignored.</P><PRE><CODE>METHOD ignore_when_last_digit_not_012.
...
ENDMETHOD.</CODE></PRE><P>The second category focuses on invalid combinations. In the following example, the Profit Center ends with 0, which means the expected Segment should be GERAL. Since the supplied value is ATO, the validation must generate an error message.</P><PRE><CODE>METHOD error_when_last_digit_is_0.
" Given
DATA(profit_center_data) = VALUE fin_enh_profit_center( validityenddate = `19000101`
controllingareaforedit = `SI01`
profitcenterforedit = `Z999999990`
validityenddateforedit = `99991231`
validitystartdate = `20260623`
profitcentername = `Z999999999`
profitctrresponsiblepersonname = `DFARCIC`
profitcentercreationdate = `20260623`
profitcentercreatedbyuser = `DFARCIC`
profitcenterstandardhierarchy = `0101`
segment = `ATO` ).
" When
TRY.
me->f_cut->if_badi_fin_pc_validation~execute( EXPORTING is_profit_center = profit_center_data
CHANGING ct_messages = me->messages ).
CATCH cx_ble_runtime_error INTO DATA(lx_error).
cl_abap_unit_assert=>fail( msg = lx_error->get_text( ) ).
ENDTRY.
" Then
DATA(expected_messages) = VALUE fin_enh_pc_message_t( ( msgid = `ZFIN`
msgty = `E`
msgno = 001
msgv1 = `GERAL` ) ).
cl_abap_unit_assert=>assert_equals( act = me->messages " Data object with current value
exp = expected_messages ). " Data object with expected type
ENDMETHOD.</CODE></PRE><P>Finally, positive test cases verify that valid combinations do not generate any validation messages.</P><PRE><CODE>METHOD validate_when_last_digit_is_1.
me->assert_no_validation_error(
profitcenter = 'Z999999991'
segment = 'ATO' ).
ENDMETHOD.</CODE></PRE><PRE><CODE>METHOD validate_when_last_digit_is_2.
me->assert_no_validation_error(
profitcenter = 'Z999999992'
segment = 'NAO_ATO' ).
ENDMETHOD.</CODE></PRE><H2 id="toc-hId-1032191524">Lessons Learned and Clean ABAP Considerations</H2><P>One interesting aspect of this exercise is how testability influenced the overall design of the solution. The need to create clear and maintainable tests encouraged the use of small methods, descriptive names, and reusable helper methods.</P><P>The resulting test class follows several Clean ABAP principles:</P><UL><LI>Small and focused test methods</LI><LI>Meaningful and descriptive names</LI><LI>Helper methods to eliminate duplication</LI><LI>Explicit use of <CODE>me-></CODE> for clarity</LI><LI>Minimal shared state between tests</LI></UL><P>Another takeaway is that even relatively small BADI implementations benefit from automated testing. The effort required to create the tests was modest, while the long-term benefits in maintainability and confidence are substantial.</P><H2 id="toc-hId-835678019">Final Thoughts</H2><P>Implementing a BAdI is only the first step. Ensuring that the implementation remains reliable over time is equally important.</P><P>ABAP Unit provided a simple and effective way to validate the business rules implemented in FIN_PROFIT_CENTER_VALIDATION while making future changes much safer.</P><P>If you are developing custom validations through enhancement spots or BAdIs, I strongly recommend investing a little extra time in automated tests—it pays off quickly.</P><P><span class="lia-unicode-emoji" title=":backhand_index_pointing_right:">👉</span>I would be interested to hear how other teams are testing their BAdI implementations and validation frameworks.</P>2026-07-16T11:16:13.843000+02:00https://community.sap.com/t5/technology-blog-posts-by-members/rap-augmentation-in-managed-scenario-enriching-transactional-requests/ba-p/14409354RAP Augmentation in Managed Scenario – Enriching Transactional Requests Before BO Processing2026-07-17T11:22:43.643000+02:00Abhi_0118https://community.sap.com/t5/user/viewprofilepage/user-id/1874843<H2 id="toc-hId-1816513912"><FONT face="arial,helvetica,sans-serif">Introduction</FONT></H2><P class="">The RESTful Application Programming Model (RAP) provides several extension points for implementing business logic, such as Determinations, Validations, Actions, and Prechecks. <STRONG>RAP Augmentation</STRONG> adds another extension point that allows developers to enrich incoming create or update requests before the framework starts processing the business object.</P><P class="lia-align-justify" style="text-align : justify;">This early execution makes augmentation useful for scenarios where default values, audit information, or business-specific data must be available before any further RAP processing takes place. In this blog, we will understand RAP Augmentation, compare it with Determinations, and implement it using an Employee Management example.</P><HR /><H4 id="toc-hId-1878165845"><FONT face="arial,helvetica,sans-serif">Business Requirement</FONT></H4><P class="">I had a requirement an Employee Management application where users create and maintain employee records. During record creation, the application should automatically populate business-specific information instead of relying on users to enter every value manually.</P><P class="lia-align-justify" style="text-align : justify;">The application should:</P><UL class="lia-align-justify" style="text-align : justify;"><LI>Set the employee status to <STRONG>PENDING_APPROVAL</STRONG>.</LI><LI>Determine whether approval is required based on the selected department.</LI><LI>Capture the current user as the creator.</LI><LI>Maintain audit information during updates.</LI></UL><P class="lia-align-justify" style="text-align : justify;">Instead of implementing all this logic inside the business object, we will use RAP Augmentation to enrich the incoming request before standard processing begins.</P><HR /><H5 id="toc-hId-1810735059"><FONT face="arial,helvetica,sans-serif">Problem Statement</FONT></H5><P class="">Determinations are commonly used in RAP to derive or update field values. However, they execute after the request has already entered the transactional buffer.</P><P class="lia-align-justify" style="text-align : justify;">In some business scenarios, values must be available even before the business object starts processing. For example, default values or audit fields may be required before validations or other business logic execute. In such cases, Augmentation provides a cleaner and more suitable solution by enriching the request at the beginning of the transaction.</P><HR /><H3 id="toc-hId-1356056116"><FONT face="arial,helvetica,sans-serif">What is RAP Augmentation?</FONT></H3><P class="">RAP Augmentation is an extension mechanism that runs during the Interactive Phase of a RAP transaction. It allows developers to enrich incoming create or update requests before the framework processes the business object.</P><P class="lia-align-justify" style="text-align : justify;">Rather than modifying persisted data, augmentation focuses on preparing the request by supplying additional values or applying business-specific logic. Once the request is enriched, RAP continues with its normal processing flow.</P><HR /><H5 id="toc-hId-1417708049"><U><FONT face="arial,helvetica,sans-serif">Augmentation Flow</FONT></U></H5><P class="">The request passes through augmentation before reaching the business object implementation. During this stage, additional values can be added or modified, ensuring the business object receives a complete request for further processing.</P><P>The overall execution flow is:</P><UL><LI>User sends a create or update request.</LI><LI>RAP invokes the registered augmentation.</LI><LI>The request is enriched with additional data.</LI><LI>Standard RAP processing continues.</LI><LI>Data is persisted to the database.</LI></UL><HR /><H4 id="toc-hId-1092111825"><U><FONT face="arial,helvetica,sans-serif">Augmentation vs Determination</FONT></U></H4><TABLE width="852px"><TBODY><TR><TD width="443.575px" height="57px">Defined at the <STRONG>Projection Behavior Definition</STRONG> using use create/update (augment).</TD><TD width="407.625px" height="57px">Defined at the <STRONG>Interface Behavior Definition</STRONG> using <STRONG>determination</STRONG>.</TD></TR><TR><TD width="443.575px" height="57px">Implemented in a Projection Behavior Implementation Class </TD><TD width="407.625px" height="57px">Implemented in the Behavior Pool class.</TD></TR><TR><TD width="443.575px" height="57px">Runs during the <STRONG>Interactive Phase</STRONG>, before the BO implementation processes the request.</TD><TD width="407.625px" height="57px">Runs during ON MODIFY or ON SAVE, after data enters the transactional buffer.</TD></TR><TR><TD width="443.575px" height="57px">Used to <STRONG>enrich or modify the incoming request</STRONG> before BO processing.</TD><TD width="407.625px" height="57px">Used to derive or recalculate values based on data in the transactional buffer.</TD></TR></TBODY></TABLE><H4 id="toc-hId-895598320">When Execution timing matter?</H4><P class="lia-align-justify" style="text-align : justify;">The main advantage of Augmentation is <STRONG>when</STRONG> it executes. Since it runs before business object processing, any values added during augmentation are available to the rest of the RAP processing flow.</P><UL><LI>If the application should automatically set an employee's status or determine whether approval is required, these values are already present when the framework performs subsequent processing. If the same logic were implemented in a Determination, the values would only be available later in the transaction.</LI></UL><H4 id="toc-hId-699084815"><U><FONT face="arial,helvetica,sans-serif">When to Use Augmentation?</FONT></U></H4><P class="">Augmentation is a good choice when the incoming request needs to be enriched before RAP starts processing the business object.</P><P class="lia-align-justify" style="text-align : justify;">Typical use cases include:</P><UL class="lia-align-justify" style="text-align : justify;"><LI>Setting default values.</LI><LI>Populating audit fields.</LI><LI>Deriving values from user input.</LI><LI>Performing lightweight request enrichment.</LI><LI>Preparing data required by later processing steps.</LI></UL><P class="lia-align-justify" style="text-align : justify;">It is not intended to replace Determinations, which remain the preferred option for business logic that should execute after the request has entered the transactional buffer.</P><P> </P><H4 id="toc-hId-502571310"><FONT size="4"><U><FONT face="arial,helvetica,sans-serif">BDEF of Interface</FONT></U></FONT></H4><pre class="lia-code-sample language-abap"><code>managed implementation in class zbp_aky_i_emp unique;
strict ( 2 );
define behavior for zaky_i_emp //alias <alias_name>
persistent table zaky_t_emp
lock master
authorization master ( instance )
//etag master <field_name>
{
create( authorization : global ) ;
update;
delete;
action Approve result [1] $self;
mapping for zaky_t_emp
{
Employeeid = employeeid;
Firstname = firstname;
Lastname = lastname;
Department = department;
Status = status;
Approvalrequired = approvalrequired;
Createdby = createdby;
Createdat = createdat;
Lastchangedby = lastchangedby;
Lastchangedat = lastchangedat;
}
}</code></pre><HR /><H4 id="toc-hId-306057805"><FONT size="4"><U><FONT face="arial,helvetica,sans-serif">BDEF of Projection</FONT></U></FONT></H4><pre class="lia-code-sample language-abap"><code>projection implementation in class zbp_aky_c_emp unique;
strict ( 2 );
define behavior for zaky_c_emp //alias <alias_name>
{
use create( augment );
use update( augment );
use delete;
field ( readonly ) Status;
field ( readonly ) Approvalrequired;
field ( readonly ) Createdby;
field ( readonly ) Createdat;
field ( readonly ) Lastchangedby;
field ( readonly ) Lastchangedat;
use action Approve;
}</code></pre><HR /><H4 id="toc-hId--388172795"><U><FONT face="arial, helvetica, sans-serif" size="4">BP of Projection</FONT></U></H4><pre class="lia-code-sample language-abap"><code>CLASS lhc_zaky_c_emp DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS augment_create FOR MODIFY
IMPORTING entities FOR CREATE zaky_c_emp.
METHODS augment_update FOR MODIFY
IMPORTING entities FOR UPDATE zaky_c_emp.
ENDCLASS.
CLASS lhc_zaky_c_emp IMPLEMENTATION.
METHOD augment_create.
LOOP AT entities INTO DATA(entity).
IF entity-Department IS INITIAL.
APPEND VALUE #(
%cid = entity-%cid
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Department is mandatory' ) )
TO reported-zaky_c_emp.
APPEND VALUE #( %cid = entity-%cid )
TO failed-zaky_c_emp.
CONTINUE.
ENDIF.
MODIFY AUGMENTING ENTITIES OF zaky_i_emp
ENTITY zaky_i_emp
CREATE FIELDS ( Status Approvalrequired Createdby Createdat )
WITH VALUE #( (
%cid = entity-%cid
Status = 'PENDING_APPROVAL'
Approvalrequired = COND #(
WHEN entity-Department = 'HR'
OR entity-Department = 'FIN'
THEN abap_true
ELSE abap_false )
Createdby = sy-uname
Createdat = cl_abap_context_info=>get_system_date( )
) ).
ENDLOOP.
ENDMETHOD.
METHOD augment_update.
LOOP AT entities INTO DATA(entity).
MODIFY AUGMENTING ENTITIES OF zaky_i_emp
ENTITY zaky_i_emp
UPDATE FIELDS ( Lastchangedby Lastchangedat )
WITH VALUE #( (
Employeeid = entity-Employeeid
Lastchangedby = sy-uname
Lastchangedat = cl_abap_context_info=>get_system_date( )
) ).
ENDLOOP.
ENDMETHOD.
ENDCLASS.</code></pre><H4 id="toc-hId--584686300"><FONT size="4"><U><FONT face="arial,helvetica,sans-serif">BP of interface</FONT></U></FONT></H4><pre class="lia-code-sample language-abap"><code>METHOD Approve.
" Read current status of the employee
READ ENTITIES OF zaky_i_emp IN LOCAL MODE
ENTITY zaky_i_emp
FIELDS ( Status Employeeid )
WITH CORRESPONDING #( keys )
RESULT DATA(employees)
FAILED DATA(read_failed).
" Loop and update status
LOOP AT employees INTO DATA(employee).
" Only approve if current status is PENDING_APPROVAL
IF employee-Status <> 'PENDING_APPROVAL'.
APPEND VALUE #(
%tky = employee-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Only records with PENDING_APPROVAL status can be approved' ) )
TO reported-zaky_i_emp.
APPEND VALUE #( %tky = employee-%tky )
TO failed-zaky_i_emp.
CONTINUE.
ENDIF.
" Update status to APPROVED
MODIFY ENTITIES OF zaky_i_emp IN LOCAL MODE
ENTITY zaky_i_emp
UPDATE FIELDS ( Status )
WITH VALUE #( (
%tky = employee-%tky
Status = 'APPROVED'
) )
FAILED DATA(update_failed)
REPORTED DATA(update_reported).
" Pass back result
APPEND VALUE #(
%tky = employee-%tky
%param = employee
) TO result.
ENDLOOP.
ENDMETHOD.</code></pre><P><U><FONT face="arial,helvetica,sans-serif" size="4"><STRONG>Output</STRONG></FONT></U></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Abhi_0118_1-1782208500025.png" style="width: 657px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/425239i3E505C640B9BC34F/image-dimensions/657x304?v=v2" width="657" height="304" role="button" title="Abhi_0118_1-1782208500025.png" alt="Abhi_0118_1-1782208500025.png" /></span></P><P><STRONG>Click on the create </STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Abhi_0118_2-1782208568634.png" style="width: 654px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/425242i6AE4CACBEC0358D3/image-dimensions/654x310?v=v2" width="654" height="310" role="button" title="Abhi_0118_2-1782208568634.png" alt="Abhi_0118_2-1782208568634.png" /></span></P><P>After adding the value click on the create and put the debugger on the create-augment method to check it is triggering or not because we are doing managed application where creation is handled by framework</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Abhi_0118_0-1783921767429.png" style="width: 532px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/432182i0467F4A6A38B1515/image-dimensions/532x456?v=v2" width="532" height="456" role="button" title="Abhi_0118_0-1783921767429.png" alt="Abhi_0118_0-1783921767429.png" /></span></P><P><STRONG>Execute</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Abhi_0118_4-1782209444122.png" style="width: 628px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/425252iC67537BA421DD23C/image-dimensions/628x153?v=v2" width="628" height="153" role="button" title="Abhi_0118_4-1782209444122.png" alt="Abhi_0118_4-1782209444122.png" /></span></P><P><STRONG>Currently it is in pending state click on the Approve employee.</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Abhi_0118_5-1782209514677.png" style="width: 622px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/425254i1971B2B62521F508/image-dimensions/622x148?v=v2" width="622" height="148" role="button" title="Abhi_0118_5-1782209514677.png" alt="Abhi_0118_5-1782209514677.png" /></span></P><P><STRONG>After clicking on action</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Abhi_0118_6-1782209548205.png" style="width: 622px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/425255i279C217B0C0C4680/image-dimensions/622x70?v=v2" width="622" height="70" role="button" title="Abhi_0118_6-1782209548205.png" alt="Abhi_0118_6-1782209548205.png" /></span></P><P><STRONG>If you not adding the department</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Abhi_0118_0-1782210556795.png" style="width: 630px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/425261i394039D97B6C97F1/image-dimensions/630x326?v=v2" width="630" height="326" role="button" title="Abhi_0118_0-1782210556795.png" alt="Abhi_0118_0-1782210556795.png" /></span></P><P> </P><H2 id="toc-hId--194393791"><U><FONT face="arial,helvetica,sans-serif">Conclusion</FONT></U></H2><P class="">RAP Augmentation provides a simple and effective way to enrich transactional requests before the RAP framework begins processing the business object. It is particularly useful for populating default values, maintaining audit information, and preparing request data that should be available throughout the transaction.</P><P class="lia-align-justify" style="text-align : justify;">In this example, we used augmentation to automatically populate employee details while keeping the business object implementation clean and maintainable. Understanding when to use Augmentation instead of Determinations helps developers choose the right extension point and build more maintainable RAP applications</P>2026-07-17T11:22:43.643000+02:00https://community.sap.com/t5/abap-blog-posts/the-paging-catastrophe/ba-p/14442948The paging catastrophe2026-07-20T05:50:04.703000+02:00josealbahttps://community.sap.com/t5/user/viewprofilepage/user-id/885577<P><ul =""><li style="list-style-type:disc; margin-left:15px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/the-paging-catastrophe/ba-p/14442948#toc-hId-1820005198">Introduction</a></li><li style="list-style-type:disc; margin-left:15px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/the-paging-catastrophe/ba-p/14442948#toc-hId-1623491693">Context</a></li><li style="list-style-type:disc; margin-left:15px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/the-paging-catastrophe/ba-p/14442948#toc-hId-1426978188">Case 1: No BTP pre-filtering or post-filtering</a></li><li style="list-style-type:disc; margin-left:15px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/the-paging-catastrophe/ba-p/14442948#toc-hId-837437673">Case 2: BTP post-filtering</a></li><li style="list-style-type:disc; margin-left:15px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/the-paging-catastrophe/ba-p/14442948#toc-hId-247897158">Case 3: BTP pre-filtering</a></li><li style="list-style-type:disc; margin-left:15px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/the-paging-catastrophe/ba-p/14442948#toc-hId-5611000">Case 4: Split BTP pre-filtering</a></li><li style="list-style-type:disc; margin-left:15px; margin-bottom:1px;"><a href="https://community.sap.com/t5/abap-blog-posts/the-paging-catastrophe/ba-p/14442948#toc-hId--583929515">Conclusions</a></li></ul></P><H2 id="Introduction" id="toc-hId-1820005198">Introduction</H2><P>In the late 19th century, the scientific community started to face unexpected issues, some of them quite serious, upon proven experiments for which no accepted formula was able to produce reasonable prediction or explanation. This originated the entire collapse of the current physics, now called ‘classic physics’, into a new frame ignited by the quantum mechanics. The game-changing problem was named ‘the ultraviolet catastrophe’.</P><P>Similarly to what happened back then –hopefully less ontologically problematic–, the SAP transition from classic to Fiori-oriented development brings about some anomalies not especially easy to overcome without a systemic revolution of the technology itself. One of the problems we have experienced regards the paging mechanism when rendering a Fiori list report via back-end OData service.</P><H2 id="toc-hId-1623491693">Context</H2><P>Let’s assume the following scenario:</P><OL class=""><LI><P>On-premise OData service.</P></LI><LI><P>BTP Fiori list report application consuming the back-end service via custom entity.</P><OL class=""><LI><P>Respecting the Clean Core principles, the report combines information from the back-end –only read–, and local BTP tables. To ensure integrity, the key fields are the same on both sides.</P></LI><LI><P>Consequently, the selection filters can refer to both back-end and BTP fields.</P></LI></OL></LI><LI><P>The BTP application, fields and tables underneath dominate the entire execution engine. This is to say, BTP-located filtering, if any, must lead the back-end selection.</P></LI></OL><H2 id="Case-1:-No-BTP-pre-filtering-or-post-filtering" id="toc-hId-1426978188">Case 1: No BTP pre-filtering or post-filtering</H2><H3 id="Scenario" id="toc-hId-1359547402">Scenario</H3><P>No BTP-located filter fields are set, so there is no need to implement BTP filtering before or after the service call. In real executions, this is not very likely to happen, but anyway interesting to start exposing the problem.</P><H3 id="Behaviour" id="toc-hId-1163033897">Behaviour</H3><P><SPAN class="">All pages are correctly delivered through scrolling. Considering </SPAN><EM><SPAN class="">n</SPAN></EM><SPAN class=""> items are hit in the back-end, when reaching the last page, all of them are rendered.</SPAN></P><P class="lia-align-center" style="text-align: center;"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="josealba_5-1784278865631.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/434211iFDF9E2619F66EA26/image-size/large?v=v2&px=999" role="button" title="josealba_5-1784278865631.png" alt="josealba_5-1784278865631.png" /></span></P><H2 id="Case-2:-BTP-post-filtering" id="toc-hId-837437673">Case 2: BTP post-filtering</H2><H3 id="Scenario.1" id="toc-hId-770006887">Scenario</H3><P>Here, BTP-located filter fields are set. The idea is to retrieve matching information from the back-end and, next, filter by the BTP conditions.</P><H3 id="Behaviour.1" id="toc-hId-573493382">Behaviour</H3><P>If the page is not reduced during the post filtering, i.e., no line is impacted by the BTP filtering, then it is correctly shown and the scroll for the next one continues to be enabled.</P><P><SPAN class="">Else, if the page size is reduced, the system considers it is the last so no more scrolling is enabled; even trying to scroll down no more service calls are run. The page cropping leads then to missing information.</SPAN></P><P><SPAN class=""><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="josealba_6-1784278941276.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/434214i37D72D2BEA2A5266/image-size/large?v=v2&px=999" role="button" title="josealba_6-1784278941276.png" alt="josealba_6-1784278941276.png" /></span></SPAN></P><H2 id="Case-3:-BTP-pre-filtering" id="toc-hId-247897158">Case 3: BTP pre-filtering</H2><H3 id="Scenario.2" id="toc-hId-180466372">Scenario</H3><P>If the post-filtering does not work, why not first filter in BTP and then use the key fields to retrieve from the back-end only exactly what is needed?</P><H3 id="Behaviour.2" id="toc-hId--91278502">Behaviour</H3><P>Here, <EM>x </EM>items are pre-filtered in BTP. If, additionally, back-end filtering is set, the final number of retrieved items, say <EM>n</EM>, can potentially be less than <EM>x</EM>.</P><P><SPAN class="">Anyway, the strategy seems finely focused but the problem arises when too many items are pre-filtered so the URL to call the service is too long to be accepted and leads to an exception.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="josealba_7-1784279009939.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/434249i2BA5B20A471CF36A/image-size/large?v=v2&px=999" role="button" title="josealba_7-1784279009939.png" alt="josealba_7-1784279009939.png" /></span></P><H2 id="Case-4:-Split-BTP-pre-filtering" id="toc-hId-5611000">Case 4: Split BTP pre-filtering</H2><H3 id="Scenario.3" id="toc-hId--484305512">Scenario</H3><P>Considering some trust was put in the previous step, maybe we could split the filtering and manually call the service in small packages to avoid problems with the URL.</P><H3 id="Behaviour.3" id="toc-hId--680819017">Behaviour</H3><P>To avoid the cropped page problem, the main purpose is to always build complete pages to keep the execution alive; otherwise, it stops. The challenge is to seamlessly advance through packages as if no additional calls were executed.</P><P>In BTP, <EM>x </EM>items are filtered and supposed to be sent to the back-end. The URL length is first checked:</P><UL class=""><LI><P><SPAN class="">If it is short enough to be accepted, then no split is needed and the call can be executed as conventionally.</SPAN></P></LI><LI><P>In other case, the logic will split the <EM>x </EM>items into small packages of <EM>s</EM>; the package size must be greater than the page size so as to avoid the scroll disabling.</P></LI></UL><P><SPAN class="">For the first call, the </SPAN><EM><SPAN class="">s</SPAN></EM><SPAN class=""> items hit </SPAN><EM><SPAN class="">n</SPAN></EM><SPAN class=""> back-end items, so the report counter shows </SPAN><EM><SPAN class="">n </SPAN></EM><SPAN class="">as the total number of items, but this value is not correct, as there are more items waiting to be sent.</SPAN></P><P>By scrolling down, the complete list of <EM>n </EM>items related to the first package is delivered correctly, so for now no need to process other packages.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="josealba_8-1784279068283.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/434251iDE0BA053E8F420A2/image-size/large?v=v2&px=999" role="button" title="josealba_8-1784279068283.png" alt="josealba_8-1784279068283.png" /></span></P><P>If the current page size is less than the determined size, i.e., if the page is cropped, this means we have reached the end of the package, so the next one can be processed.</P><P>The next package is then processed making sure the <EM>skip </EM>is reset to retrieve all back-end hits from the beginning. The cropped page is then completed with <EM>p - q</EM> items from the new package.</P><P><SPAN class="">For next page the </SPAN><EM><SPAN class="">skip</SPAN></EM><SPAN class=""> is automatically set to the page size and because there is no option to keep track of the actual index we are in –stateless processing–, a gap of missing information can occur.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="josealba_9-1784279104507.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/434268i12DD7D483E4B3B5E/image-size/large?v=v2&px=999" role="button" title="josealba_9-1784279104507.png" alt="josealba_9-1784279104507.png" /></span></P><H2 id="Conclusions" id="toc-hId--583929515"><STRONG>Conclusions</STRONG></H2><P>The development of BTP reports via custom entities where local filtering is supposed to restrain the information coming from the back-end introduces a series of problems not easy to overcome. Business may claim classic development where all the data and logic was set on-premise did not carry this type of problems.</P><P>As it happened to physics, the transition to modern SAP development presents by comparison some obstacles for which quick adaptation is needed. The answer to this problem, something like quantum mechanics in our recurrent reference, goes through using a more powerful technology; for the time being, <U>external entities based on HANA virtual tables are the best alternative to avoid the paging catastrophe</U>.</P>2026-07-20T05:50:04.703000+02:00https://community.sap.com/t5/technology-blog-posts-by-members/sap-note-creation-process-for-customer-incident/ba-p/14438304SAP Note Creation Process for Customer Incident2026-07-21T12:15:39.081000+02:00Swathi_PVhttps://community.sap.com/t5/user/viewprofilepage/user-id/1676261<P><STRONG>Introduction :-<BR /></STRONG>When customer raises a production-related incident in the ServiceNow tool, they provide issue details, scenario snapshots, and system information to help debug the reported issue. Based on this input after resolving the issue and testing in Internal systems. I followed a defined process to create the corresponding SAP Note and release note either tailored to the specific customer or applicable to all customers. <STRONG><BR /></STRONG></P><P><FONT size="4"> The process covers:</FONT></P><UL><LI><FONT size="4"><SPAN>Creating the Request and associated Task</SPAN><SPAN> </SPAN></FONT></LI></UL><UL><LI><FONT size="4"><SPAN>Releasing the Transport Request (TR)</SPAN><SPAN> </SPAN></FONT></LI></UL><UL><LI><FONT size="4"><SPAN>Adding Corrective Instructions (Support Pack references)</SPAN><SPAN> </SPAN></FONT></LI></UL><UL><LI><FONT size="4"><SPAN>Creating and structuring the SAP Note</SPAN><SPAN> </SPAN></FONT></LI></UL><UL><LI><FONT size="4"><SPAN>Pilot Release and General Release process </SPAN><SPAN> </SPAN></FONT></LI></UL><H2 id="toc-hId-1819254529"><FONT size="4"><STRONG>What is I7P?</STRONG></FONT></H2><P><FONT size="4"><SPAN>I7P is SAP’s internal support and knowledge management system that serves as the central repository for SAP Notes. It is used by SAP teams to create, maintain, and track solutions for product issues before they are published to customer-facing support channels. As the backend source of SAP Notes, I7P helps ensure accurate technical knowledge, fixes, and support documentation are delivered to customers and also I7P system help to create Transport Request , Notes and to add support Pack based on customer system version.</SPAN><SPAN> </SPAN></FONT></P><H2 id="toc-hId-1622741024"><FONT size="4"><STRONG>Transport Request and Task</STRONG></FONT></H2><P><FONT size="4"><STRONG>Transport Request</STRONG> is the main container that holds all development changes. It is created whenever changes are made to repository objects such as programs, classes, and tables.</FONT></P><P><FONT size="4"><STRONG><SPAN>Task</SPAN></STRONG><SPAN> is a child object under a Transport Request.</SPAN><SPAN> </SPAN></FONT></P><UL><LI><FONT size="4"><SPAN>Must be released first before releasing the parent request. </SPAN><SPAN> </SPAN></FONT></LI></UL><UL><LI><FONT size="4"><SPAN>Tasks cannot be transported independently.</SPAN><SPAN> </SPAN></FONT></LI></UL><H2 id="toc-hId-1426227519"><FONT size="4"><STRONG>Steps to Create ABAP Corrective Measures</STRONG></FONT></H2><P><FONT size="4"><STRONG>Step 1: Open ABAP Corr. Measures</STRONG></FONT></P><P><FONT size="4">Log in to the I7P system and click ABAP Corr. Measures.</FONT></P><P><FONT size="4"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_0-1783767004790.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431843i63CECE30A075C902/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_0-1783767004790.png" alt="Swathi_PV_0-1783767004790.png" /></span></FONT></P><P><FONT size="4"><STRONG>Step 2: Provide the Required Details</STRONG></FONT></P><P><FONT size="4">Fill in the required fields — Application Component, Short Text, Priority, and Software Component — and select the SAP Note radio button.</FONT></P><P><FONT size="4"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_1-1783767004803.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431845iE049E42CBCAF672F/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_1-1783767004803.png" alt="Swathi_PV_1-1783767004803.png" /></span></FONT></P><P><FONT size="4"><STRONG>Step 3: Select Components and Systems</STRONG></FONT></P><P><FONT size="4">Select the components and systems where the changes are needed, then click Continue with System Selection.</FONT></P><P><FONT size="4"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_2-1783767004805.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431844i914535206A00E2C9/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_2-1783767004805.png" alt="Swathi_PV_2-1783767004805.png" /></span></FONT></P><P><FONT size="4"><STRONG>Step 4: Choose the Transport Request Type</STRONG></FONT></P><P><FONT size="4">Select the type of Transport Request required based on the object changes — Workbench or Customizing.</FONT></P><P><FONT size="4"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_3-1783767004808.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431848iA74694EC3A9F0B9A/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_3-1783767004808.png" alt="Swathi_PV_3-1783767004808.png" /></span></FONT></P><P><FONT size="4">The correction request is then created, as shown below:</FONT></P><P><FONT size="4"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_4-1783767004808.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431846i5FD921A97C634CDA/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_4-1783767004808.png" alt="Swathi_PV_4-1783767004808.png" /></span><STRONG><EM><I>Note: </I></EM></STRONG><EM><I>All Transport Requests and their associated tasks can be reviewed in transactions SE09 and SE10. Once all changes have been locked in the Transport Request, open transaction SE09, enter the user name, and click Display. Select the task and run a Consistency Check. If any errors are found, the task cannot be released until they are resolved. After a successful consistency check, click the Transport icon, as shown below.</I></EM></FONT></P><P><FONT size="4"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_5-1783767004810.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431847iCE81054F70263D42/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_5-1783767004810.png" alt="Swathi_PV_5-1783767004810.png" /></span></FONT></P><H2 id="toc-hId-1229714014"><FONT size="4"><STRONG>Step 5: Retrofitting</STRONG></FONT></H2><P>Retrofit is a synchronization process used to copy changes made in a production or maintenance system into a parallel project or development system.</P><P>Go to transaction SCWB, enter the user ID (the request should be under the name of the person performing the retrofit), and click Execute.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_6-1783767004812.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431851i98209C65F56D834E/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_6-1783767004812.png" alt="Swathi_PV_6-1783767004812.png" /></span>Double-click the request whose changes need to be distributed to other systems, then select the request and click the Distribute icon, as shown below. All object changes are transported to the respective systems, and the system releases the tasks.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_7-1783767004814.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431850iE7404850D051D0B0/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_7-1783767004814.png" alt="Swathi_PV_7-1783767004814.png" /></span></P><P>The system displays a success message confirming that the changes were distributed successfully.</P><H2 id="toc-hId-1033200509"><FONT size="4"><STRONG>Step 6 : </STRONG><STRONG>Test Transport</STRONG></FONT></H2><P>Test Transport is the process of importing development changes from the DEV system into QAS for testing and validation prior to production deployment.</P><P>Right-click the request for the relevant system, select Process Item, then Generate Test Transport.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_8-1783767004816.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431849iA793359E668C0865/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_8-1783767004816.png" alt="Swathi_PV_8-1783767004816.png" /></span>Press Enter, and a success message will appear.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_9-1783767004818.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431852i3C70F264995C63F3/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_9-1783767004818.png" alt="Swathi_PV_9-1783767004818.png" /></span><SPAN> </SPAN></P><P><FONT size="4"><STRONG>Step 7 : </STRONG></FONT><STRONG><FONT size="4">Creating Correction Instructions and Adding the Support Packa</FONT>ge</STRONG></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_10-1783767004819.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431854i1FAEA50763594AF0/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_10-1783767004819.png" alt="Swathi_PV_10-1783767004819.png" /></span></P><P>A pop-up screen will appear — click Enter.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_11-1783767004819.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431853i2F922BAA55A4DD10/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_11-1783767004819.png" alt="Swathi_PV_11-1783767004819.png" /></span></P><P>The correction request is created as shown below. Repeat this step for all the systems.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_12-1783767004821.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431855iDF6728BC17571F54/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_12-1783767004821.png" alt="Swathi_PV_12-1783767004821.png" /></span>Double-click the created correction instruction to review the changes made to the object, add the dependent SAP Note, and add the Support Package.</P><P>Double-click the object name to view the code changes (inserted and deleted blocks).</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_13-1783767004822.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431856iF6D33332960FF7F8/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_13-1783767004822.png" alt="Swathi_PV_13-1783767004822.png" /></span><SPAN>Click Validity to add the Support Package (SP) — select n+1, where n represents 12 months</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_14-1783767004823.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431857i831CDE685B957A10/image-size/large?v=v2&px=999" role="button" title="Swathi_PV_14-1783767004823.png" alt="Swathi_PV_14-1783767004823.png" /></span>Select the block and press Enter.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Swathi_PV_15-1783767004826.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/431858iDD16A880C3E37649/image-size/medium?v=v2&px=400" role="button" title="Swathi_PV_15-1783767004826.png" alt="Swathi_PV_15-1783767004826.png" /></span></P><P><SPAN>Check and Release the Correction Instruction.</SPAN><SPAN> </SPAN></P><P><STRONG><EM><I>Note: </I></EM></STRONG><EM><I>Correction instructions must be created for all the systems.</I></EM></P><H2 id="toc-hId-836687004"><FONT size="4"><STRONG>Step 8 : </STRONG><STRONG>Creating the SAP Note</STRONG></FONT></H2><P>Double-click the created SAP Note and provide the symptom, solution, and objects changed for the issue. Add attachments if needed, and mention the relevant components in the SAP Note header.</P><P><STRONG>Pilot Release</STRONG> – A customer number is added to the SAP Note so that the changes apply only to the designated customer and do not impact others.</P><P><STRONG>General Release</STRONG> – The changes implemented through the SAP Note become applicable to all customers.</P><H2 id="toc-hId-640173499"><FONT size="4"><STRONG>Step 9 : </STRONG><STRONG>Final Step</STRONG></FONT></H2><P>After completing all development activities, SAP Note creation, correction instruction creation, and testing across various scenarios, the changes are thoroughly validated. Once all validations are successful, the SAP Note and correction request are assigned to the senior consultants for final review and release.<BR /><BR /><STRONG>Conclusion </STRONG></P><P>By reading this blog,one will have a knowledge on Transport Request, Task, Retrofitting, Transporting changes from Development system to Quality system, Steps to create SAP Note, Release note.<BR />Once the release note is issued, the customer can apply the note via SNOTE transaction and the reported issue will be resolved.<BR /><BR /><STRONG>Thank you for reading!!</STRONG></P><P><SPAN> </SPAN></P><P><SPAN> </SPAN></P>2026-07-21T12:15:39.081000+02:00https://community.sap.com/t5/technology-blog-posts-by-members/open-source-abap-utility-to-search-text-symbols-text-elements-using-read/ba-p/14428902Open-Source ABAP Utility to Search Text Symbols (Text Elements) Using READ TEXTPOOL2026-07-21T13:15:55.012000+02:00aravindhan2529https://community.sap.com/t5/user/viewprofilepage/user-id/2160838<H2 id="toc-hId-1818336772">Introduction</H2><P>During a maintenance activity, I needed to locate a company name across several custom ABAP programs. Running the standard report **RPR_ABAP_SOURCE_SCAN** successfully found occurrences in the ABAP source code, but it did not return matches maintained as **Program Text Elements (Text Symbols)**.</P><P>The reason is that program Text Elements are stored in the program's text pool and are accessed using the ABAP statement **READ TEXTPOOL**, rather than being part of the ABAP source itself.</P><P>To solve this, I developed a small open-source utility that searches text pools across multiple ABAP programs and displays the matching entries using the SALV framework.</P><HR /><P><STRONG>## Why RPR_ABAP_SOURCE_SCAN Was Not Enough</STRONG></P><P>The standard report **RPR_ABAP_SOURCE_SCAN** is useful for searching ABAP source code. However, it does not search **Program Text Elements (Text Symbols)** because these texts are maintained in the program's text pool rather than in the source code.</P><P>During a maintenance activity, I needed to locate a company name maintained as a Program Text Element (Text Symbol).Since the standard report did not return these occurrences, I needed another approach to search the text pool directly.</P><P>To address this limitation, I developed a utility that reads the text pool of each selected program, searches for matching text entries, and displays the results using SALV.</P><H1 id="toc-hId-1492740548">Implementation</H1><P>To address this limitation, I developed a lightweight utility that reads the text pool of each selected ABAP program, searches for matching text entries, and displays the results using SALV.</P><P>The implementation consists of the following steps:</P><OL><LI>Retrieve the selected ABAP programs from the repository.</LI><LI>Read the text pool of each program using <CODE>READ TEXTPOOL</CODE>.</LI><LI>Search the retrieved text entries for the specified text.</LI><LI>Display the matching results using SALV.</LI></OL><H2 id="toc-hId-1425309762">Step 1: Retrieve the Selected Programs</H2><P>The first step is to retrieve the selected ABAP programs from the repository based on the user input provided on the selection screen.</P><pre class="lia-code-sample language-abap"><code>SELECT pgmid,
object,
obj_name
FROM tadir
INTO TABLE <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/2891">@MT</a>_programs
WHERE pgmid = 'R3TR'
AND obj_name IN <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/148934">@SO</a>_prog.</code></pre><P>The utility reads the selected repository objects from the <CODE>TADIR</CODE> table. Each program is then processed individually to search its Program Text Elements.</P><H2 id="toc-hId-1228796257">Step 2: Read the Program Text Pool</H2><P>For each selected program, the utility uses the <CODE>READ TEXTPOOL</CODE> statement to retrieve the program's Text Elements for the selected language.</P><pre class="lia-code-sample language-abap"><code>LOOP AT mt_programs INTO DATA(ls_program).
CLEAR mt_textpool.
READ TEXTPOOL ls_program-obj_name
LANGUAGE so_lang-low
INTO mt_textpool
STATE 'A'.
ENDLOOP.</code></pre><P><CODE>READ TEXTPOOL</CODE> retrieves the text pool for the current program. The selected language (<CODE>so_lang-low</CODE>) determines which language version is loaded into the internal table <CODE>mt_textpool</CODE>. These entries are then processed in the next step.</P><H2 id="toc-hId-1032282752">Step 3: Search for Matching Text</H2><P>After reading the text pool, the utility loops through the retrieved entries and searches for the text entered on the selection screen. A partial text search is performed using the <CODE>CS</CODE> (Contains String) operator.</P><pre class="lia-code-sample language-abap"><code>LOOP AT mt_textpool INTO DATA(ls_textpool)
WHERE id = 'I'
AND entry CS so_text-low.
APPEND VALUE ty_result(
program = ls_program-obj_name
key = ls_textpool-key
text = ls_textpool-entry )
TO mt_result.
ENDLOOP.</code></pre><P>The <CODE>CS</CODE> operator performs a substring search, allowing partial matches instead of requiring an exact text match. Whenever a matching entry is found, the program name, text key, and text are added to the result table for later display.</P><H2 id="toc-hId-835769247">Step 4: Display the Search Results</H2><P>After all matching text entries have been collected, the results are displayed using the SAP List Viewer (SALV), providing a simple and interactive ALV report with standard features such as sorting, filtering, and exporting.</P><pre class="lia-code-sample language-abap"><code>cl_salv_table=>factory(
IMPORTING
r_salv_table = DATA(lo_alv)
CHANGING
t_table = mt_result ).
lo_alv->get_functions( )->set_all( abap_true ).
lo_alv->display( ).</code></pre><P>The result table is passed to the SALV factory method to create the ALV output. Standard SALV functions are enabled before displaying the results.</P><P> </P><HR /><H2 id="toc-hId-639255742">Selection Screen</H2><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="aravindhan2529_1-1784560808831.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/435179iB5712CF026E6449D/image-size/large?v=v2&px=999" role="button" title="aravindhan2529_1-1784560808831.png" alt="aravindhan2529_1-1784560808831.png" /></span></P><H2 id="toc-hId-442742237">Sample Output</H2><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="aravindhan2529_2-1784560928112.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/435180iE5F32DBD5395ADC0/image-size/large?v=v2&px=999" role="button" title="aravindhan2529_2-1784560928112.png" alt="aravindhan2529_2-1784560928112.png" /></span></P><P> </P><HR /><H2 id="toc-hId-246228732">SOURCE CODE</H2><P>The complete source code is available on GitHub:</P><P><STRONG><A href="https://github.com/aravindhanchandran/abap-text-symbol-search" target="_self" rel="nofollow noopener noreferrer">https://github.com/aravindhanchandran/abap-text-symbol-search</A> </STRONG></P><P>The repository includes the complete implementation and can be used as a reference or extended to meet additional search requirements.</P><HR /><H2 id="toc-hId-49715227">Conclusion</H2><P>The standard report `RPR_ABAP_SOURCE_SCAN` is effective for searching ABAP source code, but it does not search Program Text Elements maintained in a program's text pool. This utility complements the standard report by using `READ TEXTPOOL` to search Text Symbols across multiple ABAP programs.</P><P>I hope this utility is useful for developers performing impact analysis, maintenance activities, company renaming projects, or any task that requires searching Program Text Elements. If you know of a SAP standard alternative or have suggestions for improvements, I'd be happy to hear your feedback. Contributions and ideas are always welcome.</P>2026-07-21T13:15:55.012000+02:00https://community.sap.com/t5/technology-blog-posts-by-sap/abap-development-tools-for-visual-studio-code-version-1-1-released/ba-p/14421143ABAP development tools for Visual Studio Code: Version 1.1 released2026-07-21T13:53:34.813000+02:00thomasalexander_ritterhttps://community.sap.com/t5/user/viewprofilepage/user-id/185696<H1 id="toc-hId-1688269120" id="toc-hId-1689037953"><SPAN>What happened since the last release?</SPAN></H1><P><A href="https://marketplace.visualstudio.com/items?itemName=SAPSE.adt-vscode" target="_self" rel="nofollow noopener noreferrer"><SPAN>Link to the extension.</SPAN></A></P><P><SPAN>First of all, thanks for the positive feedback regarding the 1.0.1 patch which added the much requested RFC + password support! Please keep providing feedback as it helps us to plan the next releases. A lot of users are asking us how they can provide feedback. We have recently added a <A href="https://influence.sap.com/sap/ino/#campaign/2911" target="_self" rel="noopener noreferrer">new customer influence channel</A> just for the VS Code extension. We recommend using that one.</SPAN></P><P><SPAN>Last month, <A href="https://abapconf.org/abapconf2026/" target="_self" rel="nofollow noopener noreferrer">ABAPConf 2026</A> took place in Mannheim. We want to highlight two talks:</SPAN></P><OL><LI><SPAN>Tobias Hofmann provided public feedback regarding the extension and compiled a nice to-do list. I can report that a lot of these to-do items are already part of our internal to-do list. The talk can be found <A href="https://www.youtube.com/watch?v=hzRQuEzMLhY" target="_self" rel="nofollow noopener noreferrer">here</A>.</SPAN></LI><LI><SPAN>Anne Keller and I gave a talk on the overall ABAP IDE strategy. Of course, it touches the VS Code extension but also aims to provide a broader picture on how we want to support ABAP IDEs via a single technology stack in the future and shares some insights on how the ADT MCP server will evolve in the future. The talk can be found <A href="https://www.youtube.com/watch?v=2a7hzuw3woM" target="_self" rel="nofollow noopener noreferrer">here</A>.</SPAN></LI></OL><P> </P><H1 id="toc-hId-1491755615" id="toc-hId-1492524448"><SPAN>What gets shipped with this release?</SPAN></H1><H3 id="toc-hId-1554176381"><SPAN>Usability improvements for system connection handling</SPAN></H3><P><SPAN>After creating a new destination there was no visual feedback that the destination was created successfully. We added a notification pop-up with a button which directly adds it as a folder to your workspace.</SPAN></P><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="destination_add_as_folder.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/434898i10292816BFAD1A46/image-size/medium?v=v2&px=400" role="button" title="destination_add_as_folder.png" alt="destination_add_as_folder.png" /></span></SPAN></P><P><SPAN>We added a "Log on to Destination..." command. While it was possible to log on to a destination via a right-click menu in the explorer view there was no command available for it. </SPAN></P><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="logon_menu_item.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/434931iB7F9BF5A47889FC6/image-size/medium?v=v2&px=400" role="button" title="logon_menu_item.png" alt="logon_menu_item.png" /></span></SPAN></P><P><SPAN>Now, you can easily log on to a destination using the keyboard via the new command.</SPAN></P><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="logon1.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/434910i9D9212B5A0BB6C21/image-size/medium?v=v2&px=400" role="button" title="logon1.png" alt="logon1.png" /></span></SPAN></P><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="logon2.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/434914i14577214BB68CBEE/image-size/medium?v=v2&px=400" role="button" title="logon2.png" alt="logon2.png" /></span></SPAN></P><H3 id="toc-hId-1357662876">A significant improvement of object type support</H3><P>A lot of requested object types get enabled by this release. Here is the list of added object types:</P><H5 id="toc-hId-1419314809">Classic ABAP source code</H5><UL><LI><SPAN>Create and Manage Function Groups and Modules</SPAN></LI><LI><SPAN>Create and Manage ABAP Programs and Includes</SPAN></LI><LI><SPAN>Create and Manage Lock Objects</SPAN></LI></UL><H5 id="toc-hId-1222801304"><SPAN>Data Dictionary</SPAN></H5><UL><LI><SPAN>Create and Manage Database Tables</SPAN></LI><LI><SPAN>Create and Manage Structures</SPAN></LI><LI><SPAN>Create and Manage Type Groups</SPAN></LI></UL><H5 id="toc-hId-1026287799">RESTful Application Programming Model</H5><UL><LI><SPAN>Creating Behavior Definition Extensions</SPAN></LI><LI><SPAN>Enabling more OData Binding Types in Service Binding</SPAN></LI><LI><SPAN>Create and Manage CDS Entity Buffers</SPAN></LI></UL><H3 id="toc-hId-571608856">New MCP tools</H3><H5 id="toc-hId-633260789">Unified diff tool for transports</H5><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="thomasalexander_ritter_0-1784628047832.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/435436iB59B911CF866B6C9/image-size/medium?v=v2&px=400" role="button" title="thomasalexander_ritter_0-1784628047832.png" alt="thomasalexander_ritter_0-1784628047832.png" /></span></P><P>The unified diff tool generates a <A href="https://git-scm.com/docs/diff-format" target="_self" rel="nofollow noopener noreferrer">git like diff</A> for a given transport request. The tool enables token efficient analysis of the changes contained in a transport request. This enables AI agents to fulfill requests such as:</P><UL><LI>"Explain transport XYZ"</LI><LI>"Generate a description for transport XYZ documenting what got changed and why"</LI><LI>"How much impact does transport XYZ has on the system? How dangerous is this transport?"</LI></UL><H5 id="toc-hId-436747284">Tools for ABAP Test Cockpit (ATC)</H5><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="thomasalexander_ritter_0-1784633951380.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/435557iD397E3BC3A126A06/image-size/medium?v=v2&px=400" role="button" title="thomasalexander_ritter_0-1784633951380.png" alt="thomasalexander_ritter_0-1784633951380.png" /></span></P><P>The ATC MCP tools give AI agents access to running the ATC checks for a given change. This enables AI agents to fulfill requests such as:</P><UL><LI>"Implement [XYZ]. Afterwards, run the ATC checks and fix the reported findings."</LI><LI>"Run ATC checks for object XYZ"</LI></UL><H3 id="toc-hId--93163028">Additional UX improvements</H3><P>We added a command which allows you to quickly open the SAP Help documentation.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="abap_vscode_documentation.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/434927iD70EE3151616CDD8/image-size/medium?v=v2&px=400" role="button" title="abap_vscode_documentation.png" alt="abap_vscode_documentation.png" /></span></P><P>From each occurrence of a CDS annotation in a CDS data definition or CDS metadata extension, you can now navigate to its CDS annotation definition. To navigate, press F3 on the relevant CDS annotation. This helps you to investigate and to understand the use of a CDS annotation.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="thomasalexander_ritter_0-1784557648564.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/435160iC57E82F6E5DBC314/image-size/medium?v=v2&px=400" role="button" title="thomasalexander_ritter_0-1784557648564.png" alt="thomasalexander_ritter_0-1784557648564.png" /></span></P><P>For more information see the new <A href="https://help.sap.com/docs/abap-cloud/abap-development-tools-for-visual-studio-code/what-s-new" target="_self" rel="noopener noreferrer">"What's New"</A> page.</P><P> </P><H1 id="toc-hId-297129481">Sidenote: first version of ABAP cleaner VS Code extension available</H1><P>Lots of community members asked for ABAP cleaner support in VS Code. We are happy to announce that the first version of the <A href="https://marketplace.visualstudio.com/items?itemName=SAPOSS.abap-cleaner" target="_self" rel="nofollow noopener noreferrer">ABAP cleaner extension</A> is available, now!</P><P> </P><H1 id="toc-hId-902215100" id="toc-hId-100615976"><SPAN>What's next?</SPAN></H1><P data-unlink="true"><SPAN>From now on, we will stop listing upcoming features directly in the release blogs. Instead we have cleaned up and refreshed our <A href="https://help.sap.com/docs/abap-cross-product/roadmap-info/tools" target="_self" rel="noopener noreferrer">ABAP Cloud Roadmap page</A>. The planned features are listed there</SPAN><SPAN>.</SPAN></P><H2 id="toc-hId-834784314" id="toc-hId--389300536">Provide feedback and influence our product backlog!</H2><P><SPAN>We welcome your feedback! Feel free to use the comment section or <A href="https://influence.sap.com/sap/ino/#/campaign/2911" target="_blank" rel="noopener noreferrer">create a customer influence request</A> to let us know which features you are missing the most. Your input will help us prioritize the feature backlog for the next releases.</SPAN></P>2026-07-21T13:53:34.813000+02:00