https://raw.githubusercontent.com/ajmaradiaga/feeds/main/scmt/topics/API-Management-blog-posts.xml SAP Community - API Management 2024-05-20T11:10:02.988674+00:00 python-feedgen API Management blog posts in SAP Community https://community.sap.com/t5/technology-blogs-by-sap/graph-intro-series-part-4-hello-graph-write-your-first-graph-application/ba-p/13620393 Graph intro series, part 4: Hello Graph! Write your first Graph application 2024-02-28T10:16:21.965000+01:00 shardulsonar https://community.sap.com/t5/user/viewprofilepage/user-id/159141 <P style=" text-align : justify; ">This is the first of the end-to-end implementation blog series for Graph that focuses on a developer writing an extension application that uses the single, unified API of Graph in SAP Integration Suite. Please refer to <A href="https://community.sap.com/t5/technology-blogs-by-sap/graph-tutorial-part-1-introduction-to-graph-in-sap-integration-suite/ba-p/13615255" target="_self">Part 1</A> of this series for an introduction to Graph and to the <A href="https://community.sap.com/t5/technology-blogs-by-sap/information-map-multi-part-tutorial-graph-in-sap-integration-suite/ba-p/13614448" target="_self">Information Map</A> for an introduction to the entire series.</P><P style=" text-align : justify; ">The initial developer parts in this series will lead you through building the rudimentary basics of a classical enterprise extension web app: a list-details-navigate application in the <A href="https://community.sap.com/t5/technology-blogs-by-sap/graph-intro-series-part-5-use-graph-securely-with-real-data-authentication/ba-p/13622195" target="_self">next part</A>. This is what it will look like:</P><P style=" text-align : justify; "><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Picture 1.png" style="width: 722px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/71905iEDF835C79461B9D9/image-dimensions/722x240?v=v2" width="722" height="240" role="button" title="Picture 1.png" alt="Picture 1.png" /></span></P><P style=" text-align : justify; ">Here, in this part, our goal is to establish the basic hello world programming essentials. This implementation requires no prior knowledge – we will teach you everything you need to know to become a proficient Graph developer. To test that everything works, we will re-use the Graph server that was configured as an SAP Business Accelerator Hub sandbox, and that we used in <A href="https://community.sap.com/t5/technology-blogs-by-sap/graph-tutorial-part-1-introduction-to-graph-in-sap-integration-suite/ba-p/13615255" target="_self">Part 1</A>.</P><H2 id="toc-hId-987847579">Getting Started: Node.js and NPM</H2><P style=" text-align : justify; ">We will use <STRONG>node.js</STRONG> (v20.11.1) and <STRONG>npm&nbsp;</STRONG>(version 10.2.4) to build this application and to keep it extremely simple, we will use the express web framework. Not familiar with node.js and express? I recommend <A title="Mozilla Developer Network - Introduction to Express JS " href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction" target="_blank" rel="noopener nofollow noreferrer">this</A> article on the&nbsp;Mozilla Developer Network (MDN) website. This article also explains how to easily set up a Node development environment, whether you use Windows, MacOS, or Linux.</P><P style=" text-align : justify; ">If you prefer to develop applications in the cloud directly from your browser, SAP offers a great cloud-based development experience alternative in the form of the SAP Build. Follow this link for more details on getting your instance. The rest of this blog assumes that you installed node.js and npm on your computer.</P><H2 id="toc-hId-791334074"><STRONG><FONT face="courier new,courier">package.json</FONT></STRONG></H2><P style=" text-align : justify; ">Select a folder (directory) where you want to develop your application. In this folder, create a small file called <FONT face="courier new,courier"><STRONG>package.json</STRONG></FONT>, with the following content:</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>{ "name": "hello-graph", "version": "0.0.0", "private": true, "type": "module", "script" : { "start": "node src/hellograph.js" }, "dependencies": { "express": "4.18.1", "node-fetch": "3.3.2", "universal-cookie": "7.1.0" } }</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P style=" text-align : justify; "><FONT face="arial,helvetica,sans-serif">Note: For the latest version of these libraries please refer to <A href="https://www.npmjs.com/" target="_blank" rel="noopener nofollow noreferrer">https://www.npmjs.com/</A> </FONT></P><P style=" text-align : justify; ">After saving the file, run the following command on your console:</P><PRE><FONT face="arial,helvetica,sans-serif">npm install</FONT></PRE><P style=" text-align : justify; ">If your node.js environment was properly set up, then this command will install a few standard library packages in a new sub-folder called <FONT face="arial,helvetica,sans-serif"><STRONG><FONT face="courier new,courier">node_modules</FONT></STRONG>.<BR /></FONT>Now, create another sub-folder, next to&nbsp;<FONT face="arial,helvetica,sans-serif"><STRONG><FONT face="courier new,courier">node_modules</FONT></STRONG></FONT>, called&nbsp;<FONT face="arial,helvetica,sans-serif"><STRONG><FONT face="courier new,courier">src</FONT></STRONG></FONT>. This is where we will develop our code.</P><H2 id="toc-hId-594820569"><STRONG><FONT face="courier new,courier">graph.js</FONT></STRONG></H2><P style=" text-align : justify; ">First, we will create a boilerplate file in the <STRONG><FONT face="courier new,courier">src</FONT></STRONG> folder, called <STRONG><FONT face="courier new,courier">graph.js</FONT></STRONG>. This file will serve as a foundational template that you'll reuse, with a few small changes, across all future Graph implementation blogs and your projects. This file will contain a class called Graph, which provides a nice wrapper for using Graph. At this time, we will show how to read data, using a <STRONG><FONT face="courier new,courier">get()</FONT></STRONG> function.</P><P style=" text-align : justify; ">Copy and paste the code below into the file, then save it. This straightforward snippet utilizes the node-fetch package for simplicity.</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>import fetch from "node-fetch"; export default class Graph { async get(entity, params) { const url = `https://sandbox.api.sap.com/sapgraph/${entity}${params ? `?${params}` : ""}`; console.log(url) //for debugging const options = { method: "get", headers:{ "Accept": "application/json", "apiKey": "&lt;your-api-key&gt;" // TODO: Enter the actual key } }; const response = await fetch(url, options); console.log(`${response.status} (${response.statusText})`) // for debugging return await response.json(); } }</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P style=" text-align : justify; ">Please note that we hard-coded the Graph server that uses the SAP Business Accelerator Hub sandbox. This allows us to focus here on the data access API, without requiring you to configure a new Business Data Graph(BDG) and deal with all the complex aspects of security and authentication, which will be the subject of future blog series.<BR />Since we are accessing the sandbox landscape data via SAP Business Accelerator Hub, you will need to insert your API Key (a short string) into the code above. Where do you get this key? Simply log in to <A title="SAP API Hub" href="https://api.sap.com/settings" target="_self" rel="noopener noreferrer">https://api.sap.com/settings</A> and click on <STRONG>Show API Key</STRONG> to see and save it.</P><H2 id="toc-hId-398307064"><STRONG><FONT face="courier new,courier">hellograph.js</FONT></STRONG></H2><P style=" text-align : justify; ">Now we are ready to write our first, simple server-side application that uses Graph. Paste the following into a new file, called<STRONG><FONT face="courier new,courier"> hellograph.js</FONT></STRONG>, in the <FONT face="courier new,courier"><STRONG>src</STRONG></FONT> folder:</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>import express from 'express'; import Graph from './graph.js'; const app = express(); const port = 3004; const graph = new Graph(); app.get('/sap*', async (req, res) =&gt; { const response = await graph.get(req, `${req.url}`, ""); res.send(`&lt;pre&gt;&lt;code&gt;${JSON.stringify(response, null, 2)}&lt;/code&gt;&lt;/pre&gt;`); }); app.listen(port, () =&gt; { console.log(`Explore Graph at http://localhost:${port}`) });</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P style=" text-align : justify; ">As previously mentioned, our code uses a popular node.js package called express. On line 8, we define the action taken when our server-side app is called from a browser. Here, we simply take the URL that we received (<FONT face="courier new,courier"><STRONG>req.url</STRONG></FONT>) and pass it through to Graph. We then show the returned data from Graph as a raw result on the browser screen.</P><P style=" text-align : justify; ">Our server-side app is ready. To run it, use your terminal console to enter:</P><PRE>npm run start</PRE><P style=" text-align : justify; ">The console will show:</P><PRE>$ Explore Graph at http://localhost:3004&nbsp;</PRE><P style=" text-align : justify; ">Now the fun begins. The application expects a well-formed query URL to function properly. Open a browser window or tab, and enter the following query URL:</P><PRE>http://localhost:3004/sap.graph/SalesQuote?$top=2</PRE><P style=" text-align : justify; ">The browser will invoke your application code, which will call Graph to fetch the data, and if all goes well, you will see the following output on your screen.&nbsp;</P><P style=" text-align : justify; "><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="2024-02-27_14-03-55.png" style="width: 746px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/71937i23F3BB1BE0551DA5/image-size/large?v=v2&amp;px=999" role="button" title="2024-02-27_14-03-55.png" alt="2024-02-27_14-03-55.png" /></span></SPAN></P><P style=" text-align : justify; ">Note: if you get an unformatted result, you can install a JSON formatter in your browser.&nbsp;<BR />Our Hello Graph app is already pretty useful; we can use it to explore the business data graph, by trying out different OData queries. Note: to stop your app from running, simply kill it (e.g. press CTRL-C on your Linux terminal or Windows console).<BR />We will re-use this app as a skeleton in the <A href="https://community.sap.com/t5/technology-blogs-by-sap/graph-intro-series-part-5-use-graph-securely-with-real-data-authentication/ba-p/13622195" target="_self">next part</A> of this series, where we will introduce authentication.</P><HR /><P style=" text-align : justify; "><STRONG>Shardul Sonar</STRONG>, Developer – Graph in SAP Integration Suite</P><P style=" text-align : justify; "><SPAN><A href="https://pages.community.sap.com/topics/graph" target="_blank" rel="noopener noreferrer">Learn more about Graph in the SAP Community</A></SPAN></P> 2024-02-28T10:16:21.965000+01:00 https://community.sap.com/t5/technology-blogs-by-sap/graph-intro-series-part-5-use-graph-securely-with-real-data-authentication/ba-p/13622195 Graph intro series, part 5: Use Graph Securely with Real Data – Authentication 2024-02-28T15:12:59.976000+01:00 LeonidGunko https://community.sap.com/t5/user/viewprofilepage/user-id/1406385 <P><SPAN>Here, in </SPAN><SPAN>this part</SPAN><SPAN> of this tutorial, we are going to build the rudimentary basics of a classical enterprise extension web app: a list-details-navigate application. Please refer to</SPAN> <A href="https://community.sap.com/t5/technology-blogs-by-sap/graph-tutorial-part-1-introduction-to-graph-in-sap-integration-suite/ba-p/13615255" target="_blank"><SPAN>Part 1</SPAN></A> <SPAN>of this tutorial for an introduction to Graph</SPAN><SPAN> in SAP Integration Suite</SPAN><SPAN>, </SPAN><SPAN>to the previous tutorial part</SPAN><SPAN> for an introduction to the programming interface of Graph, and to the</SPAN> <A href="https://community.sap.com/t5/technology-blogs-by-sap/information-map-multi-part-tutorial-graph-in-sap-integration-suite/ba-p/13614448" target="_blank"><SPAN>Information Map</SPAN></A><SPAN> for an introduction to the entire tutorial series.</SPAN><SPAN>&nbsp;</SPAN></P><P><STRONG><SPAN>Business Data Graphs</SPAN></STRONG><SPAN>&nbsp;</SPAN></P><P><SPAN>In</SPAN><SPAN> the <A href="https://community.sap.com/t5/technology-blogs-by-sap/graph-intro-series-part-4-hello-graph-write-your-first-graph-application/ba-p/13620393" target="_self">previous part</A></SPAN><SPAN>, we accessed data from a preconfigured Graph sandbox server via SAP </SPAN><SPAN>Business Accelerator Hub</SPAN><SPAN>. We even embedded this server URL into our code. Anybody with an API key can access the sandbox data, without any further authentication or authorization.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Of course, this is not a secure way of accessing confidential business data. Therefore, in this part of the tutorial, we will access Graph securely, via the oAuth protocol. OAuth doesn’t share password data but instead uses </SPAN><I><SPAN>authorization tokens</SPAN></I><SPAN> to prove an identity between clients and services like Graph and supports Single Sign On. With oAuth, you effectively approve your browser to interact with Graph on your behalf without giving away your password.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Graph is a multitenant service. Customer administrators use the SAP Business Technology Platform (BTP) to </SPAN><I><SPAN>subscribe to Graph</SPAN></I><I><SPAN> in SAP Integration Suite</SPAN></I><SPAN>, by configuring one or more </SPAN><STRONG><I><SPAN>business data graphs</SPAN></I></STRONG><SPAN>. We</SPAN> <SPAN>discuss this topic in more detail in a </SPAN><SPAN>separate part</SPAN><SPAN> of this tutorial, but </SPAN><SPAN>for this tutorial part it</SPAN><SPAN> is important to understand that the business data graph is the key to a specific </SPAN><I><SPAN>landscape</SPAN></I><SPAN> of customer systems. Most customers will configure multiple landscapes, for instance for development, staging and productive usage.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Each Graph business data graph is unique with unique credentials, such as its URL, its business data graph identifier and various secrets/tokens.</SPAN><SPAN>&nbsp;</SPAN></P><P><STRONG><SPAN>credentials.js</SPAN></STRONG><SPAN>&nbsp;</SPAN></P><P><SPAN>To programmatically access the data from a Graph business data graph, an application requires these credentials. How do you get them? A file containing them, </SPAN><STRONG><SPAN>credentials.json</SPAN></STRONG><SPAN>, is created during the process of setting up and configuring the business data graph. You receive this file and the business data graph identifier from the BTP administrator or key user who configured the specific business data graph you want to access.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Save the credentials file in the </SPAN><STRONG><SPAN>src</SPAN></STRONG><SPAN> folder of your project (you can use the existing </SPAN><STRONG><SPAN>src </SPAN></STRONG><SPAN>folder in which we developed our very first </SPAN><I><SPAN>hello Graph</SPAN></I><SPAN> server-side application, or create a new source folder in your project, up to you).</SPAN><SPAN>&nbsp;</SPAN></P><P><STRONG><SPAN>auth.js</SPAN></STRONG><SPAN>&nbsp;</SPAN></P><P><SPAN>In the same </SPAN><STRONG><SPAN>src </SPAN></STRONG><SPAN>folder, create a file called </SPAN><STRONG><SPAN>auth.js</SPAN></STRONG><SPAN>, paste in the following boilerplate (standard) code, and save:</SPAN><SPAN>&nbsp;</SPAN></P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>import credentials from "./credentials.json" assert { type: "json" }; import fetch from "node-fetch"; import Cookies from "universal-cookie"; const CALLBACK_URI = "/myCallbackURI"; const CookieName = "SAPGraphHelloQuotesCookie"; export default class Auth { constructor() { this.clientId = credentials.uaa.clientid; this.clientSecret = credentials.uaa.clientsecret; this.authUrl = credentials.uaa.url; } getToken(req) { const cookies = new Cookies(req.headers.cookie); return cookies.get(CookieName); } async fetchToken(code, redirectUri) { const params = new URLSearchParams(); params.set('client_id', this.clientId); params.set('client_secret', this.clientSecret); params.set('code', code); params.set('redirect_uri', redirectUri); params.set('grant_type', 'authorization_code'); const response = await fetch(`${this.authUrl}/oauth/token`, { method: 'post', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json' }, body: params }); const json = await response.json(); return json.access_token; } getMiddleware() { return async (req, res, next) =&gt; { const redirectUri = `${req.protocol}://${req.get("host")}${CALLBACK_URI}`; if (req.url.startsWith(CALLBACK_URI)) { const code = req.query.code; if (code) { const token = await this.fetchToken(code, redirectUri); res.cookie(CookieName, token, { maxAge: 1000 * 60 * 120, httpOnly: true, path: "/", }); } res.redirect("/"); } else if (!this.getToken(req)) { res.redirect(`${this.authUrl}/oauth/authorize?client_id=${encodeURIComponent(this.clientId)}&amp;redirect_uri=${encodeURIComponent(redirectUri)}&amp;response_type=code`); } else { next(); } }; } }</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P><SPAN>As you can see, this boilerplate authentication code refers to several pieces of information which are extracted from the </SPAN><STRONG><SPAN>credentials.json</SPAN></STRONG><SPAN> file, and are used to log the user of your application in, using single sign on, according to the specifics of the business data graph. For the user’s convenience, it also saves the obtained access token as a cookie, so that it can be used until it expires.</SPAN><SPAN>&nbsp;</SPAN></P><P><STRONG><SPAN>graph.js</SPAN></STRONG><SPAN>&nbsp;</SPAN></P><P><SPAN>We will re-use the Graph class that we saw in</SPAN><SPAN> the previous part </SPAN><SPAN>of this tutorial, but now that we are required to authenticate the user before we can use the business data graph, we need to make a few small changes. Copy the following text into </SPAN><STRONG><SPAN>graph.js</SPAN></STRONG><SPAN> and save.</SPAN><SPAN>&nbsp;</SPAN></P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>import credentials from "./credentials.json" assert { type: "json" }; import fetch from "node-fetch"; const apiUrl = credentials.uri; const dataGraphId = "v1"; // example, modify accordingly export default class Graph { constructor(auth) { this.auth = auth; this.apiUrl = apiUrl; this.dataGraphId = dataGraphId; } async get(req, entity, params) { const token = this.auth.getToken(req); const url = `${this.apiUrl}/${this.dataGraphId}/${entity}${params ? `?${params}` : ""}`; console.log(url) //for debugging const options = { method: "get", headers: { "Authorization": `Bearer ${token}`, "Accept": "application/json" } }; const response = await fetch(url, options); console.log(`${response.status} (${response.statusText})`) // for debugging const json = await response.json(); return json; } }</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P><SPAN>You can see that we made two small changes. The Graph URL is now determined from the credentials of the specific business data graph, and the authorization token, obtained during user authentication, is passed to Graph. You may have to modify the business data graph identifier string from “v1” in the above code, before saving the file.</SPAN><SPAN>&nbsp;</SPAN></P><P><STRONG><SPAN>helloQuotes.js</SPAN></STRONG><SPAN>&nbsp;</SPAN></P><P><SPAN>Now are we finally ready to build the rudimentary basics of a classical three-page enterprise extension web app: a </SPAN><I><SPAN>list-details-navigate application</SPAN></I><SPAN>. This is what it will eventually look like:</SPAN><SPAN>&nbsp;</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="LeonidGunko_2-1709118113938.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/72583i865A28B78BD77ADD/image-size/medium?v=v2&amp;px=400" role="button" title="LeonidGunko_2-1709118113938.png" alt="LeonidGunko_2-1709118113938.png" /></span></P><P><SPAN>Don’t expect fancy code, with all the necessary error and exception handling of a robust, production-ready application. Our goal is to show how easy it is to just create small business applications using</SPAN> <SPAN>Graph; we will discuss the finer aspects of robust Graph clients in another part of this tutorial.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>We will first establish the skeleton of our application, in a file we will call </SPAN><STRONG><SPAN>helloQuotes.js</SPAN></STRONG><SPAN>:</SPAN><SPAN>&nbsp;</SPAN></P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>// Hello Quote - our first SAP Graph extension app import express from 'express'; import Graph from './graph.js'; import Auth from './auth.js'; const app = express(); const port = 3003; const auth = new Auth(); app.use(auth.getMiddleware()); const graph = new Graph(auth); // ------------------ 1) get and display a list of SalesQuotes ------------------ // ------------------ 2) show one quote and its items ------------------ // ------------------ 3) navigate to the product details for all the items in the quote ------------------ app.listen(port, () =&gt; { console.log(`Example app listening at http://localhost:${port}`) });</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P><SPAN>This code doesn’t do anything interesting. It basically logs in the user, using the standard authentication that we just discussed, and then listens on port 3003 for web (REST) requests. To make the code work, we need to install </SPAN><I><SPAN>request handlers</SPAN></I><SPAN>.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Using the </SPAN><I><SPAN>express</SPAN></I><SPAN> framework, we now create three such handlers, corresponding to three different expected URLs:</SPAN><SPAN>&nbsp;</SPAN></P><OL><LI><SPAN>The root (/)</SPAN><SPAN>&nbsp;</SPAN></LI></OL><OL><LI><SPAN>Request for a quote: /quote/…</SPAN><SPAN>&nbsp;</SPAN></LI></OL><OL><LI><SPAN>Request for a quote’s product details: /quote… /product</SPAN><SPAN>&nbsp;</SPAN></LI></OL><P><SPAN>Here is the first request handler:</SPAN></P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>// ------------------ 1) get and display a list of SalesQuotes ------------------ app.get('/', async (req, res) =&gt; { const quotes = await graph.get(req, "sap.graph/SalesQuote", "$top=20"); const qlist = quotes.value.map(q =&gt; `(${q.netAmount} ${q.netAmountCurrency})`).join(""); res.send(` &lt;h1&gt;Hello Quotes&lt;/h1&gt; ${qlist} `); });</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P><SPAN>The handler will be fired if the browser requests the root document (“/”). What does the code do? It fetches the first 20 quotes (</SPAN><STRONG><SPAN>sap.graph/SalesQuote</SPAN></STRONG><SPAN>), and then wraps the resulting information (date and total amount) in HTML, and returns it.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Go ahead, paste this handler into the app skeleton, save, and run the server-side app on your terminal console as follows:</SPAN><SPAN>&nbsp;</SPAN></P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>node helloQuotes.js </code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P><SPAN>Open a new browser tab and enter the URL </SPAN><I><SPAN><A href="http://localhost:3003" target="_blank" rel="noopener nofollow noreferrer">http://localhost:3003</A></SPAN></I><SPAN>. If all went well, you will now see a list of dates and corresponding amounts in the browser.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>That was nice, but not very interesting. To turn your app into an interesting list-details app, </SPAN><I><SPAN>modify</SPAN></I><SPAN> the </SPAN><STRONG><SPAN>qlist</SPAN></STRONG><SPAN> assignment above to introduce a </SPAN><I><SPAN>link</SPAN></I><SPAN>, as follows:</SPAN><SPAN>&nbsp;</SPAN></P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>const qlist = quotes.value.map(q =&gt; `&lt;p&gt; &lt;a href="/quote/${q.id}"&gt;${q.pricingDate} &lt;/a&gt; (${q.netAmount} ${q.netAmountCurrency}) &lt;/p&gt;`).join(""); </code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P><SPAN>Now, when the user clicks on one of the quotes, your app will be called again, and this time the URL will match ‘</SPAN><STRONG><SPAN>/quote</SPAN></STRONG><SPAN>…’.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Let us now also introduce our second and third handlers:</SPAN><SPAN>&nbsp;</SPAN></P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>// ------------------ 2) show one quote and its items ------------------ app.get('/quote/:id', async (req, res) =&gt; { const id = req.params.id; const singleQuote = await graph.get(req, `sap.graph/SalesQuote/${id}`, "$expand=items&amp;$select=items"); const allItemLinks = singleQuote.items.map(item =&gt; `&lt;p&gt;&lt;a href="/quote/${id}/item/${item.itemId}"&gt;&lt;button&gt;Product details for item ${item.itemId}: ${item.product}&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;`).join(""); res.send(` &lt;h1&gt;SalesQuote - Detail&lt;/h1&gt; &lt;h4&gt;&lt;code&gt;id: ${id}&lt;/code&gt;&lt;/h4&gt; ${allItemLinks} `); }); // ------------------ 3) navigate to the product details for an item in the quote ------------------ app.get('/quote/:id/item/:itemId', async (req, res) =&gt; { const id = req.params.id; const itemId = req.params.itemId; const product = await graph.get(req, `sap.graph/SalesQuote/${id}/items/${itemId}/_product`, "$expand=distributionChains"); res.send(` &lt;h1&gt;Product Detail&lt;/h1&gt; &lt;h4&gt;&lt;code&gt;For SalesQuote ${id} and item ${itemId}&lt;/code&gt;&lt;/h4&gt; &lt;pre&gt;&lt;code&gt;${JSON.stringify(product, null, 2)}&lt;/code&gt;&lt;/pre&gt; `); });</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P><SPAN>The OData query at the heart of the second handler uses the </SPAN><STRONG><SPAN>$expand</SPAN></STRONG><SPAN> query parameter to fetch the details of the quote, including what was quoted (items). The product id in the quote is then used in the third handler to </SPAN><I><SPAN>navigate </SPAN></I><SPAN>across the business graph, to fetch the detailed product information from the product catalog. In both cases, the data is just dumped to the screen as JSON, but evidently, a real app would format the information much more nicely.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Go ahead, make the change in the first handler, and then paste the second and third handlers in your code, save the file, restart the service, and refresh the </SPAN><STRONG><SPAN>localhost:3003 </SPAN></STRONG><SPAN>page in the browser. Voila! Your app is live.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>Note again, how you, as a developer, never had to ask yourself where the data came from. You just navigated from a quote object to a product object, without any effort. The landscape that you accessed via the configured business data graph may have managed quotes in SAP Sales Cloud, or in SAP S/4HANA, and the product catalog may have been, theoretically, in yet another system. You simply don’t have to care.</SPAN><SPAN>&nbsp;</SPAN></P><P><SPAN>&nbsp;</SPAN></P><P><SPAN>—————————————————————————————————————————&nbsp;</SPAN></P><P><SPAN>Leonid Gunko, Developer – Graph in SAP Integration Suite</SPAN><SPAN>&nbsp;</SPAN></P><P><A href="https://pages.community.sap.com/topics/graph" target="_blank" rel="noopener noreferrer"><SPAN>Learn more about Graph in the SAP Community</SPAN></A><SPAN>&nbsp;</SPAN></P><P>&nbsp;</P> 2024-02-28T15:12:59.976000+01:00 https://community.sap.com/t5/technology-blogs-by-sap/sap-recognized-as-a-leader-in-2024-gartner-magic-quadrant-for-ipaas/ba-p/13623157 SAP Recognized as a Leader in 2024 Gartner® Magic Quadrant™ for iPaaS 2024-02-29T05:15:00.020000+01:00 piyush_gakhar https://community.sap.com/t5/user/viewprofilepage/user-id/182218 <P style=" text-align : justify; "><FONT size="3">We are proud to announce that Gartner has recognized SAP as a Leader in the Gartner Magic Quadrant for Integration Platform as a Service (iPaaS) worldwide. SAP’s Integration Suite was evaluated and based on various factors including reviews of current users of our service. We were recognized as a Leader for the fourth consecutive time. We believe we have received this recognition for the targeted efforts to deliver a customer-centric service with a strong focus on innovation and being future-ready.</FONT></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="piyush_gakhar_0-1709178652583.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/73072i1976FA73A84F6DD2/image-size/medium?v=v2&amp;px=400" role="button" title="piyush_gakhar_0-1709178652583.png" alt="piyush_gakhar_0-1709178652583.png" /></span></P><P style=" text-align : justify; ">Built as a single, comprehensive integration platform, SAP Integration Suite empowers you to integrate and automate processes with speed and confidence across SAP and third-party landscapes. You can leverage our pre-built integrations, APIs, connectors and best practices to design end-to-end automated business processes and deliver innovations that can set you apart from your competition. You can learn more about it <A href="https://www.sap.com/india/products/technology-platform/integration-suite.html" target="_blank" rel="noopener noreferrer">here</A>.</P><P>SAP is recognized for its ability to execute, we believe this validates our customer-centric approach to product development and evolution. Our innovations which include new integration patterns and artificial intelligence-based features that enhance developer productivity, were rated highly.</P><P style=" text-align : justify; ">We offer a strong commercial and product support presence across all geographical regions. This makes Integration Suite one of the few truly global managed iPaaS offerings suitable for all market segments. We also offer deployment flexibility with our service’s ability to be deployed on client data centers, data centers for regulated industries and private cloud regions.</P><P style=" text-align : justify; ">It gives us immense satisfaction to see that 97% of our customers strongly recommend SAP Integration Suite on Gartner® Peer Insights™. We feel this is an indicator of our customer-focused execution and a shot in the arm for our teams to double down on our roadmap and continue to deliver innovations. Customers also reported that their trust in our roadmap and vision is 4.5% higher than the market average reported by We focus on ensuring that our customers have an enterprise-grade feature set that can help them remain competitive in a market that continues to evolve at a rapid pace, while also ensuring that their investments in SAP Integration Suite is protected for the foreseeable future.</P><H1 id="toc-hId-858852191">What makes Integration Suite a Leader in the iPaaS Market?</H1><P style=" text-align : justify; ">SAP Integration Suite is an AI-assisted integration platform as a service (iPaaS). With this single solution, you can connect applications from SAP and third parties, whether they run on-premise or across clouds. You can use a combination of integration modes to address specific use cases and run your integrations on major public clouds for greater flexibility.</P><P>Robust functionality in SAP Integration Suite means you can confidently integrate and manage your mission-critical processes across SAP and third-party applications in complex and distributed landscapes.</P><P>Here are some of the key value propositions that we believe set SAP Integration Suite apart from the competition:</P><OL><LI><STRONG>Third-Party Connectivity:</STRONG> SAP Integration Suite is a general-purpose iPaaS that can easily integrate with third-party applications as well. We offer 250+ third-party application connectors in addition to protocol-based connectors that can be used to connect with different systems. We also have a strong roadmap to increase the number of non-SAP connectors, further demonstrating our intent to be an excellent all-purpose iPaaS.</LI><LI><STRONG>Runtime Deployment Flexibility:</STRONG> Depending on your needs and security constraints, you can choose to deploy our runtime in the public cloud, private cloud, within your private data centres, or employ a hybrid setup with runtimes in both public and private regions.</LI><LI><STRONG>Power of Artificial Intelligence:</STRONG> We at SAP are committed to leveraging artificial intelligence in the Integration Suite to boost developer productivity and insights via behavioural patterns that include mapping proposals, industry-based inter selection and scenario generation. This is a priority topic for us and we are investing continuously to offer a true next-gen integration platform.</LI><LI><STRONG>Enterprise Automation:</STRONG> We at SAP believe that Process Automation is the key to any digital transformation and our endeavour is to equip you with the tools necessary to build end-to-end intelligent business and IT processes. In combination with SAP Signavio and SAP Build, we offer the perfect enterprise trifecta for Enterprise Automation.<STRONG>&nbsp;</STRONG></LI><LI><STRONG>API and Event-Driven Integration: </STRONG>Support for modern integration patterns is a critical aspect of any future-proof iPaaS. Integration Suite supports and offers best practices for both API-centric and event-driven integrations. We offer out-of-the-box 600+ business events and ~4000 APIs on the SAP Business Accelerator Hub, with the number growing at a rapid pace as more SAP LoBs publish their content on the hub.<STRONG>&nbsp;</STRONG></LI><LI><STRONG>SAP Process Orchestration Move: </STRONG>We are very cognizant of the fact that many of our customers have significant investments in SAP Process Orchestration, and we are fully committed to helping them transition to Integration Suite with the least business disruption and maximum reusability while staying true to the digital transformation objective. Our migration tools and special programs like Migration Factory focused on migration help customers craft a strategic journey that will ensure the lowest TCO and highest value in their transition from the on-premise SAP Process Orchestration to the hybrid SAP Integration Suite.</LI><LI><STRONG>Business Integration Content: </STRONG><SPAN>Getting started quickly by using integration packages infused with business expertise and best-in-class industry experience on the SAP Business Accelerator hub has been one of our unique offerings for our customers. We engage our vibrant community to develop content in a collaborative model and offer it to our customer base.&nbsp;As of today, SAP offers 3400+ pre-packaged Integrations including SAP and third-party integration scenarios.</SPAN></LI></OL><P><STRONG>&nbsp;Summary</STRONG></P><P>We are very grateful for the vote of confidence from our customers, partners, and analysts that has culminated in SAP. We are happy to be recognized as a Leader in Gartner Magic Quadrant for Enterprise iPaaS. We feel, this is validation and it has boosted our confidence that we are heading in the right direction and will further energize us to deliver more customer-centric features and innovations while staying true to our core principles of high developer productivity, happy user experience, and optimized total cost of ownership (TCO).</P><P><STRONG>&nbsp;</STRONG><STRONG>Where Can I Learn More?&nbsp;</STRONG><STRONG>&nbsp;</STRONG><BR /><BR /></P><UL><LI><A href="https://news.sap.com/2024/02/sap-named-leader-2024-gartner-magic-quadrant-ipaas/" target="_blank" rel="noopener noreferrer">Read the News Center feature by JG Chirapurath</A></LI><LI><A href="https://www.sap.com/cmp/dg/integration-platform-as-a-service-leader/index.html" target="_self" rel="noopener noreferrer">Access the full report&nbsp;</A></LI><LI><A href="https://www.sap.com/products/technology-platform/integration-suite.html" target="_blank" rel="noopener noreferrer">SAP Integration Suite&nbsp;Product Page</A></LI><LI><A href="https://gateway.on24.com/wcc/eh/3869277/integration-space" target="_blank" rel="noopener nofollow noreferrer">Explore exclusive iPaaS content on SAP Integration Space</A></LI><LI><A href="https://discovery-center.cloud.sap/serviceCatalog/integration-suite?category=integration" target="_blank" rel="noopener nofollow noreferrer">Integration Suite @ Discovery Center</A></LI><LI><A href="https://open.sap.com/courses/btp3" target="_blank" rel="noopener noreferrer">OpenSAP Course on SAP Integration Suite&nbsp;&nbsp;</A></LI><LI><A href="https://open.sap.com/courses/btp4" target="_blank" rel="noopener noreferrer">Manage B2B Scenarios Effectively with SAP Integration Suite | openSAP</A></LI><LI><A href="https://community.sap.com/topics/integration-suite" target="_blank">SAP Integration Suite Community</A>&nbsp;&nbsp;</LI><LI><A href="https://help.sap.com/docs/SAP_INTEGRATION_SUITE" target="_blank" rel="noopener noreferrer">SAP Integration Suite on SAP Help Portal</A>&nbsp;&nbsp;</LI></UL><H6 id="toc-hId-1307752281"><FONT size="1 2 3 4 5 6 7"><STRONG>GARTNER is a registered trademark and service mark of Gartner and Magic Quadrant and Peer Insights are&nbsp;a registered trademark, of Gartner, Inc. and/or its affiliates in the U.S. and internationally and are used herein with permission. All rights reserved.</STRONG></FONT></H6><H6 id="toc-hId-1111238776"><FONT size="1 2 3 4 5 6 7"><STRONG>Gartner Peer Insights content consists of the opinions of individual end-users based on their own experiences with the vendors listed on the platform, should not be construed as statements of fact, nor do they represent the views of Gartner or its affiliates. Gartner does not endorse any vendor, product or service depicted in this content nor makes any warranties, expressed or implied, with respect to this content, about its accuracy or completeness, including any warranties of merchantability or fitness for a particular purpose.</STRONG></FONT></H6><H6 id="toc-hId-914725271"><FONT size="1 2 3 4 5 6 7"><STRONG>Gartner does not endorse any vendor, product or service depicted in its research publications and does not advise technology users to select only those vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner’s research organization and should not be construed as statements of fact. Gartner disclaims all warranties, expressed or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose.</STRONG></FONT></H6><H6 id="toc-hId-718211766"><FONT size="1 2 3 4 5 6 7"><STRONG>This graphic was published by Gartner, Inc. as part of a larger research document and should be evaluated in the context of the entire document. The Gartner document is available upon request from SAP.</STRONG></FONT></H6><H6 id="toc-hId-521698261">&nbsp;</H6><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P> 2024-02-29T05:15:00.020000+01:00 https://community.sap.com/t5/enterprise-resource-planning-blogs-by-members/there-is-no-ai-without-api-integration-is-the-backbone-of-digital/ba-p/13626331 There is no AI without API - Integration is the backbone of digital transformations. 2024-03-04T08:00:00.021000+01:00 MichalKrawczyk https://community.sap.com/t5/user/viewprofilepage/user-id/45785 <H1 id="toc-hId-858943418">Why API?</H1><P>When we talk about AI <SPAN>(like generative AI) </SPAN>we need to remember they can't do much alone. They need APIs, which are like bridges, to connect them to other <SPAN>applications or</SPAN> software in general. This way, AI can get the data it needs and tell other systems what to do. Think of AI as someone who wants to cook but needs someone else to bring the ingredients and turn on the stove. That helper is the API.</P><P style=" text-align: center; "><FONT size="5">"<SPAN>Integration is the backbone of digital transformations and APIs are the building blocks of every SAP customer who sells, buys or transports their products with its use" - Michal Krawczyk&nbsp;</SPAN></FONT></P><P style=" text-align: center; ">&nbsp;</P><H1 id="toc-hId-662429913">Why APIs are Important for AI - communication layer?&nbsp;</H1><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="api_ai.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/74721i4CFB39F1E9A3A78A/image-size/medium?v=v2&amp;px=400" role="button" title="api_ai.png" alt="api_ai.png" /></span></P><P>Figure 1 - AI cannot exist without API as it needs it to communicate&nbsp;</P><H2 id="toc-hId-594999127">APIs help AI in many ways:</H2><P><STRONG>Getting Data:</STRONG> AI needs lots of information to learn and make decisions. APIs bring this data to AI from different places.</P><P><STRONG>Working Together:</STRONG> Different programs and applications (event from SAP Ecosystem) don't always speak the same language. APIs help them understand each other so AI can be part of the team.</P><P><STRONG>Creating New Things:</STRONG> With APIs, people can make new smart tools by using what's already there, like mixing different ingredients to bake a new cake.</P><P>&nbsp;</P><H1 id="toc-hId-269402903">Things to Watch Out For</H1><P>APIs make a lot of things possible, but there are some issues, like keeping data safe, making sure private stuff stays private, and getting different APIs to work well together. Making APIs secure, protecting privacy, and making them fit together better are big tasks for the people who make them.</P><P>&nbsp;</P><H1 id="toc-hId-72889398">What's Next for AI and APIs (and iPaaS like SAP BTP Integration Suite)?&nbsp;</H1><P>As the world gets more connected and smart, AI and APIs will become even more important. We need better, safer, and easier-to-use APIs so AI can do more cool stuff in areas like health, money, making things, and moving around.&nbsp;In the future, we need APIs that can handle big tasks, keep data safe, and work well with all kinds of systems. This will help AI do more for us, making life easier and more interesting. When reading articles like&nbsp;<A href="https://www.nasdaq.com/articles/ipaas-emerges-as-the-dominant-platform-for-automation-and-integration" target="_self" rel="nofollow noopener noreferrer">iPaaS Emerges as the Dominant Platform for Automation and Integration</A>&nbsp;all of a sudden you may understand why we might see such a big expenditure shift in iPaaS technology like SAP BTP Integration Suite.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-01-31 at 2.32.34 PM (2).png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/74724i8EC9DC84E83D72BE/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-01-31 at 2.32.34 PM (2).png" alt="Screenshot 2024-01-31 at 2.32.34 PM (2).png" /></span></P><P>Figure 2 -&nbsp;Figure 2 - iPaaS Dominates the Automation + Integration Technology Market from linked article&nbsp;</P><P>&nbsp;</P><H1 id="toc-hId--123624107">To Summarise</H1><P>Just like a chef needs a good kitchen team, AI needs APIs to bring its smart ideas to life. Without APIs, AI can't do much. But with good APIs, AI can help us in many ways, making our world smarter and our lives better. As we move forward, making better APIs will help AI do even more amazing things.</P><P>&nbsp;</P> 2024-03-04T08:00:00.021000+01:00 https://community.sap.com/t5/technology-blogs-by-sap/the-state-of-integration-research-from-asug-and-sap/ba-p/13631727 The State of Integration – Research from ASUG and SAP 2024-03-07T21:19:30.312000+01:00 k-huthziegler https://community.sap.com/t5/user/viewprofilepage/user-id/1410925 <P>Integration is not only a technological investment, but also strategically imperative across organizations to thrive in today’s digital economy. Through the research conducted by ASUG, we know that the integration topic is highly relevant for ASUG members with almost all being actively involved in integration projects. The study also highlighted how SAP Integration Suite is being used today.</P><P>ASUG discovered that many customers use a wide range of connections with SAP applications including SAP SuccessFactors and SAP S/4HANA, but they are also connecting with a multitude of other non-SAP application types and in their landscapes. &nbsp;The ASUG research shows our customers growing diversity in their application landscape confirming the need for seamless integration across all application types. We have seen more customers connecting with non-SAP applications and these results validate what we have seen across our customer base. There are an equal number of integrations between SAP to SAP applications and SAP to 3rd party applications. Interestingly, over half of those surveyed are connecting non-SAP to non-SAP which speaks to the comprehensive set of features we have in Integration Suite.&nbsp;</P><P>The ASUG study also noted that 90% of respondents face challenges with integrations, with a wide array of issues experienced such as lack of internal skills/resources, data inconsistencies, and budget constraints top the list. However, many benefits can be realized from integrating data, processes, and/or applications. They include:</P><UL><LI>Improved use of data and analytics</LI><LI>Streamlined business processes</LI><LI>Better application adoption and use.</LI></UL><P>More than 1/3 of users also find realized value by using intelligence to drive business decisions and to collaborate with others.&nbsp;</P><P>Listen to this <A href="https://gateway.on24.com/wcc/eh/3869277/lp/4528948/insights-on-the-benefits-on-sap-integration-suite?partnerref=asugblog" target="_self" rel="nofollow noopener noreferrer">webcast</A> to learn more about how customers see having an integration strategy is critical, the benefits of implementing an integration strategy, the types of landscapes and applications they are integrating, what capabilities are most used, and what common challenges users experience with integration. Here’s a <A href="https://gateway.on24.com/wcc/eh/3869277/lp/4528941/sap-customers-embrace-integration-to-amplify-successful-outcomes?partnerref=asugblog%20" target="_self" rel="nofollow noopener noreferrer">synopsis</A> of the study.</P> 2024-03-07T21:19:30.312000+01:00 https://community.sap.com/t5/technology-blogs-by-members/how-to-remove-metadata-from-cpi-json-payload/ba-p/13632562 How to remove __Metadata from CPI json payload 2024-03-08T17:49:09.791000+01:00 Akash https://community.sap.com/t5/user/viewprofilepage/user-id/863626 <P>Hi,</P><P>Please suggest, how to remove __metadata from json payload using groovy script.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Akash_0-1709916373311.png" style="width: 691px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/77690iAEC8A729627793E3/image-dimensions/691x325?v=v2" width="691" height="325" role="button" title="Akash_0-1709916373311.png" alt="Akash_0-1709916373311.png" /></span></P><P>&nbsp;</P> 2024-03-08T17:49:09.791000+01:00 https://community.sap.com/t5/technology-blogs-by-sap/what-s-new-for-sap-integration-suite-february-2024/ba-p/13635001 What’s New for SAP Integration Suite – February 2024 2024-03-12T09:22:05.281000+01:00 GabrielaGahse https://community.sap.com/t5/user/viewprofilepage/user-id/4015 <P>Before going into the highlights of our innovations, we are thrilled to inform you that SAP Integration Suite has been recognized as a Leader in the latest Gartner Magic Quadrant for Integration Platform-as-a-Service (iPaaS) for the fourth consecutive time. We are convinced that we have been received this recognition for our commitments to deliver a top-tier customer-centric integration solution, the ability to accelerate business outcomes through prebuilt content, ongoing innovation, the global geographic strategy, and readiness for the future. And a big thanks also goes to you in supporting us with all your great feedback. For more details checkout the <A href="https://community.sap.com/t5/technology-blogs-by-sap/sap-recognized-as-a-leader-in-2024-gartner-magic-quadrant-for-ipaas/ba-p/13623157" target="_blank">blogpost</A> and the <A href="https://news.sap.com/2024/02/sap-named-leader-2024-gartner-magic-quadrant-ipaas/" target="_blank" rel="noopener noreferrer">SAP News article</A>.</P><P>SAP Integration Suite highlights are:</P><UL><LI>JMS receiver adapter: property to identify sending integration flow</LI><LI>Inspect resource consumption through SAP Cloud ALM/SAP Focused Run</LI><LI>Call to action: Upgrade to new version of third-party connectors</LI><LI>Duplicate nodes on target side in a MAG</LI><LI>Definition of more complex code value mapping scenarios</LI><LI>Add metadata for OData-based API artifacts deployed on Edge Integration Cell</LI><LI>Enhancement of security standards in API Management</LI><LI>Policy templates in API Management</LI><LI>Distributed tracing in advanced event mesh</LI><LI>Direct consumption of SAP S/4HANA Cloud events in advanced event mesh</LI></UL><H2 id="toc-hId-988916891">Cloud Integration</H2><H3 id="toc-hId-921486105">JMS receiver adapter: property to identify sending integration flow</H3><P>We have extended the JMS receiver adapter by storing a new <STRONG>SAP_IntegrationFlowID</STRONG> property. It contains the ID of the integration flow that has sent the message through the JMS receiver adapter. The JMS consumer can use this property to define steps depending on the sending integration flow ID. Refer the&nbsp;<A href="https://help.sap.com/docs/integration-suite/sap-integration-suite/headers-and-exchange-properties-provided-by-integration-framework" target="_blank" rel="noopener noreferrer">documentation</A>.&nbsp;</P><H3 id="toc-hId-724972600">Inspect resource consumption through SAP Cloud ALM/SAP Focused Run</H3><P>Inspection of your resource consumption has been available since the middle of last year. Now you may analyze the utilization of database and system resources through the health monitoring application of SAP Cloud ALM and SAP Focused Run. For troubleshooting bottlenecks caused by integration flows you may jump directly to the Inspect section of the Cloud Integration monitor.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="GabrielaGahse_0-1710162608878.png" style="width: 703px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/78583i4DDAA3ACF5EC10BD/image-dimensions/703x262?v=v2" width="703" height="262" role="button" title="GabrielaGahse_0-1710162608878.png" alt="GabrielaGahse_0-1710162608878.png" /></span></P><H3 id="toc-hId-528459095">Call to action: Upgrade to new version of third-party connectors</H3><P>As per <A href="https://me.sap.com/notes/3001980" target="_blank" rel="noopener noreferrer">SAP note 3001980</A> the following previous adapter versions are deprecated since end of 2020: Salesforce, Amazon Web Services, Microsoft Dynamics, SugarCRM. There haven't been any new features or enhancements for these previous adapter versions. After the upcoming Apache Camel upgrade, the adapter versions will no longer run.</P><P>Action is required from the customer's side. Check all your tenants to see whether you have any kind of the above adapters still deployed. Please undeploy and delete the adapters. In case of question reach out to <A href="mailto:annemarie.kiefer@sap.com" target="_blank" rel="noopener nofollow noreferrer">annemarie.kiefer@sap.com</A><SPAN>.</SPAN></P><H2 id="toc-hId-202862871">B2B Integration</H2><P>We have extended the mapping functionality of the Integration Advisor capability to offer you more flexibility.</P><H3 id="toc-hId-135432085">Duplicate nodes on target side in a MAG</H3><P>When designing B2B integration scenarios you may have situations where certain information within the source structure needs to be mapped to only one node in the target structure. Now the mapping guidelines editor of the Integration Advisor capability enables you to duplicate group or leave nodes and map each source alternative to one of the reproductions. Refer to the <A href="https://help.sap.com/docs/cloud-integration/sap-cloud-integration/mapping-source-and-target-nodes#duplicate-target-nodes" target="_blank" rel="noopener noreferrer">documentation</A>.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="GabrielaGahse_1-1710156933032.jpeg" style="width: 652px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/78430iB74065749B4DCFAC/image-dimensions/652x259?v=v2" width="652" height="259" role="button" title="GabrielaGahse_1-1710156933032.jpeg" alt="GabrielaGahse_1-1710156933032.jpeg" /></span></P><P>&nbsp;</P><H3 id="toc-hId--61081420">Definition of more complex code value mapping scenarios</H3><P>You are now able to define local or global mappings of multiple code values at the source side to one code value at the target side. The value function now supports N:1 cardinality code value mapping ease e.g., situations where you have to map multiple partners or currencies.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="GabrielaGahse_2-1710156933037.jpeg" style="width: 692px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/78429i302CBE7871F725EB/image-dimensions/692x285?v=v2" width="692" height="285" role="button" title="GabrielaGahse_2-1710156933037.jpeg" alt="GabrielaGahse_2-1710156933037.jpeg" /></span></P><H2 id="toc-hId--386677644">API Management</H2><H3 id="toc-hId--454108430">Add metadata for OData-based API artifacts deployed on Edge Integration Cell</H3><P>You can now supply an EDMX specification for API artifacts (API-led integration flows for deployment on Edge Integration Cell), that are based on OData APIs. This allows you to easily specify additional integration steps based on the resources of this API. See the detailed <A href="https://help.sap.com/docs/integration-suite/sap-integration-suite/create-api-artifact-using-url" target="_blank" rel="noopener noreferrer">documentation.</A></P><H3 id="toc-hId--650621935">Enhancement of security standards</H3><P>As always, our intention is to offer the highest security standards to avoid attack vulnerabilities. Therefore, we encourage you to use strong certificates, and will no longer accept uploads to the Trust Store of weak customer-owned self-signed certificates or certificate chains used for mTLS handshakes.&nbsp;Consequently, the OpenSSL security level has been increased to level 2. See a comprehensive definition of security level 2 published on the <A href="https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_security_level.html#DEFAULT-CALLBACK-BEHAVIOURInformation" target="_blank" rel="noopener nofollow noreferrer">OpenSLL site</A>. For additional details please see <A href="https://me.sap.com/notes/3418201" target="_blank" rel="noopener noreferrer">note -3418201</A>.</P><H3 id="toc-hId--922366809">Policy templates</H3><P>We have filled a small gap when applying policy templates to an API proxy. Default fault&nbsp;rules or post-client flows available within a policy template will now also be appended to the API proxy. Refer to the &nbsp;<A href="https://help.sap.com/docs/integration-suite/sap-integration-suite/apply-policy-template" target="_blank" rel="noopener noreferrer">documentation</A>.</P><H2 id="toc-hId--825477307">Event-driven Integration</H2><P>We have news regarding SAP Integration Suite, advanced event mesh our offering for distributed network of event brokers and sophisticated features.</P><H3 id="toc-hId--1315393819">Distributed tracing</H3><P>We have extended SAP Integration Suite, advanced event mesh with a distributed tracing capability. Now you are able to trace the the lifecycle of events through OpenTelemetry, from the producing application across one or multiple event brokers to the receiving application.</P><H3 id="toc-hId--1511907324">Direct consumption of SAP S/4HANA Cloud events</H3><P>We have an update regarding the event sources. We have enabled the direct consumption of SAP S/4HANA Cloud events into SAP Integration Suite, advanced event mesh without any intermediate hops. SAP S/4HANA Cloud customers may leverage SAP Integration Suite, advanced event mesh for very large projects, where performance is crucial. Read the <A href="https://help.sap.com/docs/SAP_S4HANA_CLOUD/0f69f8fb28ac4bf48d2b57b9637e81fa/9b34c841dfba4f82af0825a2f3196ecf.html?version=2402.500" target="_blank" rel="noopener noreferrer">documentation</A>.</P><H2 id="toc-hId--1415017822">How to stay tuned to recent and upcoming innovations?</H2><P>The SAP Road Map Explorer is your one-stop shop for all&nbsp;<A href="https://roadmaps.sap.com/board?PRODUCT=000D3A47875C1EDB98A8A910864AC24B&amp;range=CURRENT-LAST" target="_blank" rel="noopener noreferrer">SAP Integration Suite</A>&nbsp;innovations. You can easily check out the latest innovations and follow what is planned for the following quarters. All recent innovations also cover under the tab <EM>Features</EM> further links to blogposts or documentation.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="GabrielaGahse_0-1710227126039.png" style="width: 635px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/78987i1CA65BB89053CE1B/image-dimensions/635x237?v=v2" width="635" height="237" role="button" title="GabrielaGahse_0-1710227126039.png" alt="GabrielaGahse_0-1710227126039.png" /></span></P><P>We also refer to the complete list of new releases in our documentation: <A href="https://help.sap.com/whats-new/5793247a5d5741beb0decc5b7dee1160?locale=en-US" target="_blank" rel="noopener noreferrer">What’s New in SAP Integration Suite</A>.</P><P>And if you have not heard of&nbsp;our monthly webinars, I suggest you <A href="https://www.sap.com/cmp/nl/sap-cloud-platform-integration-suite/index.html?sap-outbound-id=6287F912007644D6C49C53EAA9594EE1B4431938&amp;smc_campaign_id=0000032983&amp;source=email-smc" target="_blank" rel="noopener noreferrer">sign up</A> to get an invitation to the upcoming ones. Our team of Product Management experts host these webinars to showcase the latest and greatest updates regarding all SAP Integration Suite capabilities. The webinars are hosted on the last Tuesday of every month and the next one is already scheduled for February 27th.</P><P>In case you have missed our last monthly webinar, don’t worry. Visit <A href="https://webinars.sap.com/sap-user-groups-k4u/en/ifgintegration" target="_blank" rel="noopener noreferrer">2024 Learning Sessions for SAP User Groups on SAP Integration Suite</A> for all recordings, presentations, and Q&amp;As.</P><P>Are you aware of the <A href="https://readiness-at-scale.enable-now.cloud.sap/pub/20230621_ras/index.html?show=book!BO_EC8330B09B97CDBE#SL_120BDFE08096029D" target="_blank" rel="noopener nofollow noreferrer">Release Navigator for SAP BTP</A>? It consolidates release information across SAP BTP products and services easing you the way to find product release related notes, blogposts, and webpages. For your convenience use the direct link to the <A href="https://readiness-at-scale.enable-now.cloud.sap/pub/20230621_ras/index.html?show=book!BO_EC8330B09B97CDBE#slide!SL_83EFB74698B85387" target="_blank" rel="noopener nofollow noreferrer">SAP Integration Suite section of the Release Navigator</A>.</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P> 2024-03-12T09:22:05.281000+01:00 https://community.sap.com/t5/technology-blogs-by-sap/api-composition-with-graph-customizing-your-business-data-graphs-with-model/ba-p/13639447 API Composition with Graph: customizing your Business Data Graphs with Model Extensions 2024-03-15T13:43:13.362000+01:00 florian_moritz https://community.sap.com/t5/user/viewprofilepage/user-id/748729 <P>Hello!</P><P>in this part of the tutorial series we will have a look at how to use Graph for composing APIs and customizing business data graphs with model extensions.&nbsp;<SPAN>We will walk through an example of how to create a custom entity with a custom association.</SPAN></P><P>For an overview of other parts of this series, check out the<SPAN>&nbsp;</SPAN><A href="https://community.sap.com/t5/technology-blogs-by-sap/information-map-end-to-end-tutorial-graph-in-sap-integration-suite/ba-p/13614448" target="_blank">Information Map.</A> </P><P>---</P><P>API Composition helps organizations to customize their API surface and combine multiple data sources into a single unified API. With Graph, as part of SAP Integration Suite, API administrators can create a single API using a customized connected graph data model either for their whole landscape or for specialized use cases.</P><P>API administrators can customize Business Data Graphs with the help of Model Extensions. These are packages that define several Custom Entities. All customizations in Graph are virtual: custom entity definitions are projections using mirrored entities as sources. Custom entities can have one or multiple source entities from possibly different data sources.</P><H2 id="toc-hId-989040029">Example Scenario</H2><P>In this blog we will walk through an example of composing and customizing an API from two separate services. An SAP S/4HANA Service and a service based on a custom CAP extension. Here is an overview of the example scenario:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="blog-example-scenario.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81313i146FE72CEEE3BD39/image-size/large?v=v2&amp;px=999" role="button" title="blog-example-scenario.png" alt="blog-example-scenario.png" /></span><BR /><EM>Example scenario diagram</EM></P><P><SPAN>We will compose a&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">demo.FrequentFlyer</FONT><SPAN>&nbsp;Custom Entity out of two sources: the&nbsp;</SPAN><FONT face="terminal,monaco" size="3" color="#800000">sap.s4.A_BusinessPartner</FONT><SPAN>&nbsp;from an SAP S/4HANA data source and a&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">my.custom.LoyaltyAccount</FONT><SPAN>&nbsp;entity from a custom CAP Extension on BTP. In addition, we will model an association from the custom entity&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">demo.FrequentFlyer</FONT><SPAN>&nbsp;to the&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">my.custom.LoyaltyStatus</FONT><SPAN>&nbsp;mirrored entity from the custom CAP Extension.</SPAN></P><H2 id="toc-hId-792526524">Example Setup</H2><P><SPAN>In this example we will be using the SAP S/4HANA sandbox provided on SAP Business Accelerator Hub and a simple CAP Extension service which we will be deploying in Cloud Foundry. The following steps will guide you through the required setup.</SPAN></P><H3 id="toc-hId-725095738"><SPAN>(1) Setting up Graph and SAP Integration Suite</SPAN></H3><P><SPAN>First we need a BTP subaccount with an SAP Integration Suite instance with Graph activated. Follow the steps outlined in this previous&nbsp;<A href="https://community.sap.com/t5/technology-blogs-by-sap/graph-intro-series-part-2-set-up-graph-in-sap-integration-suite/ba-p/13616727" target="_blank">blog post</A>&nbsp;if you have not done so already. As a result you have a running SAP Integration Suite instance with Graph.</SPAN></P><H3 id="toc-hId-528582233"><SPAN>(2) Setting up the SAP S/4HANA Sandbox Destination</SPAN></H3><P><SPAN>For demo data we will be using the SAP S/4HANA BusinessPartner sandbox service available on SAP Business Accelerator Hub. Create a destination named&nbsp;<FONT face="terminal,monaco" color="#800000">demo-s4-bupa</FONT>&nbsp;in your BTP subaccount for this service with the following URL:</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-bash"><code>https://sandbox.api.sap.com/s4hanacloud/sap/opu/odata/sap/API_BUSINESS_PARTNER</code></pre><P>&nbsp;</P><P><SPAN>You will also have to configure an API key for sandbox access as described in this previous&nbsp;<A href="https://community.sap.com/t5/technology-blogs-by-sap/graph-intro-series-part-2-set-up-graph-in-sap-integration-suite/ba-p/13616727" target="_blank">blog post</A>.</SPAN></P><H3 id="toc-hId-332068728"><SPAN>(3) Setting up the demo CAP Extension Service Destination</SPAN></H3><P>For the custom extension service, we will be deploying a small CAP-service in Cloud Foundry for demo purposes. We prepared this service<SPAN>&nbsp;</SPAN><A href="https://github.com/SAP-samples/graph-example-apps/tree/main/blog-series/API-composition/graph-demo-service" target="_blank" rel="nofollow noopener noreferrer">here</A>. Note that this example is only for demo puposes and would not fulfill requirements for any productive use cases.</P><P>To deploy the example CAP-service, make sure your BTP subaccount has the Cloud Foundry runtime enabled and a Cloud Foundry space exists (see also this<SPAN>&nbsp;</SPAN><A href="https://developers.sap.com/tutorials/btp-app-prepare-btp.html" target="_blank" rel="noopener noreferrer">tutorial</A>). Note that this minimal demo service only serves a few example records and does not require a database.</P><P>Clone the example service repository and copy the contents of<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">.cdsrc.json.template</FONT><SPAN>&nbsp;</SPAN>to a new file<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">.cdsrc.json</FONT><SPAN>&nbsp;</SPAN>and add a password for the configured Basic Authentication. In this demo we use Basic Authentication, to learn more about authenticating against Graph see<SPAN>&nbsp;</SPAN><A href="https://help.sap.com/docs/graph/graph/authentication" target="_blank" rel="noopener noreferrer">here</A>.</P><P>&nbsp;</P><pre class="lia-code-sample language-bash"><code>git clone https://github.com/SAP-samples/graph-example-apps.git cd graph-example-apps/blog-series/API-composition/graph-demo-service cp .cdsrc.json.template .cdsrc.json</code></pre><P>&nbsp;</P><P><SPAN>Make sure you have installed the prerequisites (Node.js, CAP, MBT) listed <A href="https://github.com/SAP-samples/graph-example-apps/tree/main/blog-series/API-composition/graph-demo-service#prerequisites" target="_blank" rel="noopener nofollow noreferrer">here</A>. Then install and build the project:</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-bash"><code>npm ci npm run build</code></pre><P>&nbsp;</P><P><SPAN>Next, deploy the service, for example using the Cloud Foundry CLI (see also <A href="https://github.com/SAP-samples/graph-example-apps/tree/main/blog-series/API-composition/graph-demo-service#prerequisites" target="_blank" rel="noopener nofollow noreferrer">here</A>)</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-bash"><code>cf login --sso cf deploy gen/mta.tar</code></pre><P>&nbsp;</P><P>After the deployment is finished you can access the example Loyalty service under<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">&lt;CF-application-route-URL&gt;/graph-demo/</FONT>.</P><P>Finally, we need to create a BTP destination for this service. In the BTP Cockpit under<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">Connectivity &gt; Destinations</FONT><SPAN>&nbsp;</SPAN>create a new Destination<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">demo-loyalty</FONT><SPAN>&nbsp;</SPAN>with the following URL:<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">&lt;CF-application-route-URL&gt;/graph-demo/</FONT><SPAN>&nbsp;</SPAN>(<FONT face="terminal,monaco" color="#800000">&lt;CF-application-route-URL&gt;</FONT><SPAN>&nbsp;</SPAN>depends on your Cloud Foundry deployment). Select<SPAN>&nbsp;"</SPAN>BasicAuthentication"<SPAN>&nbsp;</SPAN>for Authentication and add the user name and password you previously configured.</P><H3 id="toc-hId-135555223"><SPAN>(4) Preparing a Business Data Graph for the Example Scenario</SPAN></H3><P><SPAN>Now that we have created two destinations with our demo services, we can create a business data graph which we will extend with a model extension in the next section. In SAP Integration Suite open&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">Design &gt; Graph</FONT><SPAN>&nbsp;and create a new business data graph&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">demo-bdg</FONT><SPAN>. Select the two destinations&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">demo-s4-bupa</FONT><SPAN>&nbsp;and&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">demo-loyalty</FONT><SPAN>. Leave the model extension input empty for now, this is what we are about to create. Activate the BDG in the final step. By default, Graph will use the namespace&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">my.custom</FONT><SPAN>&nbsp;for destinations with services of unknown type, such as&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">demo-loyalty</FONT><SPAN>&nbsp;in this case. When the business data graph is active we can start to model an extension for it.</SPAN></P><H2 id="toc-hId--190041001">Custom Entity Modeling</H2><P>Graph allows to customize business data graphs with model extensions. A model extension is a package that contains one or more custom entity definitions. To customize a business data graph, we create a new model extension for it and then add it to the BDG configuration.</P><P>Start in SAP Integration Suite under<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">Design &gt; Graph</FONT><SPAN>&nbsp;</SPAN>and open the Model Extensions tab. Create a new model extension called<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">demo-extension</FONT><SPAN>&nbsp;</SPAN>and select the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">demo-bdg</FONT><SPAN>&nbsp;</SPAN>as modeling metadata BDG (this is only for retrieving metadata while modeling, the extension itself is independent).</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="1.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81321iB0E1AF8F4E1451C1/image-size/large?v=v2&amp;px=999" role="button" title="1.jpeg" alt="1.jpeg" /></span><BR /><EM>No Model Extensions exist</EM></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="2.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81322i76D164DF78EC3A34/image-size/large?v=v2&amp;px=999" role="button" title="2.jpeg" alt="2.jpeg" /></span><BR /><EM>Create a new Model Extension dialog</EM></P><H3 id="toc-hId--257471787">&nbsp;</H3><H3 id="toc-hId--453985292">Creating a Custom Entity</H3><P>We will now create our custom entity<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">demo.FrequentFlyer</FONT><SPAN>&nbsp;</SPAN>by composing it from two source entities. In the dialog select<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">sap.s4.A_BusinessPartner</FONT><SPAN>&nbsp;</SPAN>as the main source entity. This is the entity that defines the identity of data-objects and is the source of the primary key for our custom entity. Then add<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">my.custom.LoyaltyAccount</FONT><SPAN>&nbsp;</SPAN>as an additional source entity. Here, we need to define the join condition that defines how data objects from both entities are matched. For that we select which attributes from both entities are matching. When the complete primary key of the additional source attribute is matched, Graph infers that there exists a cardinality-relationship of 0 or 1 between the data objects of both entities, as is the case in our example.</P><P>In the other case where only a partial primary key is matched, a many-cardinality will be assumed. In that case, for each data object of the main source entity there could be any number of additional source data objects. Graph will treat that case as a composition, where an entity contains an array of sub-entities.</P><P>With the source entities defined, we continue by selecting which attributes of each source we want to project into our custom entity<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">demo.FrequentFlyer</FONT>. Here, we select the primary key attribute<SPAN>&nbsp;<FONT face="terminal,monaco" color="#800000">BusinessPartner</FONT>&nbsp;</SPAN>of our main source entity&nbsp;in addition to other attributes from both sources (see below). Graph will suggest new names according to the Graph attribute naming<SPAN>&nbsp;</SPAN><A href="https://help.sap.com/docs/graph/graph/attributes" target="_blank" rel="noopener noreferrer">best practices</A>. Having selected some attributes we finalize the dialog via<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">Create</FONT>. We can then open our newly created custom entity and continue modeling the details.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="3.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81326i7ED76BD47AB3DC38/image-size/large?v=v2&amp;px=999" role="button" title="3.jpeg" alt="3.jpeg" /></span><BR /><EM>Empty Model Extension</EM></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="4.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81328i64F7DB6DAA745E02/image-size/large?v=v2&amp;px=999" role="button" title="4.jpeg" alt="4.jpeg" /></span><BR /><EM>Custom Entity creation dialog</EM></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="6.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81331i56029FF975BCCF54/image-size/large?v=v2&amp;px=999" role="button" title="6.jpeg" alt="6.jpeg" /></span><BR /><EM>Source entities definition step</EM></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="5.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81333i5132DD80F26D429A/image-size/large?v=v2&amp;px=999" role="button" title="5.jpeg" alt="5.jpeg" /></span><BR /><EM>Additional source entity definition</EM></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="7.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81336i09CADC6F825A8457/image-size/large?v=v2&amp;px=999" role="button" title="7.jpeg" alt="7.jpeg" /></span><BR /><EM>Main source attribute selection</EM></P><P><EM><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="8.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81338iC20DFE3F0F7254C4/image-size/large?v=v2&amp;px=999" role="button" title="8.jpeg" alt="8.jpeg" /></span><BR />Additional source attribute selection</EM></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="9.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81341i0553B66CD2E4B3B9/image-size/large?v=v2&amp;px=999" role="button" title="9.jpeg" alt="9.jpeg" /></span><BR /><EM>Model Extension with the newly created Custom Entity</EM></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="10.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81344iE07990B6C7871877/image-size/large?v=v2&amp;px=999" role="button" title="10.jpeg" alt="10.jpeg" /></span><BR /><EM>Custom Entity attributes</EM></P><P>&nbsp;</P><H3 id="toc-hId--650498797">Applying Transform Functions</H3><P>When defining custom entities, graph allows to apply<SPAN>&nbsp;</SPAN><A href="https://help.sap.com/docs/graph/graph/transform-functions?locale=en-US" target="_blank" rel="noopener noreferrer">transform functions</A><SPAN>&nbsp;</SPAN>as part of the definition. When adding attributes from a source entity to the custom entity this is plainly called a<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">rename</FONT><SPAN>&nbsp;</SPAN>transform (as was done in the entity creation dialog).</P><P>In our example, we want to change our data model and invert the boolean source attribute<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">isMarkedForArchiving</FONT>, which denotes whether an object was archived, and instead call the inverse<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">isActive</FONT>. For that we use the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">negation</FONT><SPAN>&nbsp;</SPAN>transform. We select the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">isMarkedForArchiving</FONT><SPAN>&nbsp;</SPAN>attribute and change the transform in the right-side panel to<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">negation</FONT>, rename the attribute and apply our changes.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="11.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81347iFC1050D805CBE21A/image-size/large?v=v2&amp;px=999" role="button" title="11.jpeg" alt="11.jpeg" /></span><BR /><EM>Details of the applied negation transform</EM></P><P>&nbsp;</P><H3 id="toc-hId--922243671">Adding a new Association</H3><P>Graph allows to customize the graph structure of a business data graph with the help of custom associations in custom entities. For example, foreign-key relationships that are present in mirrored entities, can be converted into semantic associations between custom entities.</P><P>In our example, the additional source entity<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">my.custom.LoyaltyAccount</FONT><SPAN>&nbsp;</SPAN>has an atttribute<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">loyaltyProgramStatusId</FONT><SPAN>&nbsp;</SPAN>that references<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">my.custom.LoyaltyStatus</FONT><SPAN>&nbsp;</SPAN>data objects by their ID. We turn this foreign-key relationship into an association as follows: in the dialog under<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">Add &gt; Association</FONT><SPAN>&nbsp;</SPAN>select the type of association. Here, it is a to-one association, as each LoyaltyAccount references only one LoyaltyStatus via ID.</P><P>Next, select the target of the association:<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">my.custom.LoyaltyStatus</FONT>. Graph will suggest a name according to the Graph modeling best practices.</P><P>Then define how these two entities are related by matching attributes from the source entity (foreign key) to the primary key attributes of the target entity. In our example we only map the LoyaltyAccount attribute<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">loyaltyProgramStatusId</FONT><SPAN>&nbsp;</SPAN>to the single LoyaltyStatus key attribute<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">statusId</FONT><SPAN>&nbsp;</SPAN>and then add the association to the custom entity.</P><P>This completes our example. Now we can apply the changes to our custom entity and save the extension.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="12.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81354i0FE410AA74083300/image-size/large?v=v2&amp;px=999" role="button" title="12.jpeg" alt="12.jpeg" /></span><EM>Add Association dialog</EM></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="13.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81355iCE955A88D51F6B45/image-size/large?v=v2&amp;px=999" role="button" title="13.jpeg" alt="13.jpeg" /></span><BR /><EM>Complete demo.FrequentFlyer Custom Entity definition</EM></P><H2 id="toc-hId--825354169">&nbsp;</H2><H2 id="toc-hId--1021867674">Applying the Model Extension to the Business Data Graph</H2><P><SPAN>Now that we have created a model extension for our example scenario with the <FONT face="terminal,monaco" color="#800000">demo.FrequentFlyer</FONT>&nbsp;</SPAN><SPAN>custom entity we want to see it in action. For that we will apply the model extension to a BDG.</SPAN></P><H3 id="toc-hId--1511784186">Creating new BDGs with Model Extensions</H3><P>With an existing model extension, we can simply create a new BDG and select the extension during the BDG-creation dialog. Graph will then generate a BDG configuration with locating policy rules for all custom entities.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="14.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81356iD3285069E147A252/image-size/large?v=v2&amp;px=999" role="button" title="14.jpeg" alt="14.jpeg" /></span><BR /><EM>Selecting an existing Model Extension during BDG creation</EM></P><H3 id="toc-hId--1708297691">Adding Model Extensions to existing BDGs</H3><P>Alternatively, we can also manually add a model extension to an existing BDG. Here we need to add the name of the extension to the top-level <FONT face="terminal,monaco" color="#800000">extensions</FONT> array (see below), and add locating policy rules for all custom entities.</P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>"extensions": [ "demo-extension" ],</code></pre><P>&nbsp;</P><P><EM>BDG configuration extensions snippet</EM></P><P>In our example we add a single custom entity that is based on two source entities which requires two entries in the BDG locating policy rules, one for each source entity (see also<SPAN>&nbsp;</SPAN><A href="https://help.sap.com/docs/graph/graph/business-data-graph-configuration-file?version=PROD#locating-policy" target="_blank" rel="noopener noreferrer">here</A>). Add the following snippet to the BDG configuration under <FONT face="terminal,monaco" color="#800000">locatingPolicy.rules</FONT> (adapt the name of the leading data sources to match the ones in your BDG).</P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "name": "demo.FrequentFlyer", "leading": "s4", "local": [] }, { "name": "demo.FrequentFlyer", "leading": "my.custom", "local": [], "sourceEntity": "my.custom.LoyaltyAccount" }</code></pre><P>&nbsp;</P><P><EM>BDG configuration <FONT face="terminal,monaco" color="#800000">locatingPolicy.rules</FONT> snippet</EM></P><P>&nbsp;</P><DIV class=""><SPAN>Finally, we activate the BDG with the included model extension to try it out. Once the BDG was updated we can open the Graph Navigator in SAP API Business Hub Enterprise (see also this&nbsp;</SPAN><A href="https://community.sap.com/t5/technology-blogs-by-sap/graph-intro-series-part-3-construct-and-explore-a-business-data-graph/ba-p/13616707" target="_blank">blog</A><SPAN>). There we can see that our updated&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">demo-bdg</FONT><SPAN>&nbsp;now has a&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">demo.FrequentFlyer</FONT><SPAN>&nbsp;entity with the schema we previously modeled. In the "<EM>Try Out"</EM>&nbsp;we can also see that we can follow the new&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">_loyaltyStatus</FONT><SPAN>&nbsp;association via&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$expand</FONT><SPAN><SPAN>&nbsp;or semantic navigation.</SPAN></SPAN></DIV><DIV class=""><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="navigator-schema.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81377i44F9BB50F6E17494/image-size/large?v=v2&amp;px=999" role="button" title="navigator-schema.jpeg" alt="navigator-schema.jpeg" /></span><BR /><EM>Custom Entity schema in Graph Navigator</EM></DIV><DIV class="">&nbsp;</DIV><DIV class=""><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="navigator-tryout.jpeg" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/81376iD99BE35A6600FCB9/image-size/large?v=v2&amp;px=999" role="button" title="navigator-tryout.jpeg" alt="navigator-tryout.jpeg" /></span><BR /><P><EM>Custom Entity Try Out in Graph Navigator</EM></P><H2 id="toc-hId--1611408189">&nbsp;</H2><H2 id="toc-hId--1807921694">Summary</H2><P>This small blog example illustrates how Graph can be used to compose APIs and customize the API surface with the help of a business data graph.</P><P>We used Graph to compose two different service APIs into a single connected business data graph: an SAP S/4HANA service and a custom CAP-extension service. We created a model extension containing a custom entity <FONT face="terminal,monaco" color="#800000">demo.FrequentFlyer</FONT> with&nbsp;a custom association to another entity and a negation transform function.</P><P>To learn more about the full Graph modeling capabilities find the documentation<SPAN>&nbsp;</SPAN><A href="https://help.sap.com/docs/graph/graph/model" target="_blank" rel="noopener noreferrer">here</A><SPAN>&nbsp;</SPAN>with more infomation on modeling topics such as all supported transform functions, creating compositions and adding to-many associations to your model.</P><P>&nbsp;</P><H3 id="toc-hId-1997129090">Reference Materials</H3><P>Find the full BDG configuration JSON and custom entity definition JSON files used in the example demo below.<BR /><STRONG>Custom Entity definition JSON file:</STRONG></P></DIV><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "entity": "demo.FrequentFlyer", "version": "1.0.0", "sourceEntities": [ { "name": "sap.s4.A_BusinessPartner" }, { "name": "my.custom.LoyaltyAccount", "join": [["BusinessPartner", "userId"]] } ], "attributes": [ { "name": "id", "source": ["BusinessPartner"], "key": true }, { "name": "businessPartnerFullName", "source": ["BusinessPartnerFullName"] }, { "name": "loyaltyProgramName", "source": ["loyaltyProgramName"], "sourceEntity": "my.custom.LoyaltyAccount" }, { "name": "loyaltyPoints", "source": ["loyaltyPoints"], "sourceEntity": "my.custom.LoyaltyAccount" }, { "name": "isActive", "source": ["isMarkedForArchiving"], "sourceEntity": "my.custom.LoyaltyAccount", "transform": "negation", "type": "Boolean" }, { "name": "_loyaltyStatus", "type": "Association", "associationTarget": "my.custom.LoyaltyStatus" }, { "name": "_loyaltyStatus.statusId", "source": ["loyaltyProgramStatusId"], "sourceEntity": "my.custom.LoyaltyAccount" } ], "annotations": { "description": "", "readonly": false } }</code></pre><P>&nbsp;</P><P><STRONG>BDG configuration JSON:</STRONG></P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "businessDataGraphIdentifier": "demo-bdg", "graphModelVersion": "^v3", "schemaVersion": "1.2.1", "dataSources": [ { "name": "my.custom", "services": [ { "destinationName": "demo-loyalty", "path": "" } ], "namespace": "my.custom" }, { "name": "s4", "services": [ { "destinationName": "demo-s4-bupa", "path": "" } ], "namespace": null } ], "locatingPolicy": { "cues": [], "rules": [ { "name": "sap.s4.*", "leading": "s4", "local": [], "cues": [], "sourceEntity": null }, { "name": "sap.graph.*", "leading": "s4", "local": [], "cues": [], "sourceEntity": null }, { "name": "my.custom.*", "leading": "my.custom", "local": [], "cues": [], "sourceEntity": null }, { "name": "demo.FrequentFlyer", "leading": "s4", "local": [], "cues": [], "sourceEntity": null }, { "name": "demo.FrequentFlyer", "leading": "my.custom", "local": [], "sourceEntity": "my.custom.LoyaltyAccount", "cues": [] } ], "description": "", "keyMapping": [] }, "effectiveGraphModelVersion": "3.1.0", "description": "", "exclude": [], "extensions": ["demo-extension"] }​</code></pre><P>&nbsp;</P><P>---</P><P><STRONG>Florian Moritz</STRONG></P> 2024-03-15T13:43:13.362000+01:00 https://community.sap.com/t5/technology-blogs-by-sap/graph-intro-series-part-9-use-graph-with-graphql/ba-p/13623717 Graph intro series, part 9: Use Graph With GraphQL 2024-03-17T04:30:00.031000+01:00 AlexHoffert https://community.sap.com/t5/user/viewprofilepage/user-id/707350 <H2 id="toc-hId-987940552">GraphQL</H2><P><SPAN><A href="https://graphql.org/" target="_blank" rel="noopener nofollow noreferrer">GraphQL</A> is a query language for APIs that provides a type system to describe the data model in a structured way. It provides a strongly typed schema to describe the data model of an API in a structured way. Additionally, clients of an API use the query language to describe the data they want to request. GraphQL is similar to OData because they both provide a structured, typed schema for APIs and also enable clients to write powerful queries to request exactly the data they need using a single request.</SPAN></P><P><SPAN>The GraphQL adapter builds on the same metadata as the OData adapter.</SPAN></P><H2 id="toc-hId-791427047">Tutorial Setup</H2><P><SPAN>To keep things simple, we will be using the Graph sandbox endpoint. All you need to use this endpoint is your favorite GraphQL tool, for example the Altair GraphQL client, and your API key from SAP API Hub. To retrieve your API key, log into&nbsp;</SPAN><A href="https://api.sap.com/" target="_blank" rel="noopener noreferrer">SAP API Business Hub</A><SPAN>, go to&nbsp;</SPAN><A href="https://api.sap.com/settings" target="_blank" rel="noopener noreferrer">settings</A><SPAN>&nbsp;and copy your API key from the&nbsp;</SPAN><STRONG><SPAN>Show API Key</SPAN></STRONG><SPAN>&nbsp;button.</SPAN></P><P><SPAN>To make requests against the Graph sandbox, add your API key as an HTTP header in your requests:&nbsp;apiKey: &lt;your API key&gt;. Then you can use the Graph sandbox through the following endpoint:</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-markup"><code>https://sandbox.api.sap.com/sapgraph/graphql</code></pre><P>&nbsp;</P><H4 id="toc-hId-853078980"><SPAN>Tutorial Specific Settings</SPAN></H4><P><SPAN>Usually, GraphQL requests are done using&nbsp;</SPAN><FONT color="#008080"><STRONG>POST </STRONG></FONT><SPAN>requests. But, the sandbox is limited to </SPAN><FONT color="#008080"><STRONG>GET</STRONG></FONT><SPAN> requests, so we need to do </SPAN><FONT color="#008080"><STRONG>GET</STRONG></FONT><SPAN> requests for this tutorial. For most GraphQL clients this is just a setting and we are not creating too large request. A productive Graph instance is able to receive <FONT color="#008080"><STRONG>POST</STRONG></FONT> requests.</SPAN></P><P>The API key is just used for the purposes of this sandbox endpoint and not relevant in the context of requests to productive Graph instances.</P><P>Also note that the URL of the Graph sandbox differs from the a productive URL of Graph.</P><H2 id="toc-hId-398400037"><SPAN>Exploring the Schema</SPAN></H2><P>Every GraphQL service defines a <A href="https://graphql.org/learn/schema/" target="_self" rel="nofollow noopener noreferrer">schema</A> that completely describes the set of types you can use for querying that service. GraphQL allows asking&nbsp;<SPAN>about what queries it supports using the <A href="https://graphql.org/learn/introspection/" target="_self" rel="nofollow noopener noreferrer">introspection system</A>.&nbsp;</SPAN></P><P><SPAN>Most GraphQL clients automatically load and scan the complete schema automatically, so you might not need to do that on your own and use the client to explore the schema.</SPAN></P><P><SPAN>To see what types are available, you can query the <FONT color="#008080"><STRONG>__schema</STRONG></FONT> field:</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-markup"><code>{ __schema { types { name } } }</code></pre><P>&nbsp;</P><P>This will return all service specific and build-in types of the service:</P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "data": { "__schema": { "types": [ { "name": "Query" }, { "name": "sap_c4c" }, { "name": "sap_c4c_BusinessAttributeCollection_connection" }, { "name": "sap_c4c_BusinessAttributeCollection" } ... ] } } }</code></pre><P>&nbsp;</P><P>To get more information for a specific type, you can either extend the query above or do a separate query for the <FONT color="#008080"><STRONG>__type</STRONG></FONT> field. If you introspect the <FONT color="#008080"><STRONG>Query </STRONG></FONT>with</P><P>&nbsp;</P><pre class="lia-code-sample language-markup"><code>{ __type(name: "Query"){ name fields { name } } }</code></pre><P>&nbsp;</P><P>you get all namespaces. These include Graph's build-in namespaces as well as user-defined custom namespaces for custom entities.</P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "data": { "__type": { "name": "Query", "fields": [ { "name": "sap_c4c" }, { "name": "sap_graph" }, { "name": "sap_hcm" }, { "name": "sap_s4 "} ] } } }</code></pre><P>&nbsp;</P><P>You can use a similar query to get the list of entities in a namespace, by using the namespace instead <FONT color="#008080"><STRONG>"Query"</STRONG></FONT> as the name.</P><P>To get more information in a single request, you can extend the query, for example to get all fields of <FONT color="#008080"><STRONG>sap_graph_SalesQuote</STRONG></FONT>&nbsp;with their name and kind, you simply query this:</P><P>&nbsp;</P><pre class="lia-code-sample language-markup"><code>{ __type(name: "sap_graph_SalesQuote"){ name fields { name type { name kind } } } }</code></pre><P>&nbsp;</P><P>returning all available properties of the&nbsp;<FONT color="#008080"><STRONG>sap_graph_SalesQuote</STRONG></FONT>:</P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "data": { "__type": { "name": "sap_graph_SalesQuote", "fields": [ {"name": "id", "type": {"name": "String", "kind": "SCALAR"}}, {"name": "createdAt", "type": {"name": "DateTime", "kind": "SCALAR"}}, {"name": "changedAt", "type": {"name": "DateTime", "kind": "SCALAR"}}, {"name": "displayId", "type": {"name": "String", "kind": "SCALAR"}}, {"name": "netAmount", "type": {"name": "Decimal", "kind": "SCALAR"}}, {"name": "quoteType", "type": {"name": "String", "kind": "SCALAR"}}, {"name": "soldToParty", "type": {"name": "String", "kind": "SCALAR"}}, {"name": "_soldToParty", "type": {"name": "sap_graph_SalesDocumentReason", "kind": "OBJECT"}}, {"name": "_soldToParty_id", "type": {"name": "String", "kind": "SCALAR"}}, {"name": "items", "type": {"name": "sap_graph_SalesQuote_items_connection", "kind": "OBJECT"}}, ... ] } } }</code></pre><P>&nbsp;</P><P><SPAN>We can see that a&nbsp;</SPAN><FONT color="#008080"><STRONG><SPAN>SalesQuote</SPAN></STRONG></FONT><SPAN>&nbsp;has several properties of different types, such as&nbsp;</SPAN><FONT color="#008080"><STRONG><SPAN>String</SPAN></STRONG></FONT><SPAN>&nbsp;or&nbsp;</SPAN><FONT color="#008080"><STRONG><SPAN>Decimal</SPAN></STRONG></FONT><SPAN>, but also more complex structured types like the&nbsp;</SPAN><FONT color="#008080"><STRONG><SPAN>items</SPAN></STRONG></FONT><SPAN>&nbsp;property, which is a collection of several <FONT color="#008080"><STRONG>sap_graph_SalesQuote_items</STRONG></FONT></SPAN><SPAN>, that are also defined in the same data model. The <FONT color="#008080"><STRONG>_connection</STRONG></FONT> types allow for retrieving data of entities of a to-many relation.</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "data": { "__type": { "name": "sap_graph_SalesQuote_items_connection", "fields": [ {"name": "nodes", "type": {"name": null, "kind": "LIST", "ofType": {"name": "sap_graph_SalesQuote_items"}}}, {"name": "totalCount", "type": {"name": "Int", "kind": "SCALAR", "ofType": null}} ] } } }</code></pre><P>&nbsp;</P><H2 id="toc-hId-201886532"><SPAN>Simple Example</SPAN></H2><P><SPAN>Let us look at an example. We want to get a SalesQuote. For that, we create the following GraphQL request:</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-markup"><code>{ sap_graph { SalesQuote (top: 1){ nodes { id displayId netAmount } } } }</code></pre><P>&nbsp;</P><P>In GraphQL, you always specify exactly what fields you would like to receive. In the example request above we selected the&nbsp;<FONT color="#008080"><STRONG>id</STRONG></FONT>, <FONT color="#008080"><STRONG>displayId</STRONG></FONT> and the <FONT color="#008080"><STRONG>netAmount</STRONG></FONT>&nbsp;of the <FONT color="#008080"><STRONG>SalesQuote.&nbsp;</STRONG><FONT color="#000000">To make the query fast and have an easy to read result, we have added <FONT color="#008080"><STRONG>(top: 1)</STRONG></FONT> to get only one SalesQuote.</FONT></FONT></P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "data": { "sap_graph": { "SalesQuote": { "nodes": [ { "id": "c4c~1", "displayId": "1", "netAmount": "890" } ] } } } }</code></pre><P>&nbsp;</P><H2 id="toc-hId-5373027">Example With Nesting</H2><P>We now want to get the items and the soldToParty of that SalesQuote as well, so we simply add these attributes to the query with the fields we would like to see.</P><P>Note that the attributes of the items attribute are encapsulated with <FONT color="#008080"><STRONG>nodes</STRONG></FONT> like it is done with the attributes of the SalesQuote as well. This has to be done for all list types. <FONT color="#008080"><STRONG>_soldToParty</STRONG></FONT> is a to-one association, so here the attributes are directly. The reason for this extra level is so that you can get the total amount of elements next to the actual elements of the list like here for the SalesQuote:</P><P>&nbsp;</P><pre class="lia-code-sample language-markup"><code>{ sap_graph { SalesQuote (top: 1){ totalCount nodes { id displayId netAmount _soldToParty { id name } items { nodes { itemId itemText product quantity } } } } } }</code></pre><P>&nbsp;</P><P>This will result in the items of the <FONT color="#008080"><STRONG>SalesQuote</STRONG></FONT> and the associated <FONT color="#008080"><STRONG>soldToParty</STRONG></FONT> being returned. The total count of found <FONT color="#008080"><STRONG>SalesQuotes</STRONG></FONT> is now available as well:</P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "data": { "sap_graph": { "SalesQuote": { "totalCount": 135, "nodes": [ { "id": "c4c~1", "displayId": "1", "netAmount": "890", "_soldToParty": { "id": "c4c~10014", "name": "System Tec" }, "items": { "nodes": [ { "itemId": "10", "itemText": "Green Emission Calculator", "product": "P300100", "quantity": "1" } ] } } ] } } } }</code></pre><P>&nbsp;</P><H2 id="toc-hId--191140478">Working with collections: filtering, ordering and pagination</H2><P><SPAN>When working with collections of entities, we typically want to filter the entities by some criteria or arrange them in a specific order. In Graph's GraphQL schema this is supported via the&nbsp;</SPAN><FONT color="#008080"><STRONG><SPAN>filter</SPAN></STRONG></FONT><SPAN>&nbsp;and&nbsp;</SPAN><FONT color="#008080"><STRONG><SPAN>order</SPAN></STRONG></FONT><SPAN>&nbsp;arguments.&nbsp;</SPAN></P><P><SPAN>Let us continue with our example above. Say, we want to retrieve all&nbsp;<FONT color="#008080"><STRONG>SalesQuotes</STRONG></FONT>&nbsp;with a value greater than 100 U.S. Dollars.&nbsp;</SPAN><SPAN>The value condition can be formulated with the filter rule&nbsp;<FONT color="#008080"><STRONG>netAmount: {ge: 100}</STRONG></FONT>. For the currency condition we need to compare it with a string for equality: <FONT color="#008080"><STRONG>netAmountCurrency: {eq: "USD"}</STRONG></FONT>. Filter rules that are in one filter object are combined with&nbsp;logical conjunction (and). If you want to combine rules with logical disjunction (or), you would pass multiple filters as a list in the <FONT color="#008080"><STRONG>filter</STRONG></FONT> argument.</SPAN></P><P><SPAN>In addition, we define an ascending ordering on the&nbsp;<STRONG><FONT color="#008080">netAmount</FONT>&nbsp;</STRONG>property: <FONT color="#008080"><STRONG>orderBy: {netAmount: asc}</STRONG></FONT>.<BR /></SPAN></P><P><SPAN>With&nbsp;</SPAN><FONT color="#008080"><STRONG><SPAN>top</SPAN></STRONG></FONT><SPAN>&nbsp;and&nbsp;</SPAN><FONT color="#008080"><STRONG><SPAN>skip</SPAN></STRONG></FONT><SPAN>&nbsp;we can additionally define a sliding window over the result to implement pagination. <FONT color="#008080"><STRONG>top</STRONG></FONT>&nbsp;specifies how many result entities should be returned: the page size. How many result entities should be skipped from the beginning of the ordering is defined with the <FONT color="#008080"><STRONG>skip</STRONG></FONT> argument.</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-markup"><code>{ sap_graph { SalesQuote ( top: 5, skip: 5, orderBy: {netAmount: asc}, filter: { netAmount: {ge: 100}, netAmountCurrency: {eq: "USD"} } ){ totalCount nodes { id netAmount netAmountCurrency } } } }</code></pre><P>&nbsp;</P><H2 id="toc-hId--387653983">Summary</H2><P><SPAN>In this tutorial we had a look at using Graph with GraphQL. We covered all the features that you as a developer working with Graph need to know, like how to:</SPAN></P><UL><LI>inspect the schema and structure of the business data graph</LI><LI>formulate complex queries</LI><LI>work with collections</LI></UL><P><SPAN>GraphQL itself offers much more than what we showed in this tutorial. You can read more about it in the&nbsp;</SPAN><A href="https://graphql.org/learn/" target="_blank" rel="nofollow noopener noreferrer">the GraphQL documentation</A>&nbsp;and&nbsp;<A href="https://help.sap.com/docs/graph/graph/graphql" target="_blank" rel="noopener noreferrer">the Graph documentation</A>&nbsp;<SPAN>.</SPAN><BR /><BR /><SPAN>You as a developer now have a second data protocol option you can use with Graph. The structure of all entities in the business data graph is exactly the same as if you access Graph with the OData protocol. You have one API to retrieve data in one unified format, no matter the source system.</SPAN></P><P><SPAN>________________________________________________________________<BR /><STRONG>Alexander Hoffert, Senior Developer – Graph</STRONG></SPAN></P><P>Visit&nbsp;<A href="https://pages.community.sap.com/topics/graph" target="_self" rel="noreferrer noopener">Graph</A>&nbsp;on the SAP Community</P> 2024-03-17T04:30:00.031000+01:00 https://community.sap.com/t5/technology-blogs-by-sap/graph-intro-series-part-8-use-graph-with-odata-v4/ba-p/13641190 Graph intro series, part 8: Use Graph With OData v4 2024-03-19T14:21:24.058000+01:00 florian_moritz https://community.sap.com/t5/user/viewprofilepage/user-id/748729 <P><EM>What you will learn: use OData v4 to fetch data and explore the structure of the connected data model exposed by Graph.</EM></P><P>Hello!</P><P>In this part of the tutorial on Graph we will focus on the OData protocol that Graph exposes and how to explore the structure of the data model of a business data graph. OData is one of the two data protocols supported by Graph - next to <A href="https://community.sap.com/t5/technology-blogs-by-sap/graph-intro-series-part-9-use-graph-with-graphql/ba-p/13623717" target="_self">GraphQL</A>.</P><P><SPAN>For an overview of other parts of this series, check out the</SPAN><SPAN>&nbsp;</SPAN><A href="https://community.sap.com/t5/technology-blogs-by-sap/information-map-end-to-end-tutorial-graph-in-sap-integration-suite/ba-p/13614448" target="_blank">Information Map.</A><SPAN> </SPAN></P><P>Graph is built on open standards and technologies. Clients can communicate with Graph using the<SPAN>&nbsp;</SPAN><A href="http://docs.oasis-open.org/odata/odata/v4.01/os/part1-protocol/odata-v4.01-os-part1-protocol.html" target="_blank" rel="nofollow noopener noreferrer">Open Data v4 Protocol</A><SPAN>&nbsp;</SPAN>(OData). This is a<SPAN>&nbsp;</SPAN><A href="https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=odata" target="_blank" rel="nofollow noopener noreferrer">standardized RESTful HTTP protocol</A><SPAN>&nbsp;</SPAN>with defined semantics that help promote interoperability between services.</P><P>OData is centered around resources (data entities), which are identified by URLs. In Graph, there are for example the Customer, Product, or SalesQuote entities. The structure of these entities is defined in an Entity Data Model (EDM) which can be inspected by clients. OData provides many operations to filter or search in entity collections, to navigate between associated entities and to adapt the response shape.</P><P>We will now look at examples on how to formulate OData requests for Graph.</P><H2 id="toc-hId-989722487">&nbsp;</H2><H2 id="toc-hId-793208982">Tutorial Setup</H2><P>To keep things simple, we will be using the Graph sandbox business data graph (BDG). All you need to use it is your favorite HTTP tool, for example Postman, and your API key from<SPAN>&nbsp;</SPAN><A href="https://api.sap.com/" target="_blank" rel="noopener noreferrer">SAP Business Accelerator Hub</A>. To retrieve your API key, log into SAP Business Accelerator Hub, go to<SPAN>&nbsp;</SPAN><A href="https://api.sap.com/settings" target="_blank" rel="noopener noreferrer">settings</A><SPAN>&nbsp;</SPAN>and copy your API key from the Show API Key button.</P><P>To make requests against the Graph sandbox BDG, add your API key as an HTTP header in your requests:<BR /><FONT face="terminal,monaco" color="#800000">apiKey: &lt;your API key&gt;</FONT></P><P>Then you can use the Graph sandbox BDG through the following endpoint:</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>https://sandbox.api.sap.com/sapgraph/</code></pre><P>&nbsp;</P><DIV class=""><BLOCKQUOTE><P>Note: The API key is just used for the purposes of this sandbox endpoint and not relevant in the context of OData requests or productive Graph instances.</P></BLOCKQUOTE><H2 id="toc-hId-596695477">Exploring the OData data model</H2><P>OData defines an Entity Data Model that describes the structure of all known entities. This helps developers and clients alike to reason about the available entities and their structure. The data model and further metadata can be inspected through a special<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$metadata</FONT><SPAN>&nbsp;</SPAN>resource. Graph makes metadata available for each namespace, such as<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">sap.graph</FONT><SPAN>&nbsp;</SPAN>for the unified Graph data model.</P><P>To retrieve the metadata of the unified data model in Graph, make the following request, which will return an EDMX specification (an XML dialect for describing OData Entity Data Models).</P></DIV><P>&nbsp;</P><pre class="lia-code-sample language-yaml"><code>https://sandbox.api.sap.com/sapgraph/sap.graph/$metadata</code></pre><P>&nbsp;</P><P><SPAN>In the response, we can inspect the structure of all the entities (and sub-entities) that are described as EntityType entries as well as other metadata. Let's have a closer look at the definition of the SalesQuote entity type in this extract from the sales domain metadata:</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-markup"><code>&lt;EntityType Name="SalesQuote"&gt; &lt;Key&gt; &lt;PropertyRef Name="id"/&gt; &lt;/Key&gt; &lt;Property Name="id" Type="Edm.String" MaxLength="82" Nullable="false"/&gt; &lt;Property Name="displayId" Type="Edm.String"/&gt; &lt;Property Name="netAmount" Type="Edm.Decimal" Scale="6" Precision="22"/&gt; &lt;Property Name="pricingDate" Type="Edm.DateTimeOffset"/&gt; &lt;Property Name="netAmountCurrency" Type="Edm.String" MaxLength="5"/&gt; &lt;NavigationProperty Name="_netAmountCurrency" Type="sap.graph.Currency"/&gt; &lt;NavigationProperty Name="items" Type="Collection(sap.graph.SalesQuote_items)" Partner="up_" ContainsTarget="true"/&gt; &lt;Property Name="soldToParty" Type="Edm.String" MaxLength="10"/&gt; &lt;NavigationProperty Name="_soldToParty" Type="sap.graph.Customer"/&gt; &lt;NavigationProperty Name="_cxsales" Type="sap.cxsales.SalesQuoteCollection"/&gt; ... &lt;/EntityType&gt;</code></pre><P>&nbsp;</P><P>We can see that a SalesQuote has several properties of different types, such as String or Decimal, but also more complex structured types like the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">items</FONT><SPAN>&nbsp;</SPAN>property, which is a collection of several<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">sap.graph.SalesQuote_items</FONT>, that are also defined in the same data model. Furthermore, we see that the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">id</FONT><SPAN>&nbsp;</SPAN>property is referenced as key for this entity type. Navigation Properties allow for navigation to a related entity. The<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">items</FONT><SPAN>&nbsp;</SPAN>property is a navigation property because the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">sap.graph.SalesQuote_items</FONT><SPAN>&nbsp;</SPAN>is modeled as a separate entity type in the metadata.</P><P>Let's look at an example. Add the following query path to the sandbox endpoint to make the request. This will retrieve one SalesQuote entity (here we add<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$top=1</FONT><SPAN>&nbsp;</SPAN>to limit the result set to one entity):</P><P>&nbsp;</P><pre class="lia-code-sample language-yaml"><code>/sap.graph/SalesQuote?$top=1</code></pre><P>&nbsp;</P><P>From inspecting the metadata, we have learned that SalesQuotes have items, however when comparing with the response from the example, no items are included in the response.</P><P>The reason for this is that OData has a mechanism for the client to control which navigation properties are included as part of the response. This is called expanding a property. By default, Graph returns responses non-expanded if not specified by the client. In addition to expanding the response, OData also allows for restricting it to requested values only. We will have a look at these mechanisms next.</P><DIV class=""><H2 id="toc-hId-400181972">Expanding and restricting the response</H2><P>OData allows clients to adapt the response format in two ways. Clients can restrict the response to a set of specified properties via<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$select</FONT>. And they can expand the response by including referenced entities inline as part of the response via<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$expand</FONT>.</P><P>If we only require the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">netAmount</FONT><SPAN>&nbsp;</SPAN>of a SalesQuote, we can restrict the response by adding it to the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$select</FONT><SPAN>&nbsp;</SPAN>query parameter:</P></DIV><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>/sap.graph/SalesQuote?$top=1&amp;$select=netAmount</code></pre><P>&nbsp;</P><P>This will return only the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">netAmount</FONT><SPAN>&nbsp;</SPAN>property along with the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">id</FONT>, as it is the key attribute and therefore always included.</P><P>If we also require the items of a SalesQuote, we need to expand the response (as it is a navigation property) by adding it to the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$expand</FONT><SPAN>&nbsp;</SPAN>query parameter:</P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>/sap.graph/SalesQuote?$top=1&amp;$select=netAmount&amp;$expand=items</code></pre><P>&nbsp;</P><P>This will result in the items array being returned as part of the SalesQuote response as illustrated here:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="expand-items-1.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83064i8DCDA62DE7F4CBC2/image-size/large?v=v2&amp;px=999" role="button" title="expand-items-1.png" alt="expand-items-1.png" /></span></P><P>If we have a look at a response snippet, this is what is being returned:</P><DIV class="">&nbsp;</DIV><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "@odata.context": "$metadata#SalesQuote(netAmount,id,items())", "value": [ { "id": "cxsales~1", "netAmount": 890, "items": [ { "itemId": "10", "parentItemId": "", "alternativeToItemId": "", "itemCategory": "AGN", "itemText": "Green Emission Calculator", "product": "P300100", "soldToPartyProductId": "", "quantity": 1, "quantityUnit": "EA", "grossWeight": 0, "grossWeightUnit": "", "netWeight": 0, "netWeightUnit": "", "volume": 0, "volumeUnit": "", "plant": "", "netAmount": 890, "netAmountCurrency": "USD", "pricingProduct": "", "incotermsClassification": "", "incotermsLocation": "", "processingStatus": "1", "cancellationReason": "" } ] } ] }</code></pre><P>&nbsp;</P><P>Note that we do not have to specify expanded properties explicitly as part of<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$select</FONT>.</P><P>We see that the item in the example above has a property product that references an id. When we inspect the metadata of the items by searching for the EntityType<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">SalesQuote_items</FONT>. We see that the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">product</FONT><SPAN>&nbsp;</SPAN>property represents the referenced product with a string value and the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">_product</FONT><SPAN>&nbsp;</SPAN>navigation property references the connected <FONT face="terminal,monaco" color="#800000">sap.graph.Product</FONT> entity.</P><P>&nbsp;</P><pre class="lia-code-sample language-markup"><code>&lt;EntityType Name="SalesQuote_items"&gt; &lt;Key&gt; &lt;PropertyRef Name="itemId"/&gt; &lt;/Key&gt; &lt;Property Name="itemId" Type="Edm.String" MaxLength="10" Nullable="false"/&gt; &lt;Property Name="itemText" Type="Edm.String"/&gt; &lt;Property Name="product" Type="Edm.String"/&gt; &lt;NavigationProperty Name="_product" Type="sap.graph.Product"/&gt; ... &lt;/EntityType&gt;</code></pre><P>&nbsp;</P><P>To also include this<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">_product</FONT><SPAN>&nbsp;</SPAN>as part of the response, we can expand it inside the already expanded <FONT face="terminal,monaco" color="#800000">items</FONT>: a nested expand.</P><DIV class="">&nbsp;</DIV><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>/sap.graph/SalesQuote?$top=1&amp;$select=netAmount&amp;$expand=items($expand=_product)</code></pre><P>&nbsp;</P><P>Which will include the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">_product</FONT><SPAN>&nbsp;</SPAN>response inline in the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">item</FONT><SPAN>&nbsp;</SPAN>of the SalesQuote response.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="nested-expand-1.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/83066i62D6195D5E9449B9/image-size/large?v=v2&amp;px=999" role="button" title="nested-expand-1.png" alt="nested-expand-1.png" /></span></P><P><SPAN>If we also want to adapt the format of the expanded product we can nest a&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$select</FONT><SPAN>&nbsp;query parameter in parentheses after the product. To restrict the nested product to the <FONT face="terminal,monaco" color="#800000">displayId</FONT>, for example:</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>/sap.graph/SalesQuote?$top=1&amp;$select=netAmount&amp;$expand=items($expand=_product($select=displayId))</code></pre><P>&nbsp;</P><P><SPAN>If we also want to select more properties, such as&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">netAmountCurrency</FONT><SPAN>, we can just add them to the&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$select</FONT><SPAN>&nbsp;query parameter targeting the SalesQuote, separated by commas:</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>/sap.graph/SalesQuote?$top=1&amp;$select=netAmount,netAmountCurrency&amp;$expand=items($expand=_product($select=displayId))</code></pre><P>&nbsp;</P><P>The response for the SalesQuote with included<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">netAmountCurrency</FONT>,<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">items</FONT><SPAN>&nbsp;</SPAN>and<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">_product</FONT><SPAN>&nbsp;</SPAN>now looks like this:</P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "@odata.context": "$metadata#SalesQuote(netAmount,netAmountCurrency,id,items(_product(displayId,id)))", "value": [ { "id": "cxsales~1", "netAmount": 890, "netAmountCurrency": "USD", "items": [ { "itemId": "10", "parentItemId": "", "alternativeToItemId": "", "itemCategory": "AGN", "itemText": "Green Emission Calculator", "product": "P300100", "_product": { "id": "cxsales~P300100", "displayId": null }, "soldToPartyProductId": "", "quantity": 1, "quantityUnit": "EA", "grossWeight": 0, "grossWeightUnit": "", "netWeight": 0, "netWeightUnit": "", "volume": 0, "volumeUnit": "", "plant": "", "netAmount": 890, "netAmountCurrency": "USD", "pricingProduct": "", "incotermsClassification": "", "incotermsLocation": "", "processingStatus": "1", "cancellationReason": "" } ] } ] }</code></pre><P>&nbsp;</P><H2 id="toc-hId-203668467">Working with collections: filtering, ordering and pagination</H2><P>When working with collections of entities, we typically want to filter the entities by some criteria or arrange them in a specific order. In OData this is supported via the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$filter</FONT><SPAN>&nbsp;</SPAN>and<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$orderby</FONT><SPAN>&nbsp;</SPAN>query parameters. With<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$top</FONT><SPAN>&nbsp;</SPAN>and<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$skip</FONT><SPAN>&nbsp;</SPAN>we can additionally define a sliding window over the result to implement pagination.</P><P>To continue with our example above, let's remove the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$top=1</FONT><SPAN>&nbsp;</SPAN>we added initially to now retrieve a collection of SalesQuotes. Say we want to retrieve all SalesQuotes with a value greater than 100 U.S. Dollars.</P><P>The value condition can be formulated with the greater equal operator:<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">netAmount ge 100</FONT>. For the currency condition we need to compare it with a string (enclosed in single quotes) for equality:<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">netAmountCurrency eq 'USD'</FONT>. We then combine these conditions with a logical and expression and add it to the example query below. We also define an ordering on the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">netAmount</FONT><SPAN>&nbsp;</SPAN>property with the<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$orderby</FONT><SPAN>&nbsp;</SPAN>query parameter, which is ascending by default.</P><BLOCKQUOTE><P>Note: OData operators are lower-case and space-separated. This requires URL encoding. If you are using Postman for this tutorial you don't need to worry as Postman automatically applies URL encoding.&nbsp;</P></BLOCKQUOTE><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>/sap.graph/SalesQuote?$select=netAmount,netAmountCurrency&amp;$expand=items($expand=_product($select=displayId))&amp;$filter=netAmount ge 100 and netAmountCurrency eq 'USD'&amp;$orderby=netAmount</code></pre><P>&nbsp;</P><BLOCKQUOTE><P>Note: OData only supports writing filter expressions using a small vocabulary of filter operators. See here for a full list.</P></BLOCKQUOTE><P>As a last step, we will now define a paging-window over all results. This can be achieved with the query parameters<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$top</FONT>, which specifies how many result entities should be returned: the page size, and<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$skip</FONT>, which defines how many result entities should be skipped from the beginning of the ordering. Hence, we describe the page size with<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$top</FONT><SPAN>&nbsp;</SPAN>and index the single pages with multiples of the page size in<SPAN>&nbsp;</SPAN><FONT face="terminal,monaco" color="#800000">$skip</FONT>. For the second page of five entities each, this would translate to our example as follows:</P><DIV class="">&nbsp;</DIV><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>/sap.graph/SalesQuote?$select=netAmount,netAmountCurrency&amp;$expand=items($expand=_product($select=displayId))&amp;$filter=netAmount ge 100 and netAmountCurrency eq 'USD'&amp;$orderby=netAmount&amp;$top=5&amp;$skip=5</code></pre><P>&nbsp;</P><H2 id="toc-hId-7154962">Summary</H2><P>In this tutorial we had a look at OData, one of the two data protocols used by Graph. We covered all the features that you as a developer working with Graph need to know, like how to:</P><UL><LI>formulate complex queries</LI><LI>inspect the metadata and structure of the unified data model</LI><LI>expand and restrict responses</LI><LI>work with collections</LI></UL><P>OData itself offers much more than what we showed in this tutorial. You can read more about it in the<SPAN>&nbsp;</SPAN><A href="https://docs.oasis-open.org/odata/odata/v4.01/os/part2-url-conventions/odata-v4.01-os-part2-url-conventions.html" target="_blank" rel="nofollow noopener noreferrer">standard</A>.</P><P>With Graph, you as a developer now have one data protocol you can use together with one API to retrieve data in one unified format, no matter the source system.</P><P>---<BR />Florian Moritz</P><P>&nbsp;</P> 2024-03-19T14:21:24.058000+01:00 https://community.sap.com/t5/technology-blogs-by-sap/expanding-the-reach-of-api-catalog-with-sap-api-management/ba-p/13644158 Expanding the Reach of API Catalog with SAP API Management 2024-03-20T11:33:41.357000+01:00 Kasturi https://community.sap.com/t5/user/viewprofilepage/user-id/25297 <P>In our ongoing efforts to enhance the developer experience and promote collaboration, we are thrilled to introduce an upgraded set of access controls for our API catalog.&nbsp;For detailed instructions on how to manage access control, please refer to our comprehensive <A href="https://help.sap.com/docs/integration-suite/sap-integration-suite/manage-access?q=Manage%20Access" target="_self" rel="noopener noreferrer">help documentation</A>.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Slide1.JPG" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/84410i4D53BA0ADE27C777/image-size/large?v=v2&amp;px=999" role="button" title="Slide1.JPG" alt="Slide1.JPG" /></span></P><P>&nbsp;</P> 2024-03-20T11:33:41.357000+01:00 https://community.sap.com/t5/technology-blogs-by-sap/expanding-horizons-amplifying-the-reach-of-api-catalog-via-sap-api/ba-p/13644749 Expanding Horizons: Amplifying the reach of API Catalog via SAP API Management 2024-03-20T19:32:32.803000+01:00 Nyna_Rao https://community.sap.com/t5/user/viewprofilepage/user-id/177690 <P><STRONG><FONT size="5">Introduction:&nbsp;&nbsp;</FONT></STRONG></P><P>SAP API Management offers a straightforward and sophisticated solution for creating a comprehensive API catalog. Within this catalog, you can easily find and leverage APIs (application programming interfaces) that have been published by your organization. This portal provides administrators with the ability to manage developer access to the catalog. Currently, developers can access the catalog through two different methods:&nbsp;&nbsp;</P><OL><LI>If the user already has the developer role assigned in BTP (Business Technology Platform), they will be automatically registered when they log in to the catalog.&nbsp;For more information on developer auto registration, please check the <A href="https://community.sap.com/t5/technology-blogs-by-sap/streamlining-access-through-developer-auto-registration-in-the-api-business/ba-p/13577934" target="_blank">Blog</A> . &nbsp;</LI><LI>To gain entry to the catalog, the developers must request registration, and their requests are subject to approval by the administrator.</LI></OL><P><STRONG><FONT size="5">Feature Enhancement:</FONT></STRONG></P><P><FONT size="4">I</FONT>n our continuous pursuit of improving developer experience and fostering collaboration, we are excited to introduce an enhanced set of access controls for the API catalog. This update offers three distinct levels of access, empowering your team with flexibility. Let us delve into the details of each level and how it reshapes the landscape of API utilisation.</P><OL><LI><STRONG>Authorised Users: Business as Usual&nbsp;</STRONG>&nbsp;:&nbsp;At the heart of our system lies the familiar terrain. Authorised users, those who are logged in and possess the necessary developer role, can seamlessly access, and consume the APIs, maintaining the current behaviour. This ensures a smooth transition for those accustomed to the existing framework.&nbsp;</LI><LI><STRONG>Authenticated Users: Expanding Horizons</STRONG> :&nbsp;Breaking down barriers, we introduce a new layer of access control. Authenticated users, even without a designated role, can now access the API catalog. This provides an opportunity for broader exploration, enabling users to familiarize themselves with available resources. However, to consume any API, the developer role is still a prerequisite, ensuring a balance between exploration and controlled utilization.&nbsp;</LI><LI><STRONG>All Visitors: Welcome All, Consume with Care:</STRONG>&nbsp;In a move towards inclusivity, we now extend access to all visitors, whether logged in or not. This allows anyone to explore the APIs and understand its details without the need for authentication. However, the key to consumption still lies in obtaining the necessary developer role. It is a strategy designed to encourage exploration while maintaining a secure environment for API usage.&nbsp;</LI></OL><P><STRONG><FONT size="5">How to set the access control?&nbsp;</FONT></STRONG></P><P>This is how the Manage Access page<SPAN>&nbsp;looks like. </SPAN><SPAN>&nbsp;</SPAN></P><P><FONT size="6"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Nyna_Rao_0-1710954947423.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/84022iF4A2556214382A4A/image-size/large?v=v2&amp;px=999" role="button" title="Nyna_Rao_0-1710954947423.png" alt="Nyna_Rao_0-1710954947423.png" /></span></FONT></P><P><SPAN class=""><SPAN class="">You can manage the access control by </SPAN><SPAN class="">referring</SPAN><SPAN class=""> to </SPAN><SPAN class="">the </SPAN></SPAN><A href="https://help.sap.com/docs/integration-suite/sap-integration-suite/manage-access?locale=en-US" target="_blank" rel="noopener noreferrer"><SPAN class=""><SPAN class="">help documentation</SPAN></SPAN></A><SPAN class=""><SPAN class="">. </SPAN></SPAN></P><P><SPAN class=""><SPAN class="">Additionally, we have </SPAN><SPAN class="">a</SPAN> </SPAN><A class="" href="https://community.sap.com/t5/technology-blogs-by-sap/expanding-the-reach-of-api-catalog-with-sap-api-management/ba-p/13644158" target="_blank"><SPAN class=""><SPAN class="">comic strip</SPAN></SPAN></A><SPAN class=""><SPAN class=""> available for you to explore a use case.</SPAN></SPAN><SPAN class="">&nbsp;</SPAN></P><P><FONT size="4"><SPAN class=""><STRONG><FONT size="5"><SPAN class=""><SPAN class="">Note</SPAN></SPAN></FONT><SPAN class=""><FONT size="5"><SPAN class="">:</SPAN></FONT><SPAN class="">&nbsp;</SPAN></SPAN></STRONG><SPAN class="">&nbsp;</SPAN></SPAN></FONT></P><OL><LI><SPAN>The "Manage Access" feature is only available in the new design of the Cloud Foundry environment. If you are still using the Classic design, we recommend that you move to the new design, as the Classic design is deprecated and will not be available after June 2024. To learn more about the new design, please see the </SPAN><A href="https://help.sap.com/docs/integration-suite/sap-integration-suite/configure-api-business-hub-enterprise-new-design?locale=en-US" target="_blank" rel="noopener noreferrer"><SPAN>help documentation</SPAN></A><SPAN>. </SPAN><SPAN>&nbsp;</SPAN></LI><LI><SPAN>Access to the developer portal content using the API access plan is not affected by these permissions.</SPAN><SPAN>&nbsp;</SPAN></LI><LI><SPAN>Please be mindful while changing the access control to All Visitors, as this would make your catalog public.&nbsp;</SPAN><SPAN>&nbsp;</SPAN></LI></OL><P><STRONG><FONT size="5"><SPAN class=""><SPAN class="">Conclusion: Take Charge of Your Access</SPAN></SPAN><SPAN class="">&nbsp;</SPAN></FONT></STRONG></P><P><SPAN><SPAN class=""><SPAN class=""><SPAN class="">With these changes, </SPAN><SPAN class="">we </SPAN><SPAN class="">made the API </SPAN><SPAN class="">catalog</SPAN><SPAN class=""> accessible</SPAN><SPAN class=""> for everyone.</SPAN> <SPAN class="">Whether </SPAN><SPAN class="">you are</SPAN><SPAN class=""> someone with </SPAN><SPAN class="">exclusive access</SPAN><SPAN class="">, an explorer without a specific role, or just a casual visitor, </SPAN><SPAN class="">it is</SPAN><SPAN class=""> all straightforward.</SPAN><SPAN class=""> Our </SPAN><SPAN class="">c</SPAN><SPAN class="">atalog</SPAN> <SPAN class="">a</SPAN><SPAN class="">dministrators, by using the 'Manage Access' settings, ensure that you have the right access and control. Enjoy the simplicity, stay in the loop, and let your </SPAN><SPAN class="">c</SPAN><SPAN class="">atalog</SPAN> <SPAN class="">a</SPAN><SPAN class="">dministrator be your guide through this improved API </SPAN><SPAN class="">catalog</SPAN><SPAN class=""> experience.</SPAN></SPAN><SPAN class="">&nbsp;</SPAN></SPAN></SPAN></P><P>&nbsp;</P><P><SPAN>&nbsp;</SPAN></P> 2024-03-20T19:32:32.803000+01:00 https://community.sap.com/t5/technology-blogs-by-sap/single-sign-on-to-sap-cloud-integration-cpi-runtime-from-an-external/ba-p/13655108 Single Sign On to SAP Cloud Integration (CPI runtime) from an external Identity Provider 2024-04-11T06:53:39.270000+02:00 vinayak_adkoli https://community.sap.com/t5/user/viewprofilepage/user-id/216068 <H2 id="toc-hId-990764901"><STRONG>Introduction:</STRONG></H2><P>Yes, you read it right (and you read it right here !). There is an <U>out-of-the-box</U> approach to achieving a single sign-on (SSO) experience for user flows between a corporate identity provider (that authenticates and authorizes the user) and a tenant of Cloud Integration runtime (loosely called CPI worker) fully within the BTP ecosystem.</P><P>Ok, let’s zoom out a bit and break this down.</P><P>If you are reading this blog post, you probably know already that SAP BTP Services can leverage the <U>OpenID Connect</U> federation-based mechanics of SAP Cloud Identity Service (read: SAP IAS) to connect users from corporate Identity Providers like Entra ID (formerly known as Azure AD), Okta, etc. to XSUAA BTP’s OAuth Authorization Server.<BR />This is certainly not uncharted and I did a detailed <A href="https://community.sap.com/t5/technology-blogs-by-sap/single-sign-on-to-sap-integration-suite-sap-api-business-hub-enterprise-via/ba-p/13573716" target="_self">blog post</A> a few months ago demonstrating this setup.</P><P>However, this setup applied mostly to browser-based SaaS applications (<EM>read</EM>: Design Time applications with a web frontend), and that brings us to the objective of this blog -&gt; Customers want to put together a similar setup for their client applications that interface with SAP Cloud Integration’s IFLows (in other words, the CPI runtime).<BR />Certainly, this is not impossible to achieve and solution blueprints like these have existed in the past:</P><UL><LI>My colleague Francisco’s <A href="https://community.sap.com/t5/technology-blogs-by-sap/principal-propagation-in-sap-integration-suite-from-external-system-to-an/ba-p/13543111" target="_blank">blog</A> puts API Management in between a client and Cloud Integration and enforces API Management to perform an OAuthSAMLBearer handshake.</LI><LI>Microsoft champion Martin Raepple <A href="https://community.sap.com/t5/technology-blogs-by-members/principal-propagation-in-a-multi-cloud-solution-between-microsoft-azure-and/ba-p/13479950" target="_blank">teaches</A> how to set up SAML Trust between Entra ID Identity Provider and BTP to set up a user impersonation flow.</LI></UL><P>However, these approaches were often seen as cumbersome to set up / troubleshoot and certainly not for the faint-hearted!</P><H2 id="toc-hId-794251396"><STRONG>Solution Summary:</STRONG></H2><P>An easier solution can be described in two phrases: '<FONT face="terminal,monaco" color="#993366">OpenID Connect</FONT>' and '<FONT face="terminal,monaco" color="#993366">Authorization Code</FONT> grant type'. If you are super-smart then you've figured it out already. You can stop reading this blog and hack this yourself.<BR />I wish you a nice day ahead! If you are like me and need a bit more explanation, keep reading <span class="lia-unicode-emoji" title=":slightly_smiling_face:">🙂</span></P><P>Here is the solution blueprint that explains that handshake:</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Picture1.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/93034i23EDF7DB077BF799/image-size/large?v=v2&amp;px=999" role="button" title="Picture1.png" alt="Picture1.png" /></span></P><P style=" text-align: center; "><FONT size="2"><EM><STRONG>SCENARIO</STRONG>: Flows that require end-user authentication from external Identity Providers can natively do so with OIDC and Authorization Code grant type</EM></FONT></P><P><STRONG>Step 0:</STRONG> Generate Service Instance / Service Key SAP Cloud Integration Runtime. Refer to <A href="https://help.sap.com/docs/cloud-integration/sap-cloud-integration/specifying-service-instance-and-service-key-parameters-in-json-format" target="_self" rel="noopener noreferrer">this</A> link. Instead of <FONT face="terminal,monaco" color="#993366">Client Credentials</FONT>&nbsp;make sure to select&nbsp; <FONT face="terminal,monaco" size="3" color="#993366">Authorization Code</FONT>.</P><P><STRONG>Step 1:</STRONG> Onboard the needed corporate identity providers in SAP IAS and set up the 'Application' that connects back to your SAP BTP Subaccount as a <U>Trusted Identity Provider</U> via OpenID Connect. Refer to my <A href="https://community.sap.com/t5/technology-blogs-by-sap/single-sign-on-to-sap-integration-suite-sap-api-business-hub-enterprise-via/ba-p/13573716" target="_blank">previous</A> blog post for a detailed procedure.&nbsp;</P><P><STRONG>Step 2:</STRONG> Client (end-user)&nbsp; initiates a connection to the required IFlow (or API artifact). This kicks off the 3-legged OAuth user login flow.</P><P data-unlink="true"><STRONG>Step 3:</STRONG> As the user is not signed in, she is redirected to XSUAA's login endpoint, and upon login the IAS tenant's&nbsp;<SPAN>&nbsp;OAuth server authorization endpoint at&nbsp;</SPAN><EM>https://&lt;IAS&nbsp;<SPAN>&nbsp;</SPAN>tenant name&gt;.accounts.ondemand.com</EM><EM>/oauth2/authorize </EM>is invoked using the authorization code grant type. The details of the actual federation as part of the handshake have been omitted here for simplicity. But suffice it to say that the authorization code from the identity provider is made available to the IAS's callback endpoint and finally made available to XSUAA's authorize endpoint and exchanged for the actual access token. This access token will bear the user's scopes and role permissions needed to access the Cloud Integration's IFlow resource.&nbsp;</P><P><STRONG>Step 4:</STRONG> Once successfully authorized, on the receiver side of the IFlow, we will establish connections to 3 different types of backends for illustration purposes. <U>a)</U> S/4HANA Onpremise system over Cloud Connector and Principal Propagation <U>b)</U> SuccessFactors and <U>c)</U> S/4HANA Cloud with <U>OAuth2 SAMLBearer</U> Assertion security material.&nbsp;</P><H2 id="toc-hId-597737891">Putting it all together:</H2><P>Let's get our hands dirty by putting together the sequence now. The prerequisites to follow along are listed below:</P><UL><LI>Administrator privileges in the BTP subaccount where the Integration Suite subscription exists.</LI><LI>An IAS Tenant (with Administrator privileges) that can be coupled (<EM>read</EM>: Trusted) with the said BTP Subaccount.</LI><LI>Privileges to create Applications (<EM>read</EM>: IDP configurations) in Entra ID (Azure AD) and/or Okta.</LI><LI>Postman Client.</LI><LI>Backend systems to which the frontend user principal can be propagated to. Either of S/4HANA OnPrem, S/4HANA Cloud, or SuccessFactors tenant.</LI></UL><H3 id="toc-hId-530307105"><SPAN>Step 0: Create a Service Instance for the Authorization Code grant type</SPAN></H3><P><SPAN>Create an instance of the '<U>Process Integration Runtime</U>' Service (integration-flow service plan)&nbsp; specifically with the <FONT face="terminal,monaco" color="#993366">authorization code</FONT> grant type. You can copy the JSON snippet pasted below. Do not worry about the location of the <FONT face="terminal,monaco" color="#993366">redirect_uri</FONT>. (When we get down to testing the flow, the browser will invoke the redirect_uri, but this has no consequence as the 'code' will be available for us to copy as a query parameter from the URL itself. When we test this from Postman the client, Postman does not invoke the URL. If you are curious to know, you can read about it <A href="https://stackoverflow.com/questions/62760501/how-does-postman-handle-localhost-oauth-2-redirects" target="_self" rel="nofollow noopener noreferrer">here</A>.) Also, make a note that we have specified <FONT face="terminal,monaco" color="#993366">refresh_token</FONT> as part of the requested grant type. This will let us demonstrate the ability for clients to refresh the access token post-expiry.&nbsp;</SPAN></P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "grant-types": [ "refresh_token", "authorization_code" ], "redirect-uris": [ "http://localhost" ], "roles": [ "ESBMessaging.send" ] }</code></pre><P>&nbsp;</P><P>With the service instance created, generate a service key (example block is pasted below). Grab the <FONT face="terminal,monaco" color="#993366">clientid</FONT>, <FONT face="terminal,monaco" color="#993366">clientsecret</FONT>, <FONT face="terminal,monaco" color="#993366">authorizationurl</FONT>, <FONT face="terminal,monaco" color="#993366">tokenurl</FONT> attributes. We will need these later.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-05 at 8.58.50 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92480iC725C39BBB316413/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-05 at 8.58.50 PM.png" alt="Screenshot 2024-04-05 at 8.58.50 PM.png" /></span></P><P>&nbsp;</P><H3 id="toc-hId-333793600">Step 1: Configure OpenID Connect based Trusted Identity Provider of SAP IAS in your SAP BTP subaccount</H3><P>This step is the <EM>heart-and-soul</EM> of our approach. We will couple an SAP IAS tenant with our BTP subaccount that has the subscription of our SAP Cloud Integration (SAP Integration Suite) tenant using OpenID Connect protocol and then onboard the desired external Identity Providers (I will demonstrate Entra ID and Okta) as corporate identity providers in the IAS administration console.<BR />Since I've documented the steps in my previous blog, I will not repeat the exact steps here. Please refer to the following sections in the <A href="https://community.sap.com/t5/technology-blogs-by-sap/single-sign-on-to-sap-integration-suite-sap-api-business-hub-enterprise-via/ba-p/13573716" target="_self">linked</A> blog.</P><P>&nbsp;</P><TABLE border="1" width="100%"><TBODY><TR><TD width="45.2319587628866%" height="30px"><STRONG>Objective</STRONG></TD><TD width="54.7680412371134%" height="30px"><STRONG>Steps to follow from the linked blog</STRONG></TD></TR><TR><TD width="45.2319587628866%" height="57px"><SPAN>Couple your BTP subaccount and your SAP IAS tenant.</SPAN></TD><TD width="54.7680412371134%" height="57px">Steps 1-6</TD></TR><TR><TD width="45.2319587628866%" height="85px"><SPAN>Configure applications (relying party) in Azure AD and Okta IDP based on OpenID Connect and SAP IAS as the callback URI.</SPAN></TD><TD width="54.7680412371134%" height="85px">Steps&nbsp;<SPAN>7 - 25</SPAN></TD></TR><TR><TD width="45.2319587628866%" height="57px"><SPAN>Configure application in Okta with SAML Trust to SAP IAS.</SPAN></TD><TD width="54.7680412371134%" height="57px">Steps <SPAN>26 - 33</SPAN></TD></TR><TR><TD width="45.2319587628866%" height="57px"><SPAN>Onboard the above Corporate Identity Provider configurations into SAP IAS.</SPAN><SPAN><BR /></SPAN></TD><TD width="54.7680412371134%" height="57px">Steps <SPAN>34 - 46</SPAN></TD></TR><TR><TD width="45.2319587628866%" height="57px"><SPAN>configure IAS as the proxy Identity Provider and SAP BTP as the Service Provider.</SPAN></TD><TD width="54.7680412371134%" height="57px">Steps <SPAN>47 - 52</SPAN></TD></TR></TBODY></TABLE><P>Nevertheless, here is a summary of the main steps involved in the setup.</P><P>1. The subaccount where the Integration Suite subscription exists has a 'Trusted connection' with the OpenID Connect protocol (not SAML) to the IAS tenant.</P><H3 id="toc-hId-137280095"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-06 at 9.54.43 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92370i2923FA725D32E9FB/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-06 at 9.54.43 PM.png" alt="Screenshot 2024-04-06 at 9.54.43 PM.png" /></span></H3><P>2. The IAS tenant has a '<U>Corporate Identity provider</U>' connection to Azure AD (Entra ID) via a set of Application credentials and OpenID Connect protocol.</P><H3 id="toc-hId--59233410"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-06 at 9.38.55 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92371i46791EF93D74A62B/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-06 at 9.38.55 PM.png" alt="Screenshot 2024-04-06 at 9.38.55 PM.png" /></span></H3><H3 id="toc-hId--255746915">&nbsp;</H3><P>3. Notice the '<U>Application</U>' settings on the <U>Azure</U> side. The redirect URI has been set to the IAS tenant's '<FONT face="terminal,monaco" color="#993366">../oath2/callback</FONT>' segment</P><H3 id="toc-hId--452260420"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-06 at 9.36.29 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92373i509F15FCA90FD4E7/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-06 at 9.36.29 PM.png" alt="Screenshot 2024-04-06 at 9.36.29 PM.png" /></span></H3><P>4.&nbsp;The IAS tenant has a '<U>Corporate Identity provider</U>' connection to <U>Okta IDP</U> via a set of Application credentials and OpenID Connect protocol.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-06 at 9.39.59 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92432i776D80A7FA5F374B/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-06 at 9.39.59 PM.png" alt="Screenshot 2024-04-06 at 9.39.59 PM.png" /></span></P><P>&nbsp;</P><P>5. Notice the '<U>Application</U>' settings on the Okta side. The redirect URI has been set to the IAS tenant's '<FONT face="terminal,monaco" color="#993366">../oath2/callback</FONT>' segment.</P><H3 id="toc-hId--648773925"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-06 at 9.37.38 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92374i81E6E2901B08DC4C/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-06 at 9.37.38 PM.png" alt="Screenshot 2024-04-06 at 9.37.38 PM.png" /></span></H3><P>6. We will not leverage this flow in our demonstration but note that it is very much possible to use <U>SAML bindings</U> between the Corporate Identity Provider and IAS. The federation works exactly as OIDC.</P><H3 id="toc-hId--920518799"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-06 at 10.45.14 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92375iD2A2E55CFA07BCE7/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-06 at 10.45.14 PM.png" alt="Screenshot 2024-04-06 at 10.45.14 PM.png" /></span></H3><P>&nbsp;</P><P>7. Next, we want to demonstrate a dynamic / Group assertion / <U>Role Collection</U> based user role/authorization determination. For that note that on the Azure side, we have a group called '<U>IntegrationDevelopers</U>' that contains the users who must be authorized to call the IFlow / API on the Cloud Integration side.&nbsp;</P><H3 id="toc-hId--1117032304"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-06 at 9.46.09 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92376i8C5DCA173138645F/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-06 at 9.46.09 PM.png" alt="Screenshot 2024-04-06 at 9.46.09 PM.png" /></span></H3><P>8. Notice how the 'g<U>roups</U>' claim on the IAS side resolves to the value of the group from Azure.</P><H3 id="toc-hId--1313545809"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-06 at 9.44.09 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92378iBDD9051E0C87D093/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-06 at 9.44.09 PM.png" alt="Screenshot 2024-04-06 at 9.44.09 PM.png" /></span></H3><P>9. Similarly, see that the target user has been assigned to the '<U>IntegrationSuiteDevelopers'</U>&nbsp;Group in Okta.</P><H3 id="toc-hId--1510059314"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-06 at 9.41.35 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92379iCF54AEA938541828/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-06 at 9.41.35 PM.png" alt="Screenshot 2024-04-06 at 9.41.35 PM.png" /></span></H3><P>10. Okta presents the user's '<U>Groups</U>' claim to IAS that XSUAA will resolve in a later step.&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-06 at 9.44.47 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92453iC8468488FC669780/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-06 at 9.44.47 PM.png" alt="Screenshot 2024-04-06 at 9.44.47 PM.png" /></span></P><P>11. As a last configuration step, notice that there is a RoleCollection on the BTP side (with the '<U>MessagingSend</U>' role assigned) mapped to the respective groups from the source identity providers.</P><H3 id="toc-hId--1706572819"><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-06 at 10.16.35 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92380iC7EA847196B55E73/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-06 at 10.16.35 PM.png" alt="Screenshot 2024-04-06 at 10.16.35 PM.png" /></span></H3><P>&nbsp;</P><H3 id="toc-hId--1903086324">Step 2 &amp; 3: Initiate the client flow.</H3><P>The easiest way to demonstrate a client flow is to do so in <U>Postman</U> which natively supports simulating an OAuth 2.0 3-legged Authorization Code grant flow. We can break down the segments of the 3-legged flow in a <U>browser</U> as well. I will demonstrate both of these user agents.</P><P>Summary of the steps about to be performed in this section</P><TABLE border="1" width="100%"><TBODY><TR><TD width="50%"><STRONG>Objective</STRONG></TD><TD width="50%"><STRONG>Steps</STRONG></TD></TR><TR><TD width="50%">Use Postman to set up Authorization Code flow with Okta Identity Provider</TD><TD width="50%">1-8</TD></TR><TR><TD>Use Postman to set up Authorization Code flow with Entra ID Identity Provider</TD><TD>9</TD></TR><TR><TD width="50%">Usage of Refresh Tokens</TD><TD width="50%">13-14</TD></TR><TR><TD>Use Browser to set up Authorization code flow with Identity Providers</TD><TD>15-18</TD></TR></TBODY></TABLE><P>1. Within the '<FONT face="terminal,monaco" color="#993366">Authorization</FONT>' tab in Postman, set the '<FONT face="terminal,monaco" color="#993366">Type</FONT>' to '<FONT face="terminal,monaco" color="#993366">OAuth 2.0</FONT>' and the '<FONT face="terminal,monaco" color="#993366">Grant type</FONT>' to '<FONT face="terminal,monaco" color="#993366">Authorization Code</FONT>'.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-07 at 11.15.05 AM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92461i98EB5D2D021225FD/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-07 at 11.15.05 AM.png" alt="Screenshot 2024-04-07 at 11.15.05 AM.png" /></span></P><P>2. Enter the values for the <FONT face="terminal,monaco"><FONT color="#993366">Callback URL</FONT>, <FONT color="#993366">Auth URL</FONT>, <FONT color="#993366">Access Token URL</FONT>, <FONT color="#993366">Client ID</FONT>, <FONT color="#993366">Client Secret</FONT></FONT>&nbsp;from the values saved in the Step 0 block above.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-07 at 11.15.39 AM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92468i5508D569B3F6918F/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-07 at 11.15.39 AM.png" alt="Screenshot 2024-04-07 at 11.15.39 AM.png" /></span></P><P>3. Click on '<U>Get New Access Token</U>'. Make sure to turn on the '<U>Console</U>' tab at the bottom to keep track of requests and responses across the wire.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-07 at 11.16.06 AM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92470iD8B6C992154608E8/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-07 at 11.16.06 AM.png" alt="Screenshot 2024-04-07 at 11.16.06 AM.png" /></span></P><P>4. Postman will launch the Logon pop-up from BTP's Authorization Server. Notice that you are presented with a list of Identity Providers to log into as configured in BTP's Trust Management section. Select the one that corresponds to your IAS Tenant.<BR />Pay attention to the GET requests in the Console tab. You will see that the request to the 'authorize' resource is being redirected to the login page.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-07 at 11.16.34 AM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92471i6DDB9ED43F11866D/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-07 at 11.16.34 AM.png" alt="Screenshot 2024-04-07 at 11.16.34 AM.png" /></span></P><P>5. The system will prompt you to present the user identifier, this will serve as an input to the 'Conditional Authentication' block set in the IAS tenant to resolve which corporate identity provider to redirect to, for the user logon challenge.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-07 at 11.16.57 AM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92472i5D854A4F4A5EE4E0/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-07 at 11.16.57 AM.png" alt="Screenshot 2024-04-07 at 11.16.57 AM.png" /></span></P><P>6. The system determines that the challenge should come from Okta IDP for my <EM>*.sap.com</EM> user name. Please refer to the '<U>Conditional Authentication</U>' screenshot to get a summary of the determination process.<BR />In the 'Console' section, make a note of how the callbacks are handled.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Conditional Authentication section in SAP IAS" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94888i08E3F205BCA248EF/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-10 at 9.32.30 PM.png" alt="Conditional Authentication section in SAP IAS" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Conditional Authentication section in SAP IAS</span></span></P><P>&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-07 at 11.17.19 AM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92473i7BA023461B56F428/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-07 at 11.17.19 AM.png" alt="Screenshot 2024-04-07 at 11.17.19 AM.png" /></span></P><P>7. Okta will authenticate the user and present back the '<FONT face="terminal,monaco" color="#993366">authorization code</FONT>' to IAS.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-07 at 11.17.23 AM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92474iEAFD77C181E2CDBC/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-07 at 11.17.23 AM.png" alt="Screenshot 2024-04-07 at 11.17.23 AM.png" /></span></P><P>8. Finally the client will exchange the authorization code for the <FONT face="terminal,monaco" color="#993366">access token</FONT> from the configured token endpoint.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-07 at 11.17.30 AM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92475i3FCE2A6A26E6ECB8/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-07 at 11.17.30 AM.png" alt="Screenshot 2024-04-07 at 11.17.30 AM.png" /></span></P><P>9. Let us now perform steps nos. 3-8 again, but this time let us log in with our <EM>*.outlook.com</EM> user that gets authenticated and authorized from Entra ID (Azure AD).</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-08 at 5.57.54 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/93040i2DB4528BC41E8F77/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-08 at 5.57.54 PM.png" alt="Screenshot 2024-04-08 at 5.57.54 PM.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-08 at 5.55.56 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/93041iFDA69D400BF70E20/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-08 at 5.55.56 PM.png" alt="Screenshot 2024-04-08 at 5.55.56 PM.png" /></span></P><P>10. Upon inspection, you will note that the access token issued by XSUAA has the '<FONT face="terminal,monaco" color="#993366">ESBMessaging.send</FONT>' scope as determined by the '<FONT face="terminal,monaco" color="#993366">Groups</FONT>' claim presented by the source IDP. You will remember that we created a mapping for this resolution in a previous step. Also, note that the system bears a <FONT face="terminal,monaco" color="#993366">refresh_token</FONT>.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-07 at 11.17.51 AM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92476i13000808DE7417E9/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-07 at 11.17.51 AM.png" alt="Screenshot 2024-04-07 at 11.17.51 AM.png" /></span></P><P>11. Further, if you inspect the respective JWTs issued by Okta and Entra ID, you will see that the tokens contain the claims that represent the <U>Groups</U>, <U>RoleCollections</U>, and <U>User</U> Identifier info.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-08 at 6.02.17 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/93038iDF074F57326C609D/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-08 at 6.02.17 PM.png" alt="Screenshot 2024-04-08 at 6.02.17 PM.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-08 at 6.01.10 PM.png" style="width: 982px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/93039i00D82A733F67F3CD/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-08 at 6.01.10 PM.png" alt="Screenshot 2024-04-08 at 6.01.10 PM.png" /></span></P><P>12. Simply go ahead and '<U>Use Token</U>' to load the token to make your request.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-07 at 11.18.01 AM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92477i0BF06E608D43D2AA/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-07 at 11.18.01 AM.png" alt="Screenshot 2024-04-07 at 11.18.01 AM.png" /></span></P><P>13. Using the refresh_token -&gt; Notice that the token will expire after a set duration (based on the 'expiry' setting). As you can see in the screenshot below, Postman detects that the available token is expired. It gives an option to '<U>Refresh</U>' the token. Click on this button.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-07 at 12.58.21 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92484i6CD290951A002C25/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-07 at 12.58.21 PM.png" alt="Screenshot 2024-04-07 at 12.58.21 PM.png" /></span></P><P>14. Make a note in the Console tab that the client POSTs to the token endpoint with the available refresh_token and the refresh_token grant_type to get a fresh access token.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-07 at 12.59.15 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92485i844B14E9BCCE1FBB/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-07 at 12.59.15 PM.png" alt="Screenshot 2024-04-07 at 12.59.15 PM.png" /></span></P><P>15. In the next screenshots, let us perform the same set of steps in a browser.&nbsp;We will need to frame the URL to the <FONT face="terminal,monaco" color="#993366">/oauth/authorize</FONT> endpoint. The easiest way to do so would be to copy the URL from the Postman Console we referred to before. The URL is in the format :</P><PRE><A target="_blank" rel="noopener">https://&lt;tenant-id&gt;&gt;/authentiation.&lt;dc&gt;.hana.ondemand.com/oauth/authorize<SPAN>?<BR />response_type=code&amp;client_id=&lt;url-encoded-client-id&gt;&amp;redirect_uri=&lt;url-encoded_redirect_uri&gt;</SPAN></A></PRE><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-08 at 8.58.56 AM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92933i2E3BE633C8DBD648/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-08 at 8.58.56 AM.png" alt="Screenshot 2024-04-08 at 8.58.56 AM.png" /></span></P><P>16. Invoke the URL in a browser.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-08 at 9.24.05 AM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92934iCE3000E772A66A02/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-08 at 9.24.05 AM.png" alt="Screenshot 2024-04-08 at 9.24.05 AM.png" /></span></P><P>17. After the 'login' and 'authenticate' procedures, you will see that the browser is redirected to the redirect_uri location. You can copy the '<FONT face="terminal,monaco" color="#993366">code</FONT>' parameter from the URL.&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-08 at 8.59.57 AM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92935i642C2B58390DCE85/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-08 at 8.59.57 AM.png" alt="Screenshot 2024-04-08 at 8.59.57 AM.png" /></span></P><P>18. Go back to Postman and POST the Access Token endpoint with the <FONT face="terminal,monaco" color="#993366">grant_type</FONT> set to <FONT face="terminal,monaco" color="#993366">authorization_code</FONT> and the copied <FONT face="terminal,monaco" color="#993366">code</FONT> and the <FONT face="terminal,monaco" color="#993366">redirect_uri</FONT>. The server will respond with the <FONT face="terminal,monaco" color="#993366">access_token</FONT> with the same set of attributes populated as demonstrated in Step 11.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-08 at 9.03.29 AM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/92936iBAA309680685FF77/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-08 at 9.03.29 AM.png" alt="Screenshot 2024-04-08 at 9.03.29 AM.png" /></span></P><H3 id="toc-hId--2099599829">&nbsp;</H3><H3 id="toc-hId-1998853962">Step 4: Integration Flow Reciever side propagation</H3><P>Now that we have an <FONT face="terminal,monaco" color="#993366">access_token</FONT> that can be presented to the Cloud Integration runtime (to a 'Sender Adapter'), let us put together a simple IFlow that can demonstrate the fact that the user's identity from the external identity provider can be propagated to 3 backend systems - <U>a)</U> S/4HANA Onpremse, <U>b)</U> SuccessFactors and <U>c)</U> S/4HANA Cloud via <U>Principal Propagation</U> and <U>OAuth2SAMLBearer</U> mechanisms respectively.</P><P>Here is a summary of the steps we intend to achieve:</P><TABLE border="1" width="100%"><TBODY><TR><TD width="50%"><STRONG>Objective</STRONG></TD><TD width="50%"><STRONG>Steps</STRONG></TD></TR><TR><TD width="50%">Create a sample IFlow that demonstrates the user propagation sequence to 3 different types of backend systems.</TD><TD width="50%">1-2</TD></TR><TR><TD width="50%">Invoke S4HANA Cloud backend&nbsp;</TD><TD width="50%">3 - 7</TD></TR><TR><TD>Invoke SAP SuccessFactors backend</TD><TD>8 - 13</TD></TR><TR><TD>Invoke SAP S/4HANA Onpremise backend</TD><TD>14 - 17</TD></TR></TBODY></TABLE><P>1. Let's start by putting together a simple IFlow to illustrate the user propagation flow. Since we are planning to invoke with 3 backends, the quickest way to demonstrate this would be to create a <U>Router</U> that has 3 branches. Each with a 'Request-Reply' step for the backend type, S/4HANA Cloud, SuccessFactors, and S/4HANA OnPremise respectively.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 5.04.01 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94321iB1506DA98BBAAA08/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 5.04.01 PM.png" alt="Screenshot 2024-04-09 at 5.04.01 PM.png" /></span></P><P>2. The logic we will follow is that the client passes a value in a custom header named 'target' that shall determine which of the routes is to be invoked.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 5.11.04 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94329iDAD95FEA401ADF4F/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 5.11.04 PM.png" alt="Screenshot 2024-04-09 at 5.11.04 PM.png" /></span></P><P>3. In the property sheet of the HTTP Receiver for S/4HANA Cloud backend, notice that we've used a credential named '<FONT face="terminal,monaco" color="#993366">s4hanaCloudCredentials</FONT>' with the OAuth2 SAML Bearer Assertion type.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 5.04.51 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94322i510E3E684E9F63B9/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 5.04.51 PM.png" alt="Screenshot 2024-04-09 at 5.04.51 PM.png" /></span></P><P>4. I will not get into the details behind how the attributes of this Security Material have been formulated. Refer to parts of&nbsp;<A href="https://community.sap.com/t5/technology-blogs-by-sap/how-to-get-principal-propagation-from-cloud-foundry-to-s-4hana-cloud-with/ba-p/13534051" target="_self">this</A> blog post for details. The points worth mentioning here are that <U>a)</U> we are using the target system type <U>SAP BTP (CF)</U> and<U> b)</U> the '<FONT face="terminal,monaco" color="#993366">userIdSource'</FONT>&nbsp;attribute is annotated for '<FONT face="terminal,monaco" color="#993366">email</FONT>' &amp; nameIdFormat is set to '<FONT face="terminal,monaco" color="#993366">urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</FONT>', thereby implying that the user identifier from our original JWT token negotiated with the corporate identity provider will serve as the user principal to be propagated.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 5.08.29 PM.png" style="width: 833px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94324iB398FD91A28BDD12/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 5.08.29 PM.png" alt="Screenshot 2024-04-09 at 5.08.29 PM.png" /></span></P><P>5. Let us make a call to the IFlow URL with the access token set from step 8 described in the above section. Note that we've set the 'target' header attribute to 's4hanacloud'&nbsp; so that the call gets executed in the first route. We get an HTTP 200 OK and the service document as the response and there you have it! We were able to successfully propagate the user from an external identity provider and execute a call in an S/4HANA backend with the user's context.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 5.11.42 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94328i421B86AB9618EB8D/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 5.11.42 PM.png" alt="Screenshot 2024-04-09 at 5.11.42 PM.png" /></span></P><P>6. How do I prove my point that the user was indeed propagated? The next two screenshots do so. Note that on the S/4HANA side, I have a 'Business User' that bears my (that is propagated from Okta) emailID. Also, note that the HTTP Call is executed with this user context and NOT with a Communication User (technical user) attached to the Communication Arrangement.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 4.24.48 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94326i27A22AD5685783C2/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 4.24.48 PM.png" alt="Screenshot 2024-04-09 at 4.24.48 PM.png" /></span></P><P>7. Further to prove my point, I execute step no. 5, this time by presenting my *@outlook.com user (that comes from Entra ID), you see that the call fails and the error description calls out that the backend was not able to resolve the presented *.outlook.com user.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 5.13.21 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94327i890B800F01F00C1B/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 5.13.21 PM.png" alt="Screenshot 2024-04-09 at 5.13.21 PM.png" /></span></P><P>8. Let us now look at the 2nd route, the one that invokes a SuccessFactors URL. We extend the same 'OAuthSAMLBearer Assertion' type with a credential named 'SFSFUserPrincipal'. On the processing tab, you will see that I'm invoking a GET Query on the JobProfile resource.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 5.06.05 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94332iB3049CBDC9B0A638/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 5.06.05 PM.png" alt="Screenshot 2024-04-09 at 5.06.05 PM.png" /></span></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-10 at 8.36.23 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94884i647EB0D62F0D3B36/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-10 at 8.36.23 PM.png" alt="Screenshot 2024-04-10 at 8.36.23 PM.png" /></span></P><P>9. In the details of the Security Material, note that we've set the attributes per SuccessFactors <A href="https://help.sap.com/docs/SAP_SUCCESSFACTORS_EMPLOYEE_CENTRAL/736e8ee2ac8943c7b6278039a7924e97/3a77fab602834ca686824555f7560d70.html?version=2205" target="_blank" rel="noopener noreferrer">documentation</A>. The User ID is set for principal propagation. Like before, we've used the same <FONT face="terminal,monaco" color="#993366">nameIdFormat</FONT> as set in step 4 above, and don't forget to include the <FONT face="terminal,monaco" color="#993366">apiKey</FONT> attribute as well.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 5.09.01 PM.png" style="width: 966px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94333iE5CE169F04974F33/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 5.09.01 PM.png" alt="Screenshot 2024-04-09 at 5.09.01 PM.png" /></span></P><P>10. Let us now invoke the IFlow, this time around with the header 'target' set to 'sfsf'. I get back a response from SuccessFactors with the JobProfile details.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 5.16.44 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94334i265F9EF4FBB1193A/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 5.16.44 PM.png" alt="Screenshot 2024-04-09 at 5.16.44 PM.png" /></span></P><P>11. Again, <EM>how do we prove that the call indeed was made in the signed-in user's context</EM>? There are many ways to establish this. A simple way I followed was to put a 'proxy' layer like API Management before the call hits the SuccessFactors backend and print out the '<U>Bearer token</U>' from the '<U>Authorization</U>' header.&nbsp; Upon Base64 decoding the token, you will see that the token bears a '<U>sfPrinciple</U>' attribute with the employee ID identifier.&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 2.54.16 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94335i5FCCE4AFBD05E781/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 2.54.16 PM.png" alt="Screenshot 2024-04-09 at 2.54.16 PM.png" /></span></P><P>12. Look up the employee profile of the user in question in your SuccessFactors tenant and you can verify the matching employee ID and the corresponding email address.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 2.53.41 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94336i749BE4BD06089628/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 2.53.41 PM.png" alt="Screenshot 2024-04-09 at 2.53.41 PM.png" /></span></P><P>13. Negative testing -&gt; If I perform the call again, this time by signing in with the email address from Entra ID you should see a 401 unauthorized exception stating that the propagated user wasn't resolved.&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 5.15.20 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94337iC1819ED14B8CBFF6/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 5.15.20 PM.png" alt="Screenshot 2024-04-09 at 5.15.20 PM.png" /></span></P><P>14. Finally, we are down to the last segment of our testing. A connection to S/4HANA On-premise. I've configured an SAP Cloud Connector and an X.509 certificate signing procedure (that is beyond the scope of this demonstration) and have dialed 'Principal Propagation' for the authentication type.&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 5.06.26 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94413i1D03B76E1099D38B/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 5.06.26 PM.png" alt="Screenshot 2024-04-09 at 5.06.26 PM.png" /></span></P><P>15. Invoking the client this time around with the 'target' header set to 's4hanaonpremise'. I get back a response from the server with my service document for the invoked GWSAMPLE_BASIC OData service.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-10 at 9.42.33 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94889i5506CCA84879D9A5/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-10 at 9.42.33 PM.png" alt="Screenshot 2024-04-10 at 9.42.33 PM.png" /></span></P><P>16. As a quick verification step, let us go to the 'Monitor' section in the Cloud Connector and within the 'Most Recent Requests' tab, you can see a record for the 'User' that was propagated.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 4.54.26 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94414i8899BAAC3848E6E0/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 4.54.26 PM.png" alt="Screenshot 2024-04-09 at 4.54.26 PM.png" /></span></P><P>17. Open the LJSTrace log file and you can hunt down a log entry that corresponds to the user subject that was propagated via the short-lived x.509 certificate.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Screenshot 2024-04-09 at 5.02.03 PM.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/94415iC16607E26C47C404/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-09 at 5.02.03 PM.png" alt="Screenshot 2024-04-09 at 5.02.03 PM.png" /></span></P><P><EM>Phew!</EM></P><H2 id="toc-hId-2095743464">Summary:</H2><P>It is beyond doubt that '<FONT face="terminal,monaco" color="#993366">client credentials</FONT>' and '<FONT face="terminal,monaco" color="#993366">x.509 certificate</FONT>' are the two most prominent and widely popular ways to authenticate to an Integration Flow / API artifact in SAP Integration Suite, but should you have a requirement to authenticate and authorize with the client user's identity from a corporate Identity Provider, OpenID Connect support from SAP Cloud Identity Service along with the <FONT face="terminal,monaco" color="#993366">Authorization Code</FONT> grant type in SAP Integration Suite provide an excellent and out-of-box approach to get your job done.</P><P>Cheers, and more power to the&nbsp; <a href="https://community.sap.com/t5/c-khhcw49343/SAP+Integration+Suite/pd-p/73554900100800003241" class="lia-product-mention" data-product="23-1">SAP Integration Suite</a>&nbsp;&nbsp;Community!</P> 2024-04-11T06:53:39.270000+02:00 https://community.sap.com/t5/technology-blogs-by-sap/10-ways-to-reshape-your-sap-landscape-with-sap-business-technology-platform/ba-p/13673510 10+ ways to reshape your SAP landscape with SAP Business Technology Platform - Blog 5 2024-04-18T11:57:49.712000+02:00 pinakiray https://community.sap.com/t5/user/viewprofilepage/user-id/590670 <H2 id="toc-hId-992556228"><STRONG>Blog 5: How hybrid Integration upholds the role of Clean Core</STRONG></H2><P><STRONG><SPAN>Summary:&nbsp;</SPAN></STRONG><EM><SPAN>In this blog series we will look at the role of the SAP Business Technology Platform in reshaping your SAP landscape including SAP and Non-SAP systems. In this seventh blog we’ll look into the important role of integration in terms of clean core and the overall transformation journey.</SPAN></EM></P><P><EM><SPAN><BR /></SPAN></EM><SPAN>We’ve learned about the <A href="https://community.sap.com/t5/technology-blogs-by-sap/10-ways-to-reshape-your-sap-landscape-with-sap-business-technology-platform/ba-p/13637444" target="_blank">The Central Role of Clean Core</A> in the first issue of this blog series. The concept of a clean core refers to keeping the core ERP such as SAP S/4HANA as <STRONG>up to date</STRONG>, u<STRONG>nmodified</STRONG>, <STRONG>documented</STRONG>, <STRONG>consistent</STRONG>, <STRONG>efficient</STRONG>, and <STRONG>cloud compliant</STRONG> as possible. And while extensions - either as in-app or side-by-side - probably come to mind right away when talking about these topics, it’s imperative to apply the same guiding principles to integration.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="pinakiray_0-1713971418198.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/101253iB212F13E30B72C4E/image-size/large?v=v2&amp;px=999" role="button" title="pinakiray_0-1713971418198.png" alt="pinakiray_0-1713971418198.png" /></span></P><P>&nbsp;</P><P><STRONG><SPAN>Being Aware: A Broader Perspective</SPAN></STRONG></P><P><SPAN>Some of the more severe technical debts in terms of integration include an existing, oftentimes rich <STRONG>SAP Process Orchestration (SAP PO)</STRONG> landscape, which is going to be <STRONG>out of mainstream maintenance until 2027</STRONG>, along with the Business Suite 7. On top of that there’s usually a multitude of non-SAP Adapters and Connectors, probably collected from multiple vendors and solutions over the last decade(s), which have created not only duplications, but also technical-, as well as commercial- and knowledge lifecycles. The Assessment-, Migration and ISA-M- Tooling as well as the SAP Edge Integration Cell will make this transitions as plannable and digestible as possible and are all included with the <STRONG>SAP Integration Suite</STRONG>.</SPAN></P><P><SPAN>The significance of integration extends far beyond the migration and modernization phase.<BR />APIs have become ubiquitous across the technological landscapes, forming the backbone of communication and service delivery and must be <STRONG>centrally secured, monitored and documented</STRONG>. But modern API-Management is not just about managing technology - it's about managing business outcomes. It enables organizations to leverage the full potential of their digital assets, create expansive ecosystems, and deliver exceptional user experiences while achieving and maintaining security, compliance, and performance.<BR /><BR /></SPAN></P><P><STRONG><SPAN>Decoupling for Flexibility and Agility</SPAN></STRONG></P><P><SPAN>Staying as close as possible to the standard through decoupling go hand in hand with the <A href="https://www.sap.com/products/technology-platform/what-is-sap-business-technology-platform.html#:~:text=SAP%20Business%20Technology%20Platform%20is,capabilities%20in%20one%20unified%20environment." target="_blank" rel="noopener noreferrer">SAP Business Technology Platform (BTP)</A>. In terms of integration the hybrid PaaS/on-prem runtime <STRONG>SAP Integration Suite</STRONG> covers all kinds of cloud-to-any as well as ground-to-ground integration needs.</SPAN></P><P><SPAN>With its comprehensive integration capabilities, the <STRONG>SAP Integration Suite</STRONG> provides the following contributions and qualities:</SPAN></P><P><STRONG><SPAN>“Standard” in terms of integration</SPAN></STRONG></P><UL><LI><SPAN>In the ongoingly updated <A href="http://www.sap.com/cloud-integration" target="_blank" rel="noopener noreferrer">SAP Integration Strategy Paper</A> Christian Klein, Juergen Mueller and Thomas Saueressig have outlined the SAP road map towards an integrated intelligent suite and declared <STRONG>SAP Integration Suite</STRONG> as SAP’s strategic standard. Check out the updates regularly and&nbsp;learn about the most recent integration highlights.</SPAN></LI></UL><P><STRONG><SPAN>Documentation and Consistency</SPAN></STRONG></P><UL><LI><STRONG><SPAN>Documentation:</SPAN></STRONG><SPAN> <A href="https://www.sap.com/germany/services-support/integration-solution-advisory-methodology.html" target="_blank" rel="noopener noreferrer">ISA-M</A> is an invaluable open framework and toolset included even with the free plans of Integration Suite and helps in defining and standardizing integration strategies,<BR />-styles and -practices. By providing a clear structure and methodology <STRONG>for SAP as well as non-SAP requirements and technologies</STRONG>, it ensures that all processes like integration governance, integration quality assurance- and responsibilities are defined and documented consistently and are backed by corresponding best practices and reference architectures. </SPAN></LI><LI><STRONG><SPAN>Consistency, Governance and Monitoring</SPAN></STRONG><SPAN>: an integrated and complete suite of tools for centralized connection, mapping, transformation, management, monitoring and governance of integrations, providing a single pane that helps maintaining all styles of integrations and keep consistency across the enterprise landscape.</SPAN></LI></UL><P><STRONG><SPAN>Efficiency and Cloud Compliance</SPAN></STRONG></P><P><SPAN>Instead of just providing templates (which is the industry standard), the SAP Integration Suite provides <STRONG><EM>curated</EM></STRONG> out of the box content, for example in the form of more than 3’400 integration process flows. Let’s say you’re using one of those standard iFlows to easily filing your companies annual tax returns to the government and said government changes/adds requirements - either from a technical and/or compliance point of view, SAP is usually going to adapt to these changes and will <STRONG>refactor/change, test and update </STRONG>that iFlow at no additional cost.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="pinakiray_1-1713971458271.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/101254iB00F0AC4B6765919/image-size/large?v=v2&amp;px=999" role="button" title="pinakiray_1-1713971458271.png" alt="pinakiray_1-1713971458271.png" /></span></P><UL><LI><STRONG><SPAN>Cloud-Native Integration</SPAN></STRONG><SPAN>: As a cloud-native solution, the suite facilitates modern cloud principles, ensuring that the core system is efficiently integrated with cloud services without requiring any modifications to the core. The Edge Integration Cell follows the same design principles and provides an on-prem runtime, usually at no additional cost </SPAN></LI></UL><P><STRONG><SPAN>Keeping the Core Clean</SPAN></STRONG></P><UL><LI><STRONG><SPAN>Get started quickly</SPAN></STRONG><SPAN> with predefined process integrations for the most commonly used scenarios, including APIs, events, and well-documented integration flows to integrate SAP applications as well as third-party applications with minimal effort. Benefit from <STRONG>aligned domain models</STRONG> to synchronize master data objects between different LoB’s</SPAN></LI><LI><STRONG><SPAN>Graph:</SPAN></STRONG><SPAN> Extending traditional API Management,&nbsp;Graph&nbsp;enables you to abstract the landscape, share data by <EM>removing</EM> and/or <EM>extending</EM> data sets for different use cases, connect all major SAP business objects out of the box while hiding the landscape complexity (replicated, distributed, or shared data).</SPAN></LI><LI><STRONG><SPAN>Decoupling Extensions</SPAN></STRONG><SPAN>: By allowing businesses to build extensions and custom applications outside the core ERP side by side on the BTP, the suite ensures that the core remains unmodified, which is a key aspect of the clean core concept.</SPAN></LI></UL><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="pinakiray_0-1713972648689.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/101274iE5539757CFB288A5/image-size/large?v=v2&amp;px=999" role="button" title="pinakiray_0-1713972648689.png" alt="pinakiray_0-1713972648689.png" /></span></P><P>&nbsp;</P><P><STRONG><SPAN>Conclusion</SPAN></STRONG></P><P><STRONG><SPAN>Preparing for the Future</SPAN></STRONG></P><P><SPAN>The combination of cloud computing, a clean core strategy, and the move to SAP Integration Suite as <EM>one</EM> <EM>central, hybrid iPaaS</EM> positions businesses for future growth, market dynamics and innovation. It lays the groundwork for quickly adopting emerging technologies like AI, machine learning or event driven architectures as well as the next big thing to stay ahead in the digital race!</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="pinakiray_3-1713971528437.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/101258iABFE8107D2B2A203/image-size/large?v=v2&amp;px=999" role="button" title="pinakiray_3-1713971528437.png" alt="pinakiray_3-1713971528437.png" /></span></P><P>&nbsp;</P><P><STRONG><SPAN>Links:</SPAN></STRONG></P><P><SPAN>Your success is our mission. You are wondering when, what, and how to transform to be well equipped for your changing business needs? SAP is here to guide you through your transformation and to support you along the way.&nbsp;<A href="https://www.sap.com/docs/download/2020/02/520ea921-847d-0010-87a3-c30de2ffd8ff.pdf" target="_blank" rel="noopener noreferrer">Download the Document</A></SPAN></P><P><SPAN><A href="https://www.sap.com/germany/services-support/integration-solution-advisory-methodology.html" target="_blank" rel="noopener noreferrer">SAP Integration Solution Advisory Methodology (ISA-M)</A></SPAN></P><P><SPAN><A href="https://www.sap.com/products/technology-platform/integration-suite.html" target="_blank" rel="noopener noreferrer">Integration Software | SAP Integration Suite</A></SPAN></P><P><SPAN><A href="https://blogs.sap.com/2022/04/26/integration-assessment-capability-within-sap-integration-suite-is-general-available-now/" target="_blank" rel="noopener noreferrer">Integration Assessment provided by SAP BTP</A></SPAN></P><P><SPAN><A href="https://api.sap.com/" target="_blank" rel="noopener noreferrer">SAP Business Accelerator Hub</A>.</SPAN></P><P><SPAN><BR /><STRONG>Events</STRONG></SPAN></P><P><SPAN>To get more insights, please also visit one of our BTP Innovation Days:</SPAN></P><UL><LI><SPAN>Innovation Day Switzerland:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bern 14-May-24 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<A href="https://events.sap.com/ch/sap-btp-innovation-day-bern-2024/de/home?url_id=banner-ch-homepage-row6-pos2-BTPinnovationday-240229" target="_blank" rel="noopener noreferrer">SAP | SAP BTP Innovation Day Switzerland</A></SPAN></LI><LI><SPAN>Innovation Day Germany&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Essen 16-May-24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A href="https://events.sap.com/de/sap-btp-innovation-day/de/home" target="_blank" rel="noopener noreferrer">SAP | SAP BTP Innovation Day</A></SPAN></LI></UL><P>&nbsp;</P><P>&nbsp;</P> 2024-04-18T11:57:49.712000+02:00 https://community.sap.com/t5/technology-blogs-by-members/how-to-host-static-webpages-through-sap-cpi-iflow/ba-p/13678233 How to host static webpages through SAP CPI-Iflow 2024-04-22T15:26:00.691000+02:00 GopisettySai https://community.sap.com/t5/user/viewprofilepage/user-id/149967 <P>Before walking through the solution, We will glide through How it started.</P><P>Addressing the Integration community, We have a lot of systems to connect and indeed as an integration consultant we will be having POs and CPI systems to access them we will be using bookmarks and find it difficult to remember and open them at first glance.</P><P>As an enthusiastic integration consultant, I wanted to access the systems with in single click. I built a webpage with the help of Chat-GPT and wanted to host it but was not sure to host it on the internet and expose the domains.</P><P>Discussed the same with teammates and one of the teammates came up with a solution why can’t we do this with CPI, We will host it through CPI.</P><P>How to achieve this?</P><OL><LI>It is assumed that you have the HTML5 code in a single file already. You need to copy the HTML content and encode this to base64 (using an<A href="https://www.base64encode.org/" target="_blank" rel="noopener nofollow noreferrer">&nbsp;online tool) and copy the base64 encoded string to Notepad or any IDE of your choice.</A></LI><LI>Please save the Base64 code in a header as below.<span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Content Modifier" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/99999i91E090187100CA57/image-size/medium?v=v2&amp;px=400" role="button" title="Content.png" alt="Content Modifier" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Content Modifier</span></span></LI><LI>COpy the below groovy script to decode the Base64 to HTML script.</LI></OL><P>&nbsp;</P><pre class="lia-code-sample language-javascript"><code>import com.sap.gateway.ip.core.customdev.util.Message import java.util.HashMap import java.text.SimpleDateFormat import java.util.Base64; def Message processData(Message message) { def staticContent = message.getProperties().get("HTML_CONTENT"); //Parse static content Base64.Decoder decoder = Base64.getDecoder(); staticContent = new String(decoder.decode(staticContent)); message.setBody(staticContent.getBytes("UTF-8")); message.setHeader("Content-Type", "text/html; charset=utf-8"); return message }​</code></pre><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp;</P><P>&nbsp; &nbsp; &nbsp; &nbsp; 4.Deploy the iflow, copy the HTTPS URL, and hit it from the browser, you can access your webpage.<span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Integration organizer webpage.png" style="width: 260px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/100026i8367FE411A1089B2/image-size/large?v=v2&amp;px=999" role="button" title="Integration organizer webpage.png" alt="Integration organizer webpage.png" /></span>&nbsp; &nbsp; &nbsp; &nbsp;5. In case you're getting a CORS error, Please use API management to surpass it.</P><P>&nbsp;<SPAN>Let me know if you have any queries and please share your interesting findings as well! You can contact me on&nbsp;</SPAN><A href="https://www.linkedin.com/in/gopisetty-sai-charan/" target="_blank" rel="nofollow noopener noreferrer">LinkedIn&nbsp;</A><SPAN>regarding the same! Until then stay tuned!</SPAN></P> 2024-04-22T15:26:00.691000+02:00 https://community.sap.com/t5/technology-blogs-by-sap/supporting-multiple-api-gateways-with-sap-api-management-using-azure-api/ba-p/13680433 Supporting Multiple API Gateways with SAP API Management – using Azure API Management as example 2024-04-25T17:02:14.909000+02:00 Chaim_Bendelac https://community.sap.com/t5/user/viewprofilepage/user-id/194397 <H2 id="toc-hId-993389480">Introduction</H2><P><SPAN>APIs are the cornerstone of modern business ecosystems and are crucial in today’s digital economy. The advent of action-based generative AI, which relies on accessible and well-defined APIs, underscores the importance of composable, API-centric software architectures.</SPAN></P><P><SPAN>Securing, governing, and managing APIs is essential. API Management has become a recognized discipline, supported by solutions from leading vendors such as SAP, Microsoft, Google, IBM, Salesforce, among others.&nbsp;</SPAN>API Management fosters an ecosystem where authorized developers can access and consume carefully curated and secured collections of APIs.</P><P><SPAN>The essence of API management solutions lies in their ability to regulate access, authenticate and validate API calls through an <EM>API Gateway</EM>,&nbsp;</SPAN>a proxy solution deployed between API consumers and the service endpoints themselves.</P><P>Traditional API Management solutions relied on a single, central API gateway, set up in proximity to the APIs they safeguard. However, this simple architecture is less common today, due to the distributed nature of cloud software applications; customers deploy a growing number of <EM>distributed</EM> API gateways.</P><P>For example, SAP’s API Management solution, a capability of the SAP Integration Suite, provides API gateway functionality as a service available in over twenty regions around the world, as well as self-hosted options for on-premise or private-cloud deployments. This offers customers more flexibility on where to deploy API gateways.</P><P>Customers of SAP API Management may, additionally, use API gateways from other vendors and cloud providers like Microsoft Azure. But this presents a new challenge: while there may be multiple API gateways, customers still want to present the managed API information in a unified and centralized API catalog.</P><P><SPAN>To address this, SAP and Microsoft have partnered, sharing programmatic interfaces to facilitate a cohesive API catalog.</SPAN></P><P>This blog <SPAN>targets SAP Integration Suite customers utilizing the SAP API catalog (API Business Hub Enterprise) as their <EM>central</EM> repository for all APIs, accessible through a developer portal or directly via SAP Build development tools (SAP Build Apps, SAP Build Code, SAP Build Process Automation)</SPAN></P><P>We introduce an extensible API import utility which streamlines and automates the process of importing, registering and publishing additional APIs into the central catalog, such as APIs managed by other vendors, or found in other external catalogs. Here, we focus on Microsoft’s Azure API Management as an information source, but the API import utility can be easily adapted to automate the import of APIs from any&nbsp;other source. <SPAN>For further details, please reach out to us.</SPAN></P><P>A <A title="govern sap apis in a single place" href="https://community.sap.com/t5/technology-blogs-by-members/govern-sap-apis-living-in-various-api-management-gateways-in-a-single-place/ba-p/13682483" target="_blank">companion blog</A>&nbsp;by our Microsoft friends details how APIs managed by the SAP API gateway can be imported to the Azure API Center, a new central catalog offering from Microsoft.</P><H2 id="toc-hId-796875975">Automated API import</H2><P>SAP API Management designates APIs that are not safeguarded by an SAP API gateway as&nbsp;“externally managed” or “unmanaged" APIs. Such APIs can be imported and listed in the API catalog and developer portal, and then optionally further enhanced or managed via API proxies, for instance to ensure that all APIs of the organization share the same security policies and common URL addressing.</P><P>While it is straightforward to manually specify a few individual unmanaged APIs and keep these specifications up to date, it becomes a daunting challenge for larger collections of APIs, especially those managed by a non-SAP API gateway.</P><P>This blog outlines an extensible API import utility that automates the process of importing, registering and publishing APIs into SAP API Management. <SPAN>The utility employs a “factory” design pattern implemented as an integration with Microsoft’s Azure API Management.</SPAN></P><P>Available as a stand-alone open-source portable Java application, the API import utility can be executed from a desktop, but it is more likely that you will want to incorporate it into a regular workflow or CI/CD pipeline, in order to ensure that the API catalog remains up to date.</P><H2 id="toc-hId-600362470">Accessing the API Import Utility</H2><P><SPAN>Essential tools for using the API Import Utility include:</SPAN></P><UL><LI>Git</LI><LI>Java 11+</LI><LI>Maven 3.9+</LI></UL><P><SPAN>The code is available&nbsp;</SPAN>here: <A href="https://github.com/SAP-samples/api-management-api-import-utility" target="_blank" rel="noopener nofollow noreferrer">https://github.com/SAP-samples/api-management-api-import-utility</A>.</P><H2 id="toc-hId-403848965">Overview</H2><P>The API import utility was developed by our SAP colleagues&nbsp;<A href="mailto:soumen.ghosh@sap.com" target="_blank" rel="noopener nofollow noreferrer">Soumen Gosh</A>&nbsp;and <A href="mailto:bibin.thomas@sap.com" target="_blank" rel="noopener nofollow noreferrer">Bibin Thomas</A>. It comprises two main components. The<FONT color="#3366FF"> <SPAN>api-import</SPAN> </FONT>code-tree contains the utility’s main class and entry point, in <FONT color="#3366FF"><SPAN>APIImportApplication.java</SPAN></FONT>, and the various functions for intefacing with the SAP API Management catalog.</P><P>The common interface (<FONT color="#3366FF"><SPAN>IRepositoryService</SPAN></FONT>) required by the “factory” in <FONT color="#3366FF"><SPAN>APIDiscoveryFactory.java</SPAN></FONT> is simple, and consists of three functions:</P><P style=" padding-left : 30px; "><FONT color="#3366FF">public <EM>List</EM>&lt;<EM>API</EM>&gt; getListOfApis()</FONT></P><P style=" padding-left : 30px; "><FONT color="#3366FF">public <EM>API</EM> getApi(<EM>String</EM> <EM>apiIdName</EM>)</FONT></P><P style=" padding-left : 30px; "><FONT color="#3366FF">public <EM>APIDefinition</EM> getApiDefinition(<EM>API</EM> <EM>api</EM>)</FONT></P><P>The implementation of these functions for Azure API Management is located in <FONT color="#3366FF"><SPAN>AAMApiRepository.java</SPAN></FONT>, in the <FONT color="#3366FF"><SPAN>AAM</SPAN></FONT> code-tree. The implementation adheres to the API service documented here: <A href="https://learn.microsoft.com/en-us/rest/api/apimanagement/api-management-service" target="_blank" rel="noopener nofollow noreferrer">https://learn.microsoft.com/en-us/rest/api/apimanagement/api-management-service</A>.</P><P>The following simplified illustration demonstrates the main flow:</P><P style=" padding-left : 30px; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="chaimbendelac_0-1713942707803.png" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/100952i0A069222311B8523/image-size/medium?v=v2&amp;px=400" role="button" title="chaimbendelac_0-1713942707803.png" alt="chaimbendelac_0-1713942707803.png" /></span></P><P><SPAN>The utility fetches the APIs from the Azure API Management and makes them available in SAP API Management as unmanaged APIs. In addition, by default, all imported APIs are added to a new <EM>product</EM> (a grouping of related APIs) called </SPAN><FONT color="#3366FF"><SPAN>AAMProduct</SPAN></FONT><SPAN> (you can change this default name in the </SPAN><FONT color="#3366FF"><SPAN>AAM_product_description.json</SPAN></FONT><SPAN> file in the </SPAN><FONT color="#3366FF"><SPAN>conf</SPAN></FONT><SPAN> folder). </SPAN></P><H2 id="toc-hId-207335460">Building the code</H2><OL><LI>At the root of the code-tree, execute: <SPAN><FONT color="#3366FF">mvn clean install</FONT><BR /><BR /></SPAN><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="chaimbendelac_1-1713942707804.png" style="width: 474px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/100950i1DA72EB9B5B3D156/image-dimensions/474x90?v=v2" width="474" height="90" role="button" title="chaimbendelac_1-1713942707804.png" alt="chaimbendelac_1-1713942707804.png" /></span><SPAN><BR /><BR /></SPAN></LI><LI>This creates a runtime folder: <FONT color="#3366FF"><SPAN>./target/app</SPAN></FONT> with two subfolders, <FONT color="#3366FF"><SPAN>lib</SPAN> </FONT>and <FONT color="#3366FF"><SPAN>conf</SPAN></FONT>.</LI></OL><P>&nbsp;</P><H2 id="toc-hId-10821955">Preparing Access to Azure API Management</H2><P><SPAN>Access to Azure API Management requires</SPAN> an Azure API Management account and the appropriate roles. You will need an Azure Entra ID (formerly known as Azure AD) service principal (for more information, see <A href="https://learn.microsoft.com/en-us/purview/create-service-principal-azure" target="_blank" rel="noopener nofollow noreferrer">https://learn.microsoft.com/en-us/purview/create-service-principal-azure</A>).</P><P>The command to create a service principal and configure its access to Azure resources is as follows:</P><P style=" padding-left : 30px; "><FONT color="#3366FF">az ad sp create-for-rbac --scopes /subscriptions/&lt;subscriptionId&gt; --role Contributor</FONT></P><P>For more information, see <A href="https://learn.microsoft.com/en-us/cli/azure/ad/sp?view=azure-cli-latest#az-ad-sp-create-for-rbac" target="_blank" rel="noopener nofollow noreferrer">https://learn.microsoft.com/en-us/cli/azure/ad/sp?view=azure-cli-latest#az-ad-sp-create-for-rbac</A></P><P>The command response will be something like this:</P><P style=" padding-left : 30px; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="chaimbendelac_4-1713943515861.png" style="width: 616px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/100961i035F0836F7DBB500/image-dimensions/616x196?v=v2" width="616" height="196" role="button" title="chaimbendelac_4-1713943515861.png" alt="chaimbendelac_4-1713943515861.png" /></span></P><P>Save this response in a file called <FONT color="#3366FF"><SPAN>AAM_connection_details.json</SPAN></FONT>, in the <FONT color="#3366FF"><SPAN>conf</SPAN></FONT> folder created in the build step above (replace the existing file placeholder).</P><P>&nbsp;</P><H2 id="toc-hId--185691550">Prepare access to the SAP API management catalog</H2><P>Accessing SAP API management requires access to an SAP Business Technology Platform (BTP) subaccount, with an installed tenant of the SAP Integration Suite with activated API Management. You will need to generate a service key, which provides trusted access to the public APIs of SAP’s API Management. This process is explained here: <A href="https://help.sap.com/docs/integration-suite/sap-integration-suite/api-access-plan-for-api-portal" target="_blank" rel="noopener noreferrer">https://help.sap.com/docs/integration-suite/sap-integration-suite/api-access-plan-for-api-portal</A> . The resulting service key looks like this:</P><P style=" padding-left : 30px; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="chaimbendelac_5-1713943655921.png" style="width: 450px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/100963iF363B5EC1B7EDE94/image-dimensions/450x108?v=v2" width="450" height="108" role="button" title="chaimbendelac_5-1713943655921.png" alt="chaimbendelac_5-1713943655921.png" /></span></P><P>Save this result as a file called <FONT color="#3366FF"><SPAN>SAP_service_key.json</SPAN></FONT>, in the same <FONT color="#3366FF"><SPAN>conf</SPAN> </FONT>folder created above (replace the existing file placeholder).<BR /><SPAN>&nbsp;</SPAN></P><H2 id="toc-hId--382205055"><SPAN>Running the API import utility</SPAN></H2><P><SPAN>From the </SPAN><SPAN>app</SPAN><SPAN> folder, execute:</SPAN></P><P style=" padding-left : 30px; "><FONT color="#3366FF"><SPAN>java -cp api-import.jar;lib/* com.apimgmt.gateway.APIImportApplication</SPAN></FONT></P><P><SPAN>The utility fetches the APIs and makes them available in SAP API Management as unmanaged APIs. In addition, by default, all imported APIs are added into a new product (a grouping of related APIs) called </SPAN><FONT color="#3366FF"><SPAN>AzureAPIs</SPAN></FONT><SPAN>. </SPAN></P><P style=" padding-left : 30px; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="chaimbendelac_2-1713942707809.png" style="width: 706px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/100951i7F2D6AF0643033D2/image-dimensions/706x83?v=v2" width="706" height="83" role="button" title="chaimbendelac_2-1713942707809.png" alt="chaimbendelac_2-1713942707809.png" /></span></P><P><SPAN>It is up to you to decide if you want to take additional steps, such as adding an API proxy for any of the imported APIs.</SPAN></P><P><SPAN>Developers browsing the SAP API Management API catalog will see a new product tile representing this product grouping:</SPAN></P><P style=" padding-left : 30px; "><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="chaimbendelac_3-1713942707820.png" style="width: 339px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/100953iD0F7EE1FAAE14884/image-dimensions/339x240?v=v2" width="339" height="240" role="button" title="chaimbendelac_3-1713942707820.png" alt="chaimbendelac_3-1713942707820.png" /></span></P><H2 id="toc-hId--578718560"><SPAN>Conclusion</SPAN></H2><P>The API catalog of SAP API Management serves as a centralized listing for APIs managed across distributed and private-cloud API Gateways. The blog demonstrates how to seamlessly list “externally managed” APIs from various sources, enhancing them to conform to organizational security and compliance standards, and providing a consistent URL schema for all APIs.</P><P>The integration of APIs from SAP API Management with those from other gateways or repositories allows for the creation of intricate, distributed application architectures while preserving the vital role of a centralized API catalog.</P><P>&nbsp;</P><H2 id="toc-hId--775232065">Contacts</H2><P><A href="mailto:soumen@sap.com" target="_blank" rel="noopener nofollow noreferrer">soumen.gosh@sap.com</A>, <A href="mailto:chaim@sap.com" target="_blank" rel="noopener nofollow noreferrer">chaim.bendelac@sap.com,&nbsp;</A><A href="mailto:martin@microsoft.com" target="_blank" rel="noopener nofollow noreferrer">mapankra@microsoft.com</A></P> 2024-04-25T17:02:14.909000+02:00 https://community.sap.com/t5/technology-blogs-by-members/govern-sap-apis-living-in-various-api-management-gateways-in-a-single-place/ba-p/13682483 Govern SAP APIs living in various API Management gateways in a single place with Azure API Center 2024-04-26T12:33:48.591000+02:00 Martin-Pankraz https://community.sap.com/t5/user/viewprofilepage/user-id/143781 <TABLE border="1" width="100%"><TBODY><TR><TD width="100%"><P><EM>Find the GitHub repos associated with this post on Azure API Center </EM><SPAN><A href="https://github.com/Azure-Samples/azd-apic-sap/" target="_blank" rel="noopener nofollow noreferrer"><EM>here</EM></A></SPAN><EM>.</EM></P><P><EM><SPAN>Our engineering friends from SAP Integration Suite– in particular <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/194397">@Chaim_Bendelac</a>&nbsp; – published a nice “sister blog” on supporting Azure API Management with the API Management capability of SAP Integration Suite </SPAN></EM><SPAN><A href="https://community.sap.com/t5/technology-blogs-by-sap/supporting-multiple-api-gateways-with-sap-api-management-using-azure-api/ba-p/13680433" target="_blank"><EM>here</EM></A><EM>.</EM></SPAN></P></TD></TR></TBODY></TABLE><P><SPAN>Dear community,</SPAN></P><P><SPAN>Many of you are heavily invested in APIs regarding your SAP ecosystem and the rest of your IT real estate. Given the integration specialization in the SAP space companies decide to use more than one integration tool to cater for SAP and non-SAP integrations. <A href="https://www.gartner.com/en/documents/3968032" target="_blank" rel="noopener nofollow noreferrer">Gartner</A> even says that 75% will use at least two different ones. For many of you that means SAP Integration Suite plus one for non-SAP.</SPAN></P><P><SPAN>Due to the fast-paced growth of APIs within organizations, inventory, governance, security, and management cannot keep up. The resulting fragmentation and inconsistency lead to adoption challenges, project delays, and security risks. Postman’s <A href="https://www.postman.com/state-of-api/executing-on-apis/#frequency-of-api-security-incidents" target="_blank" rel="noopener nofollow noreferrer">State of APIs report 2023</A> shows that API security incidents happen frequently.</SPAN></P><P><SPAN>These challenges are summed up under the term “API Sprawl” by the industry. Beware the API sprawl monster is upon you!</SPAN></P><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="fig.1 Illustration of API Sprawl challenge" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/101890i296B6772C9A5260E/image-size/medium?v=v2&amp;px=400" role="button" title="_34e58609-ed75-4d35-b822-969302c0ed9c.jpg" alt="fig.1 Illustration of API Sprawl challenge" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">fig.1 Illustration of API Sprawl challenge</span></span></SPAN></P><P><STRONG>Key to survival is automatic discovery</STRONG><SPAN> of available APIs and a single place to enforce guidelines from, or at least know these unmanaged APIs exist in your estate. Forgotten APIs are low hanging fruit for attackers. To drive home that argument: “Improper Inventory Management” made the <A href="https://owasp.org/API-Security/editions/2023/en/0xa9-improper-inventory-management/" target="_blank" rel="noopener nofollow noreferrer">OWASP top 10 list for API Security</A> in 2023.</SPAN></P><P><SPAN>Besides that on the human side of things: Which developer likes to develop duplicate functionality just because of the lack of shared API inventory to discover existing stuff?</SPAN></P><P><SPAN>The API Sprawl monster</SPAN>🦖<SPAN> much hungry! “Nomnom nomnom more food, yes more food!”.</SPAN></P><P><SPAN>Azure API Center embarked on the journey of taming the monster.</SPAN></P><P>&nbsp;</P><H1 id="toc-hId-864366498">What API solutions can be registered to Azure API Center?</H1><P><SPAN>Azure API Center applies to any API and any API management solution out there. Always remember that API Center is not an API Gateway! It doesn’t expose the endpoints or apply policies to them. That stays with the API Management provider. API Center makes them discoverable and allows decorating APIs with additional info to improve governance.</SPAN></P><P><SPAN>Let that sink in.</SPAN></P><P><SPAN>My colleagues are building integrated experiences for the most interesting API and integration tool providers. However, API-based registration in API Center will always be possible.</SPAN></P><P><SPAN>Get it? APIs to register APIs to register APIs ... yah maybe to complicated for a joke.</SPAN></P><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="fig.2 Azure API Center solution coverage overview" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/101888i27D6FD5DB73C6530/image-size/large?v=v2&amp;px=999" role="button" title="apic-overview.png" alt="fig.2 Azure API Center solution coverage overview" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">fig.2 Azure API Center solution coverage overview</span></span></SPAN></P><P><SPAN>The focus of this blog post will be on inventorying APIs hosted by the API Management capability of SAP Integration Suite to mitigate SAP API sprawl. However, the approach described is applicable to all the other SAP APIs out there hosted on SAP Gateway, SAP Graph, SAP CAP, SAP RAP, CloudFoundry, Kyma, etc. too.</SPAN></P><P><SPAN>Another prominent SAP service would be SAP Cloud Integration (formerly CPI – Cloud Platform Integration). Many of you expose APIs internally or to business partners through SAP integration flows without fronting them with an API Management solution – you know who you are </SPAN><span class="lia-unicode-emoji" title=":winking_face:">😉</span><SPAN>.</SPAN><SPAN> Those can be registered too. Unfortunately, there is no built-in option to retrieve the definition of such an endpoint. You may generate an API definition for your http trigger using payload samples for instance. I found <A href="https://gist.github.com/0xdevalias/5fecf0db3bd9cc7465e42616061e1ab0" target="_blank" rel="noopener nofollow noreferrer">this repo</A> useful to get an overview on how to generate OpenAPI definitions from JSON payloads.</SPAN></P><P><SPAN>Even if you don’t, putting the available metadata on the Azure API Center inventory still improves discoverability and enterprise-wide governance by magnitudes.</SPAN></P><P>But now on to SAP API Management.</P><P>&nbsp;</P><H1 id="toc-hId-667852993">Automagically registering SAP API Management APIs on Azure API Center</H1><P>Our starting point is the SAP BTP service <STRONG>apimanagement-devportal</STRONG>. Check SAP’s docs on the setup process <SPAN><A href="https://help.sap.com/docs/integration-suite/sap-integration-suite/api-access-plan-for-api-business-hub-enterprise" target="_blank" rel="noopener noreferrer">here</A>. Make sure you don’t mistakenly choose apimanagement-apiportal.</SPAN></P><P>The API “<SPAN><A href="https://api.sap.com/api/DevPortal_DiscoveryService_CF/resource/APIs" target="_blank" rel="noopener noreferrer">API Business Hub Enterprise - Discovery Service (CF)</A>” enables querying all available APIs hosted on SAP API Management on that subaccount. It holds info about their OpenAPI definitions.</SPAN></P><P><SPAN>Authenticate on the service with any of the <A href="https://help.sap.com/docs/sap-api-management/sap-api-management/api-access-plan-for-api-business-hub-enterprise?version=Cloud#create-a-service-key" target="_blank" rel="noopener noreferrer">supported authentication mechanisms</A>. I chose OAuth2 client credentials grant (instance secret – without payload).</SPAN></P><P><SPAN>See below response from “/apidiscovery/v1/apis” from my SAP BTP sandbox environment. Pay attention to the attributes of “apiDefinitions” and values for “oas-json”.</SPAN></P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-json"><code>{ "@odata.context": "$metadata#apis", "value": [ { "name": "GWSAMPLE_BASIC", "title": "GWSAMPLE_BASIC", "version": "1", "lastUpdated": "2024-01-24", "releaseStatus": "PUBLIC", "protocol": "ODATAV2", "entryPoints": [ { "name": "GWSAMPLE_BASIC", "type": "PROD", "url": "https://msftapim.test.apimanagement.eu10.hana.ondemand.com:443/GWSAMPLE_BASIC" } ], "apiDefinitions": [ { "type": "oas-json", "url": "https://eu10devportal.cfapps.eu10.hana.ondemand.com/odata/1.0/data.svc/APIMgmt.APIResourceDocumentations('2797A5F5-E18A-4FCC-826A-C833845303F5')/content/$value" }, { "type": "edmx", "url": "https://msftapim.test.apimanagement.eu10.hana.ondemand.com:443/GWSAMPLE_BASIC/$metadata" } ] }</code></pre><P>&nbsp;</P><P>&nbsp;</P><P><SPAN>For your convenience we have provided a <A href="https://github.com/Azure-Samples/azd-apic-sap/" target="_blank" rel="noopener nofollow noreferrer">sample repo</A> that runs Infrastructure-as-Code scripting to register the SAP APIs using their OpenAPI definitions as highlighted above. On each SAP API definition we execute registration requests on Azure API Center.</SPAN></P><P><SPAN>You may also use Postman, or SAP Build Process Automation etc. to execute the REST API calls if you prefer. Find our collection <A href="https://github.com/Azure-Samples/azd-apic-sap/blob/main/sap-apim-scan.http" target="_blank" rel="noopener nofollow noreferrer">here</A>.</SPAN></P><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="fig.3 Flow of automated API registration in Azure API Center" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/101894i6B0E80481BFFF330/image-size/large?v=v2&amp;px=999" role="button" title="apic-register-flow.png" alt="fig.3 Flow of automated API registration in Azure API Center" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">fig.3 Flow of automated API registration in Azure API Center</span></span></SPAN></P><H1 id="toc-hId-471339488">Discover all your APIs where you code – see VS Code and GitHub Copilot in action</H1><P><SPAN>We developers like to stay within our flow. So, having the API inventory available at my fingertips in VSCode is a good step into that direction. Also generating http requests to poke around the service and API clients is nice </SPAN><span class="lia-unicode-emoji" title=":smiling_face_with_sunglasses:">😎</span><SPAN><A href="https://github.com/microsoft/kiota" target="_blank" rel="noopener nofollow noreferrer">Kiota</A></SPAN> supports a multitude of languages for SDK generation.</P><P><SPAN>To get that going install the <A href="https://learn.microsoft.com/azure/api-center/use-vscode-extension" target="_blank" rel="noopener nofollow noreferrer">Azure API Center portal VSCode extension</A>.</SPAN></P><P><SPAN><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%2F62X0NALedCc%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D62X0NALedCc&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F62X0NALedCc%2Fhqdefault.jpg&amp;key=b0d40caa4f094c68be7c29880b16f56e&amp;type=text%2Fhtml&amp;schema=youtube" width="400" height="225" scrolling="no" title="Introducing the VS Code extension for Azure API Center" frameborder="0" allow="autoplay; fullscreen; encrypted-media; picture-in-picture;" allowfullscreen="true"></iframe></div></SPAN></P><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="fig.4 Screenshot of VSCode extension with example OpenAPI definition" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/101895i0F90ED42F7A3F97B/image-size/large?v=v2&amp;px=999" role="button" title="apic-vsc-ext.png" alt="fig.4 Screenshot of VSCode extension with example OpenAPI definition" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">fig.4 Screenshot of VSCode extension with example OpenAPI definition</span></span></SPAN></P><P><SPAN>Please note that the authorize button (and respective authentication scheme) on the OpenAPI definition explorer is only available if present on the definition file. It looks like this for Basic Auth:</SPAN></P><P><SPAN><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="fig.5 Screenshot of auth definition in example OpenAPI spec for SAP OData service" style="width: 400px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/101896i185F2B5F860C6AF7/image-size/medium?v=v2&amp;px=400" role="button" title="apic-vsc-ext1.png" alt="fig.5 Screenshot of auth definition in example OpenAPI spec for SAP OData service" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">fig.5 Screenshot of auth definition in example OpenAPI spec for SAP OData service</span></span></SPAN></P><P>W<SPAN>hen using the http file and the <A href="https://marketplace.visualstudio.com/items?itemName=humao.rest-client" target="_blank" rel="noopener nofollow noreferrer">REST client extension</A> of your choice, you may simply provide the authentication header with Bearer token etc.</SPAN></P><P><SPAN>Next to the Azure API Center extension view before, you can also use <A href="https://learn.microsoft.com/azure/api-center/use-vscode-extension-copilot" target="_blank" rel="noopener nofollow noreferrer">GitHub Copilot Chat</A> to query available APIs from API Center. See <A href="https://learn.microsoft.com/azure/api-center/use-vscode-extension-copilot#search-for-apis-using-github-copilot-chat" target="_blank" rel="noopener nofollow noreferrer">Microsoft Learn</A> for more samples. You may search for APIs by key words like so:</SPAN></P><P>&nbsp;</P><P>&nbsp;</P><pre class="lia-code-sample language-bash"><code>@apicenter /search business-partner</code></pre><P>&nbsp;</P><P>&nbsp;</P><P><SPAN>Cherry on the cake </SPAN><span class="lia-unicode-emoji" title=":shortcake:">🍰</span>is the <SPAN><A href="https://learn.microsoft.com/azure/api-center/enable-api-center-portal" target="_blank" rel="noopener nofollow noreferrer">API Center portal</A></SPAN> for the classic developer portal experience across your whole registered API inventory wherever that is.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="fig.6 Screenshot of Azure API Center portal API inventory view" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/101898iFEE25F515A582F66/image-size/large?v=v2&amp;px=999" role="button" title="apic-portal.png" alt="fig.6 Screenshot of Azure API Center portal API inventory view" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">fig.6 Screenshot of Azure API Center portal API inventory view</span></span></P><P><SPAN>So far so good on registering APIs and working off the info their definitions provide. But how about governance? I know how desperately everyone wants to plaster cost centers, line-of-business info, and security labels on your interfaces. </SPAN><span class="lia-unicode-emoji" title=":smirking_face:">😏</span></P><P>&nbsp;</P><H1 id="toc-hId-274825983">Enforced API metadata is your second line of defense against API sprawl</H1><P><SPAN>In addition to simply registering APIs you may add custom properties to the object on Azure API Center. So, even if the info is not present on the API itself you can still govern it from Azure. See below sample that I created from the <A href="https://learn.microsoft.com/azure/api-center/add-metadata-properties" target="_blank" rel="noopener nofollow noreferrer">Microsoft Learn tutorial</A>.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="fig.7 Screenshot of Azure API Center metadata maintenance view" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/101899i08A674038B335754/image-size/large?v=v2&amp;px=999" role="button" title="apic-custom-props.png" alt="fig.7 Screenshot of Azure API Center metadata maintenance view" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">fig.7 Screenshot of Azure API Center metadata maintenance view</span></span></P><P><SPAN>Knowing which APIs are public facing is useful, isn’t it?</SPAN></P><P><SPAN>For everyone looking for more sophisticated security with less human error surface, have a look at <A href="https://learn.microsoft.com/azure/defender-for-cloud/defender-for-apis-introduction" target="_blank" rel="noopener nofollow noreferrer">Defender for APIs</A>. I like the alert rule for “un-authenticated APIs” and disabling endpoints that were not used in the past 60 days most – wait what? Those exist out there in the wild west of SAP on the Internet? </SPAN><span class="lia-unicode-emoji" title=":astonished_face:">😲</span>See the open-source automatic remediations repos <SPAN><A href="https://github.com/Azure/Microsoft-Defender-for-Cloud/tree/main/Workflow%20automation/Defender%20for%20API" target="_blank" rel="noopener nofollow noreferrer">here</A></SPAN> to mitigate for Azure API Management.</P><P>Defender for API integration with <SPAN><A href="https://learn.microsoft.com/azure/defender-for-cloud/onboarding-guide-42crunch" target="_blank" rel="noopener nofollow noreferrer">42Crunch</A></SPAN> brings API security testing and hardening to your CI/CD pipeline.</P><P>&nbsp;</P><H1 id="toc-hId-78312478">API Linting gets you to the next level</H1><P><SPAN>OK, now let’s look at API style guide compliance. Is everyone playing by your rules? How do you make sure developers notice violations already during design phase rather than at later stages of deployment, release, or even months after the fact when audited?</SPAN></P><P><SPAN>Good automatic <A href="https://thenewstack.io/improve-the-quality-of-your-apis-with-spectral-linting/" target="_blank" rel="noopener nofollow noreferrer">API linting</A> creates much less hassle for everyone in the long run, less cost to fix API definitions after the fact, improved security posture, and a more rewarding experience for the people involved. See below video on the setup of the linting function for OpenAPI using <A href="https://github.com/stoplightio/spectral/blob/develop/docs/reference/openapi-rules.md" target="_blank" rel="noopener nofollow noreferrer">Spectral linting engine</A>.</SPAN></P><P><SPAN>Anyone aware of a great OData linter and would be curious to explore? Please share!</SPAN></P><P><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%2Fm0XATQaVhxA%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dm0XATQaVhxA&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fm0XATQaVhxA%2Fhqdefault.jpg&amp;key=fad07bfa4bd747d3bdea27e17b533c0e&amp;type=text%2Fhtml&amp;schema=youtube" width="400" height="225" scrolling="no" title="Mastering API Governance with Azure API Center" frameborder="0" allow="autoplay; fullscreen; encrypted-media; picture-in-picture;" allowfullscreen="true"></iframe></div></P><P><SPAN>Get more details on API Linting for Azure API Center from <A href="https://learn.microsoft.com/azure/api-center/enable-api-analysis-linting?tabs=portal" target="_blank" rel="noopener nofollow noreferrer">this Microsoft Learn article</A>.</SPAN></P><P>&nbsp;</P><H1 id="toc-hId--118201027">Thoughts on production readiness</H1><P><SPAN>Azure API Center is in public preview but due for General Availability with the next wave of announcements, so completely ready for prime time. The same is true for the VS Code extensions and APIs used to orchestrate the integration between SAP API Management and Azure.</SPAN></P><P><SPAN>Intentionally registering APIs from SAP to Azure API Center improves API inventory management by magnitudes. However, shadow inventory thrives in places you don’t actively look. To mitigate even more effectively the team is building automated discovery from your GitHub org, Azure DevOps, and other popular sources.</SPAN></P><P><SPAN><A href="https://marketplace.visualstudio.com/items?itemName=SAPSE.sap-ux-fiori-tools-extension-pack" target="_blank" rel="noopener nofollow noreferrer">SAP Fiori tools</A> on VSCode provided by SAP SE enable usage of the approach described in this blog out of the box. The same is true for <A href="https://developers.sap.com/tutorials/btp-app-prepare-dev-environment-cap.html" target="_blank" rel="noopener noreferrer">SAP CAP development</A> in VSCode.</SPAN></P><P>&nbsp;</P><H1 id="toc-hId--314714532">Final words</H1><P><SPAN>That’s a wrap</SPAN><span class="lia-unicode-emoji" title=":burrito:">🌯</span>. You saw today how you can effectively <STRONG>counter API sprawl</STRONG> and its negative side effects that put your APIs and organizations at risk. A primary means to achieve that is <STRONG>creating a central API inventory </STRONG>hosted on all the different API Management solutions out there <STRONG>with Azure API Center</STRONG>.</P><P>This blog showed how to achieve that using the API Management capability of SAP Integration Suite as an example.</P><P>Furthermore, you learned about steps to improve API governance with custom properties and API linting. Eventually, you understood the difference between Azure API Center and an API Gateway.</P><P>Find the GitHub repos associated with this post <SPAN><A href="https://github.com/Azure-Samples/azd-apic-sap/" target="_blank" rel="noopener nofollow noreferrer">here</A></SPAN>. It gets you started in no time.</P><P>Big #Kudos to <SPAN><A href="https://www.linkedin.com/in/pascalvdheiden/" target="_blank" rel="noopener nofollow noreferrer">Pascal van der Heiden</A></SPAN> – my brother in crime on this effort. And of course, last but not least to&nbsp;<a href="https://community.sap.com/t5/user/viewprofilepage/user-id/8446">@UdoPaltzer</a>&nbsp;and <a href="https://community.sap.com/t5/user/viewprofilepage/user-id/216068">@vinayak_adkoli</a>&nbsp;for the great collaboration! <span class="lia-unicode-emoji" title=":raising_hands:">🙌</span></P><P>Anyone curious to tap their toe into the waters where the API sprawl monster 🦖 lives, just reach out to me and Chaim or leave a comment.</P><P>Cheers</P><P>Martin</P> 2024-04-26T12:33:48.591000+02:00 https://community.sap.com/t5/technology-blogs-by-sap/api-management-unlocking-oauth-strategies/ba-p/13682686 API Management: Unlocking OAuth Strategies 2024-04-30T15:30:43.947000+02:00 Avinash_Vaidya https://community.sap.com/t5/user/viewprofilepage/user-id/120687 <H2 id="toc-hId-993451142">Introduction</H2><P><SPAN>In today's rapidly evolving enterprise landscape, the API-first approach has emerged as a cornerstone for organizations striving to stay competitive and relevant. At the heart of this approach lies API management, a central place for the orchestration, optimization, and security of APIs.</SPAN></P><P><SPAN>In this blog, I will elaborate the authorization considerations surrounding APIs, as well as the OAuth strategies I've investigated and encountered during my learning journey and professional experience.</SPAN></P><P>If you are new to API management I highly recommend going through the help doc to get basic knowledge of <A href="https://help.sap.com/docs/integration-suite/sap-integration-suite/api-management-capability" target="_self" rel="noopener noreferrer">API management</A> capability before diving into this blog.</P><P>Through out the blog, I have added links to some learning journeys / blogs which you can refer. I thought this is better instead of rewriting the same content which is already well written.</P><P><SPAN>I will structure the blog in below sections</SPAN></P><OL><LI><SPAN>Pre-requisites</SPAN></LI><LI><SPAN>Creating a simple integration flow</SPAN></LI><LI><SPAN>Securing integration flows</SPAN><OL><LI>Exploring API Management OAuth Policy</LI><LI>Extending OAuth Beyond API Management</LI></OL></LI><LI>Testing steps to test both solution approaches.</LI><LI>Conclusion</LI></OL><H3 id="toc-hId-926020356">Pre-requisites</H3><OL><LI>SAP BTP account or trail account</LI><LI>Integration Suite Tenant with below capabilities<OL><LI>Cloud Integration</LI><LI>API Management (ensure you have proper roles assigned)</LI></OL></LI><LI>Process Integration Runtime service</LI><LI>Insomnia or Postman client</LI></OL><H3 id="toc-hId-729506851"><SPAN>Creating simple integration flow</SPAN></H3><P><SPAN>I created a simple integration flow and deployed it as a REST API in the cloud integration tenant. This integration flow does following things</SPAN></P><P><SPAN>1. Logs the incoming message as attachment</SPAN></P><P><SPAN>2. Persists the message in JMS queue</SPAN></P><P><SPAN>Note - This is the basic integration flow. Consider it as a mock iflow which can be replaced by any other iflow based on the business use case.</SPAN></P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="Figure-1: Integration Flow" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/101983iC831FA2AFB7589BD/image-size/large?v=v2&amp;px=999" role="button" title="Screenshot 2024-04-25 at 13.49.55.png" alt="Figure-1: Integration Flow" /><span class="lia-inline-image-caption" onclick="event.preventDefault();">Figure-1: Integration Flow</span></span></P><H3 id="toc-hId-532993346"><SPAN>Securing integration flows&nbsp;</SPAN></H3><P><SPAN>In an enterprise landscape, you will always come across situations, that you have to expose your integration flows using API management. Ofcourse Integration suite provides API management capability which can seamlessly wrap the integration flows and create an API proxy.</SPAN></P><P><SPAN>One of the important question always comes up - How to secure your APIs/iflows? The obvious answer is OAuth 2.0 (Open Authorization 2.0)</SPAN><SPAN>.</SPAN></P><P><SPAN>Here I will showcase, 2 solution approaches to secure the API with OAuth 2.0.&nbsp;</SPAN></P><OL><LI><STRONG>Exploring API Management OAuth Policy: </STRONG>API Management provides security policies which can be used out of the box.<OL><LI>Create an API Proxy. Configure -- APIs -- <EM>OAuthService. </EM>This Service will be used to generate the token. Follow Step 1 (<STRONG>1 -&nbsp;Create the Token Endpoint</STRONG>) from this <A href="https://community.sap.com/t5/technology-blogs-by-sap/oauth-with-sap-api-management-hcp-part-1/ba-p/13308651" target="_self">blog</A></LI><LI>Create another API - LogMessageAPI as a proxy to the iflow. We will add token validation in this proxy.&nbsp;Define the API by referring the <A href="https://developers.sap.com/tutorials/cp-starter-isuite-api-management.html#e0dd55ad-6cc8-444e-ac59-18186bdae5c9" target="_self" rel="noopener noreferrer">Step 2: Define the API</A> from this learning journey.</LI><LI>In the LogMessageAPI:<BR /><OL><LI><SPAN><SPAN><SPAN><SPAN><SPAN>Add policy template to the LogMessageAPI as mentioned in Step 3, 4 and 5 of this <A href="https://developers.sap.com/tutorials/cp-starter-isuite-api-management.html#a363dcee-8544-44ca-b43b-cda9b363a9e3" target="_self" rel="noopener noreferrer">learning journey</A></SPAN></SPAN></SPAN></SPAN></SPAN></LI><LI><SPAN><SPAN><SPAN><SPAN><SPAN>Add VerifyAccessToken&nbsp;policy as the first policy in the pre-flow of the&nbsp;ProxyEndpoint using OAuthV2 in the LogMessageAPI proxy.</SPAN></SPAN></SPAN></SPAN></SPAN> <TABLE border="1" width="100%"><TBODY><TR><TD width="100%"><PRE>&lt;OAuthV2 async="false" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt"&gt; &lt;!-- this flag has to be set when you want to work with third-party access tokens --&gt; &lt;ExternalAuthorization&gt;false&lt;/ExternalAuthorization&gt; &lt;!-- valid values are GenerateAccessToken, GenerateAccessTokenImplicitGrant, GenerateAuthorizationCode , RefreshAccessToken , VerifyAccessToken , InvalidateToken , ValidateToken --&gt; &lt;Operation&gt;VerifyAccessToken&lt;/Operation&gt; &lt;GenerateResponse enabled="true"/&gt;&lt;SupportedGrantTypes/&gt; &lt;Tokens/&gt; &lt;/OAuthV2&gt;</PRE></TD></TR></TBODY></TABLE></LI></OL></LI><LI>Once you deploy the OAuthService and LogMessageAPI and publish the product to <STRONG>API Business Hub Enterprise,&nbsp;</STRONG>you will get the application key and application secret which can be used as client id and client secret to get the token.</LI><LI>In this way, you can use the inbuilt OAuth policy to generate the OAuth token and to validate the token for other API proxies.</LI></OL></LI><LI><STRONG>Extending</STRONG><SPAN>&nbsp;</SPAN><STRONG>OAuth Beyond API Management:&nbsp;</STRONG>Let us dive deeper into another approach where we can use the process integration runtime OAuth server to generate the token through OAuthService API.&nbsp;<OL><LI>Create an API Proxy. Configure -- APIs -- <EM>OAuthService.</EM></LI><LI>Import the policy template in the&nbsp;pre-flow of the&nbsp;ProxyEndpoint. I have exported my policy template and is available in GitHub -&nbsp;<A href="https://github.com/avinashvaidya09/apimanagementpolicytemplate" target="_blank" rel="noopener nofollow noreferrer">https://github.com/avinashvaidya09/apimanagementpolicytemplate</A>&nbsp;</LI><LI>Each policy is listed and briefly described below -&nbsp;<OL><LI><STRONG>lookupOAuthToken</STRONG> - Using LookupCache policy, checks if access token is available in cache.</LI><LI><STRONG>extractRequestHeader</STRONG> - Using ExtractVariables policy, extracts the client id and client secret from the request headers.</LI><LI><STRONG>getBTPOAuthMetadata</STRONG> - Using KeyValueMapOperations policy, finds the BTP oauth token url saved in the key value map</LI><LI><STRONG>setAuthorization</STRONG> - Using BasicAuthentication policy, creates Authorization object.</LI><LI><STRONG>callBTPOAuthService</STRONG> - Using ServiceCallout policy, calls external BTP OAuth token url.</LI><LI><STRONG>raiseException</STRONG> - Using raiseException policy, raises exception if BTP OAuth token url returns exception.</LI><LI><STRONG>extractVariablesFromOAuthResponse</STRONG> - Using ExtractVariables policy, extracts token response.</LI><LI><STRONG>populateOAuthToken</STRONG> - Using PopulateCache policy, populates access token in cache which will be used by point 1.</LI></OL></LI><LI>Go to your BTP subaccount -- Create instance of Process Integration Runtime.</LI><LI>Create a service key and get the OAuth metadata<OL><LI>client id</LI><LI>client secret</LI><LI>token url</LI></OL></LI><LI>Add the token url in the key value map in API configuration to make it externalized. This token url will be used in the service call out policy - <STRONG>callBTPOAuthService</STRONG></LI><LI>Save and and deploy the OAuthService.</LI><LI>Ensure the integration flow is deployed. Get the endpoint URL.</LI><LI>Create another API - LogMessageAPI as a proxy to the iflow.&nbsp;Define the API by referring the <A href="https://developers.sap.com/tutorials/cp-starter-isuite-api-management.html#e0dd55ad-6cc8-444e-ac59-18186bdae5c9" target="_self" rel="noopener noreferrer">Step 2: Define the API</A> from this learning journey.</LI><LI>In this API, you do not have to define any access token validation policy, but the bearer token will be forwarded to the integration flow and will be validated directly by process integration runtime.</LI></OL></LI></OL><H3 id="toc-hId-336479841"><SPAN>Test your APIs</SPAN></H3><UL class="lia-list-style-type-square"><LI><SPAN>Download any REST client like - Insomnia or Postman.</SPAN></LI><LI><SPAN>Deploy the API proxies and get the endpoints</SPAN></LI></UL><OL><LI><STRONG>Testing approach - 1:</STRONG><BR /><OL><LI><SPAN>Go to&nbsp;<STRONG>API Business Hub Enterprise.&nbsp;</STRONG>Create Application and add the product containing both the API proxies.</SPAN></LI><LI><SPAN>Get the application secret and application key after the application is created.</SPAN></LI><LI><SPAN>Create new HTTP request for API proxy&nbsp;OAuthService endpoint.</SPAN></LI><LI><SPAN>Add client id - client id will be the application key from point 2.</SPAN></LI><LI><SPAN>Add client secret -&nbsp;client secret will be the application secret from point 2.&nbsp;</SPAN></LI><LI>Add grant type - client_credentials</LI><LI>Add Content-Type -&nbsp;application/x-www-form-urlencoded</LI><LI>Get the access token.</LI><LI><SPAN>Create new HTTP request with API management LogMessageAPI endpoint.&nbsp;</SPAN><OL><LI><SPAN>Add access token</SPAN></LI><LI><SPAN>Add sample JSON payload</SPAN></LI></OL></LI><LI><SPAN>Execute the request.</SPAN></LI><LI><SPAN>Go to integration suite - Monitor - Integration &amp; APIs. You should see a message in the queue. Click on the message id and you will land on the executed iflow with payload attached for reference.</SPAN></LI></OL></LI><LI><STRONG>Testing approach - 2:</STRONG><OL><LI><SPAN>Create new HTTP request with API management OAuthService endpoint.</SPAN></LI><LI><SPAN>Add client id - client id from process integration runtime service key.</SPAN></LI><LI><SPAN>Add client secret -&nbsp;client secret from process integration runtime service key.</SPAN></LI><LI><SPAN>Content-Type - application/x-www-form-urlencoded</SPAN></LI><LI><SPAN>Get the access token</SPAN></LI><LI><SPAN>Create new HTTP request with API management LogMessageAPI endpoint.&nbsp;</SPAN><OL><LI><SPAN>Add access token</SPAN></LI><LI><SPAN>Add sample JSON payload</SPAN></LI></OL></LI><LI><SPAN>Execute the request.</SPAN></LI><LI><SPAN>Go to integration suite - Monitor - Integration &amp; APIs - Message Queues. You should see a messages in the queue. Click on the message id and you will land on the executed iflow with payload attached for reference.</SPAN></LI></OL></LI></OL><H3 id="toc-hId-139966336"><SPAN>Conclusion</SPAN></H3><P><SPAN>Drawing from my experience, I must emphasize that these insights can serve as a starting point, though their applicability may vary based on specific scenarios.</SPAN></P><P><SPAN>This is just a glimpse of wide set of capabilities offered by SAP Integration Suite and API management. Stay curious! Keep learning!</SPAN></P><P><SPAN>To get more updates about this topic, please follow the below pages<BR /></SPAN></P><UL><LI><A href="https://help.sap.com/docs/integration-suite?locale=en-US" target="_blank" rel="noopener noreferrer">SAP Integration Suite</A></LI><LI><A href="https://help.sap.com/docs/integration-suite/sap-integration-suite/api-management-capability?q=API%20Management" target="_self" rel="noopener noreferrer">API Management</A></LI><LI><A href="https://community.sap.com/t5/c-khhcw49343/SAP+Integration+Suite/pd-p/73554900100800003241" target="_self">Blogs</A></LI></UL><P><STRONG>Feel free to “<EM>like</EM>“, “<EM>Share</EM>“, “<EM>Add a Comment</EM>” and to get more updates about my next blogs follow me –&nbsp;<SPAN class=""><A href="mailto:avinash.vaidya@sap.com" target="_blank" rel="noopener nofollow noreferrer">avinash.vaidya@sap.com</A>&nbsp;</SPAN></STRONG></P> 2024-04-30T15:30:43.947000+02:00 https://community.sap.com/t5/technology-blogs-by-members/sap-pipeline-concept-and-b2b-tpm-testing/ba-p/13691706 SAP Pipeline Concept and B2B TPM testing 2024-05-06T07:30:00.023000+02:00 MichalKrawczyk https://community.sap.com/t5/user/viewprofilepage/user-id/45785 <H2 id="toc-hId-994345585">Abstract</H2><P>With the introduction of the <A href="https://help.sap.com/docs/help/90c8ad90cb684ee5979856093efe7462/6e527fb074834af2be2546c6e7e2fa5f.html" target="_self" rel="noopener noreferrer">SAP Pipeline Concept&nbsp;</A>we now have a second large use case apart from B2B-TPM which allows processing different types of messages with a set of predefined generic iflows. This blog will show a few ways how automated testing of such scenarios can be set up of the box with Int4 Shield - SAP Integration Suite testing platform and how SAP Integration Suite customers already use it for such scenarios.</P><H2 id="toc-hId-797832080"><BR />SAP Pipeline Concept and B2B TPM - multiple iflows</H2><P>In the pipeline concept, each step corresponds to an integration flow (generic integration flows and scenario-specific integration flows). The generic integration flows are used across all integration scenarios and must only be deployed once while scenario-specific integration flows handle the scenario-specific message conversions and mappings.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="01_Pipelines (1).png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/105886i04E8F60681E158D1/image-size/large?v=v2&amp;px=999" role="button" title="01_Pipelines (1).png" alt="01_Pipelines (1).png" /></span></P><P><FONT size="2">File Source: <A href="https://community.sap.com/t5/technology-blogs-by-sap/introducing-the-new-pipeline-concept-in-cloud-integration/ba-p/13639651" target="_blank">https://community.sap.com/t5/technology-blogs-by-sap/introducing-the-new-pipeline-concept-in-cloud-integration/ba-p/13639651</A></FONT></P><P>Similarly the B2B-TPM the exchange is divided into sender communication iflows, interchange processing and receiver iflows.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="tpm.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/105887i379426ADF6919A86/image-size/large?v=v2&amp;px=999" role="button" title="tpm.png" alt="tpm.png" /></span></P><P><FONT size="2">File source: <A href="https://community.sap.com/t5/technology-blogs-by-sap/use-tpm-ia-ci-to-efficiently-manage-and-run-complex-b2b-transactions/ba-p/13565068" target="_blank">https://community.sap.com/t5/technology-blogs-by-sap/use-tpm-ia-ci-to-efficiently-manage-and-run-complex-b2b-transactions/ba-p/13565068</A></FONT></P><P>Cloud integration is very flexible in terms of modeling and running your integration scenarios allowing the design of a rich variety of integration patterns on the other hand for some types of scenarios we may want to use a more "formal" way or processing and this is there SAP Pipeline Concept and B2B-TPM scenarios come in handy with some of it's common advantages:<BR /><BR />a) Provide commonly used restart capabilities<BR />b) Simplifies operations by separating errors into different generic queues<BR />c) Require lower number of JMS queues to take into account the resource limits<BR />d) Simplify monitoring operations<BR />e) Allow reusability of artifacts across multiple flows by using generic (Pipeline or TPM) iflow concept</P><H2 id="toc-hId-601318575">SAP Pipeline Concept and B2B TPM - testing</H2><P>Since those two frameworks are going to be used more and more and they involve several iflows to be tested<BR />is there any way to automate the testing of such integration processes? With Int4 Shield - SAP Integration Suite testing platform, there out of the box we have several ways to implement automated testing of the SAP Pipeline Concept and B2B TPM. Let me explain, how&nbsp;they work.</P><H3 id="toc-hId-533887789">Step 1</H3><P>In both SAP Pipeline Concept and B2B TPM we're working with multiple iflows so we may want to inject the test messages into a specific iflow. This can be the first iflows but does not have to be as we may want to skip testing the initial iflow in some cases.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="inject_2.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/105888iB8F50A54085F4C96/image-size/large?v=v2&amp;px=999" role="button" title="inject_2.png" alt="inject_2.png" /></span></P><P><FONT size="2">Figure - Int4 Shield inject test message options&nbsp;</FONT></P><H3 id="toc-hId-337374284">Step 2</H3><P>Now we need to decide what do we want to test. What are the options? Basically two:</P><P>a) we can either test the whole framework (SAP Pipeline Concept and B2B TPM ) from start to finish</P><P>b) we may want to test specific iflows of the whole framework (SAP Pipeline Concept and B2B TPM)</P><P>For this purpose Int4 Shield automatically enables Trace monitoring level on tested iFlows to be able to introspect processing inside of these steps.<BR />Thanks to this Int4 Shield can validate payload content at any single execution block of the processing steps.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="both_3.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/105889i10B0D7466D49B7F7/image-size/large?v=v2&amp;px=999" role="button" title="both_3.png" alt="both_3.png" /></span><BR /><FONT size="2">Figure - Int4 Shield inject test message and trace start with validation options&nbsp;</FONT></P><H3 id="toc-hId-140860779">Step 3</H3><P><STRONG>Scenario 1 (single automation object)</STRONG> - for simple black box testing, Int4 Shield injects the message in the initial step and awaits for logs and payload to arrive at the final processing step, capturing the output payload, as it would be sent to a target system. Single test case and single <A href="https://int4support.atlassian.net/wiki/spaces/IUM/pages/2062843993/Automation+Objects" target="_self" rel="nofollow noopener noreferrer">automation object</A> is sufficient for test and validation.</P><P><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="single_4.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/105890i9FCFA739C4957037/image-size/large?v=v2&amp;px=999" role="button" title="single_4.png" alt="single_4.png" /></span></P><P><FONT size="2">Figure - Int4 Shield validation option with a single automation object&nbsp;</FONT></P><P><STRONG>Scenario 2 (combination of automation objects - API workflows testing)</STRONG> - thorough testing is made possible with more test cases that execute more validation steps. In a typical scenario there is separate validation of Step 2 - to check if payload input was properly processed by Step 1 logic, and for Step 3 - to validate the output payload after mapping is correct and routed to the expected channel.<BR /><BR /><span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="double_5.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/105891i352C96B56E571214/image-size/large?v=v2&amp;px=999" role="button" title="double_5.png" alt="double_5.png" /></span><BR /><FONT size="2">Figure - Int4 Shield validation option with a a combination of automation objects - API workflow testing&nbsp;</FONT><BR /><BR /></P><H3 id="toc-hId--55652726">SAP Pipeline Concept and B2B TPM - framework support</H3><P>Int4 Shied testing concept for SAP Pipeline Concept and B2B TPM supports:</P><P>a) Multiple adapter types : SFTP, JMS, HTTP, IDOC, ProcessDirect, SOAP<BR />b) Enabling unit testing of specific flow components<BR />c) Testing business flows with Inputs and Outputs from different iFlows<BR />d) Test complete SAP Pipeline Concept and B2B TPM execution with one test case<BR />e) Capture and test intermediate results from specific iFlow steps<BR />f) Test complete SAP Pipeline Concept and B2B TPM execution, validating document flow through the iFlows<BR />g) Massive and automated test case creation<BR />h) Test case loader - mass load of test files<BR />i) Robotic crawler - automatic capture of historical data from another integration platform<BR />j) Test scenario builder - linking multiple test cases into test scenarios automatically based on message content (e.g. document numbers)</P><H2 id="toc-hId--381248950">Additional resources</H2><P><A href="https://community.sap.com/t5/technology-blogs-by-members/b2b-tpm-on-sap-btp-integration-suite-migration-sap-po-boomi-edi-providers/ba-p/13578709" target="_self">B2B/TPM on SAP BTP Integration Suite migration (SAP PO, Boomi, EDI Providers and home-grown apps)</A></P><P><A href="https://community.sap.com/t5/technology-blogs-by-members/int4-suite-for-sap-btp-integration-suite-testing-fully-integrated-with-sap/ba-p/13554430" target="_self">Int4 Suite for SAP BTP Integration Suite testing fully integrated with SAP Cloud ALM</A>&nbsp;</P><P><A href="https://community.sap.com/t5/enterprise-resource-planning-blogs-by-members/4-big-waves-for-api-led-strategies-and-sap-btp-integration-suite-explosive/ba-p/13629867" target="_self">4 big waves for API led strategies and SAP BTP Integration Suite explosive growth</A>&nbsp;</P><P><A href="https://community.sap.com/t5/enterprise-resource-planning-blogs-by-members/there-is-no-ai-without-api-integration-is-the-backbone-of-digital/ba-p/13626331" target="_self">There is no AI without API - Integration is the backbone of digital transformations</A>&nbsp;</P> 2024-05-06T07:30:00.023000+02:00 https://community.sap.com/t5/spend-management-blogs-by-sap/purchase-order-via-api-purchaseorder-process-srv-example-api-call/ba-p/13700856 Purchase Order via API_PURCHASEORDER_PROCESS_SRV - Example API-call 2024-05-14T14:44:51.633000+02:00 ImreMatyas https://community.sap.com/t5/user/viewprofilepage/user-id/239533 <P>Application Programming Interfaces (APIs) allow developers to interact with SAP Gateway services and perform various operations, including creating, updating, and retrieving data. Through this practical scenario, we aim to shed light on the capabilities of the transaction /n/IWFND/GW_CLIENT and on how to leverage it effectively.</P><P>&nbsp;</P><H2 id="toc-hId-1014634372">Transaction /n/IWFND/GW_CLIENT</H2><P>Upon launching the t-code /n/IWFND/GW_CLIENT you will see a screen composed by three main sections. Above you have the HTTP Request URI where you can give the Service you wish to trigger. On your left side HTTP Request frame gives you the option to place your XML payload with the actual document or query. On the right side, you will see the response from the system after executing that payload.&nbsp;</P><P><span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="14052024_sapblogAPI2.png" style="width: 999px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/110193i6FA097B799295F68/image-size/large?v=v2&amp;px=999" role="button" title="14052024_sapblogAPI2.png" alt="14052024_sapblogAPI2.png" /></span></P><P>&nbsp;</P><P>In our example scenario, we wish to create a Purchase Order through the API service API_PURCHASEORDER_PROCESS_SRV. First the HTTP Method “POST” should be selected, then the Request URI /sap/opu/odata/sap/API_PURCHASEORDER_PROCESS_SRV/A_PurchaseOrder. As a last step, you will have to copy/paste your actual payload into the left frame blank spaces:</P><P><FONT size="2"><EM>{</EM></FONT></P><P><FONT size="2"><EM>&nbsp; "CompanyCode": "0001",</EM></FONT></P><P><FONT size="2"><EM>&nbsp; "PurchaseOrderType": "NB",</EM></FONT></P><P><FONT size="2"><EM>&nbsp; "Supplier": "Your_TestSupplier",</EM></FONT></P><P><FONT size="2"><EM>&nbsp; "DocumentCurrency": "EUR",</EM></FONT></P><P><FONT size="2"><EM>&nbsp; "PurchasingOrganization": "0001",</EM></FONT></P><P><FONT size="2"><EM>&nbsp; "PurchasingGroup": "001",</EM></FONT></P><P><FONT size="2"><EM>&nbsp; "to_PurchaseOrderItem": [</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp; {</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "PurchaseOrderItem": "1",</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "PurchaseOrderItemText": "OData API test",</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Plant": "0001",</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "OrderQuantity": "1",</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "OrderPriceUnit": "EA",</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "AccountAssignmentCategory": "K",</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "PurchaseOrderQuantityUnit": "EA",</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "DocumentCurrency": "EUR",</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "NetPriceAmount": "1",</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "NetPriceQuantity": "1",</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Material": "Your_TestMaterial",</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "to_AccountAssignment": [</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Quantity": "1",</EM></FONT></P><P>&nbsp;</P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "GLAccount": "Your_Test_GL",</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "CostCenter": "Your_Test_CC"</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ]</EM></FONT></P><P><FONT size="2"><EM>&nbsp;&nbsp;&nbsp; }</EM></FONT></P><P><FONT size="2"><EM>&nbsp; ]</EM></FONT></P><P><FONT size="2"><EM>}</EM></FONT></P><P>&nbsp;</P><H2 id="toc-hId-818120867">Debugging the API-call</H2><P>Just like in case of any other HTTP request, the ABAP Debugging of the API-call can be done through external breakpoints. Go to the place you wish to stop the code and place an external breakpoint on the user executing the test scenario.</P><P>In our example a good place to start is the method PO_PROCESS (class CL_PO_HANDLER_MM). This place will call the “normal” SAP Function MEPO_DOC_PROCESS. The include LMEPOF2I, PO_PROCESS will call the subsequent Functions MEPO_DOC_HEADER_PROCESS and MEPO_DOC_ITEM_PROCESS.<BR />In case you have a Badi-specific problem, you could also stop the method IF_FLUSH_TRANSPORT_MM~START (class CL_PO_HEADER_HANDLE_MM). That place will call the BAdI-Functions MEPOBADI_PROCESS_HEADER (implementation IF_EX_ME_PROCESS_PO_CUST~PROCESS_HEADER ) and MEPOBADI_PROCESS_ITEM ( impl. IF_EX_ME_PROCESS_PO_CUST~PROCESS_ITEM ).</P><P>&nbsp;</P><H2 id="toc-hId-621607362">Creating test data for SAP cases</H2><P>In case you wish to save an existing or successfully executed HTTP Request, you can simply click the “Save” button in the upper menu of the transaction. In the next selection screen, you can enter the Test group/Test case name to save your predefined set of data.</P><P>In case you already have a predefined test scenario, you can import it. On the main screen of the transaction /n/IWFND/GW_CLIENT right click in the “Test group” field and hit “Select Test case” or hit the F9 button. It will give you the same selection screen, where you can get your test HTTP request payload.</P><P>Complete XML files can also be added to the HTTP Request if you click “Add File”.</P><P>&nbsp;<span class="lia-inline-image-display-wrapper lia-image-align-center" image-alt="14052024_sapblogAPI1.png" style="width: 772px;"><img src="https://community.sap.com/t5/image/serverpage/image-id/110218i1366AD3E3C71946F/image-size/large?v=v2&amp;px=999" role="button" title="14052024_sapblogAPI1.png" alt="14052024_sapblogAPI1.png" /></span></P><P>&nbsp;</P><H2 id="toc-hId-425093857">Related Content</H2><H3 id="toc-hId-357663071"><SPAN class="">Related SAP Notes/KBAs</SPAN></H3><P>To obtain more information about the structure of the OData Service for Purchase Order please consult our <A href="https://help.sap.com/docs/SAP_S4HANA_CLOUD/99a132748cef4fc198ad4500e3704416/acd2da57df6cc525e10000000a4450e5.html?locale=en-US&amp;version=1705%20500" target="_blank" rel="noopener noreferrer">SAP Help link</A> or see the SAP Knowledge Base Article <A href="https://me.sap.com/notes/3360429" target="_blank" rel="noopener noreferrer"><STRONG>3360429</STRONG> </A>Differences Between OData API V2 API_PURCHASEORDER_PROCESS_SRV and V4 API_PURCHASEORDER [no code inside].</P><P>(Our test scenario is based on S4 Hana version SAPK-10703INS4CORE.)</P> 2024-05-14T14:44:51.633000+02:00