Connecting SAP Business Application Studio to an on-prem python HTTP server and to a SICF ping service

We will do a couple of experiments for testing connectivity from SAP Business Application Studio to on-premise services.

The first experiment will be: test connectivity to an on-prem HTTP server, without needing to have a running SAP system available at all.

The second experiment will be: test connectivity to an on-prem Abap system, using the Ping service from SICF.

This blog assumes that the reader knows how to set up a SAP Cloud Platform trial account, and how to subscribe to Business Application Studio and open it; also assumed is that the reader knows how to install and run SAP Cloud Connector. The usual caveats apply about this not being official documentation and there being no Helpdesk if you are stuck. Good luck though, and if you spot any mistakes, feel free to point those out so we can improve the blog.

[ References for generally getting Destinations to work on SAP CF (CloudFoundry) environment: two very good blogs by Satek Amraotkar on the configuration of CF Destinations for BusinessAppStudio:

https://blogs.sap.com/2020/10/28/setup-sap-business-aapplication-studio-bas-for-developing-sapui5-fiori-like-app-using-on-premise-sap-abap-system./

https://blogs.sap.com/2020/10/29/develop-deploy-sapui5-fiori-like-app-using-sap-business-application-studio-bas-and-troubleshooting/ ]

Create a file called, say, “hello1.txt” e.g. in the config folder of local SAP Cloud Connector directory (doesn’t really matter where this file is, I just happened to pick that location):

Contents of the file, for example could be:

We start up a python server, from inside the directory on our laptop containing files for SAP Cloud Connector, this directory then becomes the python server’s root directory (again, it isn’t so important the choice of directory, except that we want to be sure that the hello1.txt file is somewhere in the directory tree under the root directory – in our case, it is, via the relative filepath ./config/hello1.txt). This blog isn’t going to explain how to install python3 on your computer, since it depends a bit on the OS you have; https://www.python.org/ is a useful resource though. Note also that if you want to use some other HTTP server, e.g. Apache or nginx, then that is fine, just so long as you know what you are doing.

So to start up a python HTTP server listening on port 8998, say, we do this command:

python3 -m http.server 8998

If you now open a browser and go to http://0.0.0.0:8998/ you will get a list of files and directories in the directory you started your server in. Also http://localhost:8998/ will work, that is maybe a clearer notation as it signals that the server is running on your own local computer.

Set up Cloud Connector, first of all connecting to your CF subaccount – for this you need to know which Region your CF account is in (visible in the Overview page of the CF account), and then you need the “long ID” of the subaccount, visible in the subaccount Overview:

Generally also a good idea to give your instance of SAP Cloud Connector a Location ID – in case now or in future you have more than one Cloud Connector connecting to the subaccount, then the Location ID is the way to differentiate between the Cloud Connectors. You can also add a Description if you like, this time I left it blank. So you might have something like this in the form for “Add Subaccount”:

Then use the “Connect” icon to make an active connection to your CF subaccount – it is this aspect of the Cloud Connector that makes it a Reverse Invoke Proxy Server – since the tunnel is always initiated from inside your network to SCP subaccount, so there is no need to configure your network firewall to allow an incoming initial connection from the SCP subaccount.

Now we make a new mapping in the Cloud To On-Premise section. Back-end Type is“Non-SAP System”, protocol is “HTTP”; with internal host (in my case) “localhost” and internal port “8998” i.e. matching how you would call the python server from wherever your Cloud Connector is located, mapping to some made-up virtual host e.g. “localghost” 👻, and a virtual port e.g. “54321”; Principal Type “None”, choose “Use Virtual Host in Request headers”; localghost resource item should give access to all subdirectories “path and all sub-paths” from server’s root directory “/”:

Set up a Destination in SAP CF trial subaccount, the Destination name I settled on was “python3”, though you can call yours whatever you like obviously. In this case the user and password are for logging in to my “laptop as a server”, so naturally I’m using my user:password tuple for said laptop.

Showing here below the downloaded file and then a screenshot. My CloudConnector has Location ID “garp” so that is why you find the matching “garp” in the SCP side in Destination config – so that the Destination knows which CloudConnector it is meant to interact with…

#Password=<< Existing password/certificate removed on export >> # #Tue Dec 01 15:41:28 UTC 2020 Description=python3 -m http.server 8998 Type=HTTP HTML5.Timeout=60000 HTML5.DynamicDestination=true Authentication=BasicAuthentication WebIDEUsage=odata_abap,dev_abap Name=python3 WebIDEEnabled=true CloudConnectorLocationId=garp ProxyType=OnPremise URL=http\://localghost\:54321 sap-client=001 User=specify-a-user

If you try to use the “Check Connection” button to, uhh, check the connection, then even if you have set up everything right, as of early December 2020 you get an error message:

“ Failure reason: “Could not check at the moment. Please try again later” ”

As Satek points out in his blog referred to above, you can thankfully just ignore this error message. Note that (as also pointed out in Satek’s blog) before being able to use the Destinations from the BusinessAppStudio, you will also need to add the following Role Collection: In your subaccount -> Trust configuration -> sap.default -> type in your account email address -> Show Assignments -> Assign Role Collection -> choose Business_Application_Studio_Developer -> Assign Role Collection.

Now open the BusinessAppStudio and if you haven’t already done so, create a Dev Space of “SAP Fiori” type, and then open the Studio by clicking on the name of the Dev Space once it is started.

We will create a standalone Fiori app project, mine is called “schmarp” (why? …uhh …well it rhymes with “garp” 😹 :)) with initially no connection to any Data Service. Later we configure the connection and Data Source.

So we use “Create Project from Template” from the Welcome screen, or we can use menu path File -> New Project from Template. Then choose “SAP Fiori Freestyle Project”, leave the target folder path as “/home/user/projects” (or change it if you prefer), and click Next. Then choose “ABAP” as the Target Runtime Environment (yes yes, Python is not Abap, you just need to choose “ABAP” here anyway), and choose “SAPUI5 Application”, and click Next. Enter a project name, keep or change the other defaults (I kept), and click Next. Keep or change the View Name, and make sure that you keep the answer “No” to the question “Do you want to add a data service?”:

(The reason to answer “No” is that the wizard cannot really handle the python server’s lack of OData services, so we will manually add our data service a bit later in this blog).

Then click Next and your new project will be generated. I took the option from pop-up to create a new workspace for the project, this helps to keep it “mentally separate” from other project code, but you can choose if you want to add it to existing workspace instead.

Now we modify the existing “xs-app.json” file, to specify a relative path in the app so that when running via Run configurations we can successfully use the Destination as data source. I found out empirically that it is better to specify a subdirectory of the python server’s directory tree, than to try and specify the server’s root directory, so for example in my server’s directory tree there is a directory called “config” which usefully enough contains our “hello1.txt” file, and I am specifying that directory in the file…

“xs-app.json” file:

So that means we add to the already generated code the following snippet, inside the “routes” : [] block:

{ "authenticationType": "none", "csrfProtection": false, "source": "^/config/", "destination": "python3"
},

Next we should replace the existing generated code of the “webapp/index.html” file with something that can be used to test our connection to the python server…

“webapp/index.html” file:

So here we have replaced the generated index.html with this:

<!DOCTYPE html>
<html>
<head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Schmarp!</title> </head>
<body class="sapUiBody"> <script id="myscript"> var schmarpy; fetch('../config/hello1.txt') .then(response => response.text()) .then(data => schmarpy = data.toString()) .then(schmarpy => console.log(schmarpy)); </script> Hello Schmarpy World!
</body>
</html>

The javascript Fetch API is the part of the code doing the hard work here. Based on copy-pasted and modified snippets I found from this amazing network of networks that all the cool kids are calling “The Internet”, e.g. here is a helpful website:

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

Next we create a run configuration for our project…

Select your project, select index.html as the runnable file, select “latest” for sapui5 version, and give the run configuration a name. Next you need to expand the run configuration, which will show that there is one “Data Source (python3)” available (thanks to our “xs-app.json” file we modified above), and you click on the plug icon to connect the Data Source:

Next, choose the correct Destination when prompted, for us it is “python3”:

Then we can start the Run config instance using the green “play” arrow icon next to “Run schmarp 001:

Then we can go and look at the runtime website click on “Open in New Tab” button when the toast message informing which port was used appears:

…and now we can open the Developer Tools (e.g. on Chrome, right-click -> Inspect), and see if we got an info message to the console (go to Console tab and check under “info” category:

So recall that our javascript snippet is outputting the result of our file retrieval to the browser’s console, that is the idea of the console.log() statement; zooming in to look at the results:

Some text from the hello1.txt file on python server.

BANZAI!!

Here we assume that you have some ABAP on-prem system available that you want to test connectivity to, but without needing to e.g. call any on-prem OData Service. For example, maybe none of those have been activated yet, or maybe you are not sure how to use existing Odata Services, or maybe you just have some nerdy affliction meaning you just want to use the Ping service even though the OData Services are all there and available… “well we have a Ping service, let’s y’know, use it!”…

So in your SAP Cloud Connector, you should set up a connection to an Abap system – you might be able to use a Sandbox SAP system of the organisation you work for, but for POCs it is often easier (and even preferable, from the point of view of your organisation) to use instead SAP Developer Edition running on an openSUSE VM on the laptop. Myself I am using bridged networking for the VM, so that the VM can be a node on my home network (at 192.168.8.122 as it happens). Then on the laptop’s /etc/hosts file I mapped vhcalnplci to the IPv4 address of the SAP Dev Edition instance:

# Local NPL over NAT: 192.168.8.112 vhcalnplci vhcalnplci.dummy.nodomain

If you are on a Windows local machine, the hosts file is somewhere else, see the Internet for details on how to modify it… if for some reason you cannot modify hosts file, you can just use the IPv4 address instead, although then your Fiori apps might have unexpected behaviour.

If you want to install SAP Dev Edition stuff yourself, see the various blogs, such as:

Installing SAP AS ABAP 752 SP04 on Linux – Virtual Box

Installing SAP AS ABAP 7.52 SP04 on Linux – VMWare

Another one is by, uhh, me (for installation on Ubuntu):

https://blogs.sap.com/2019/10/20/concise-guide-to-install-sap-netweaver-developer-edition-on-ubuntu-vm/

Anyway, that is enough about SAP Dev Edition, now let’s get back to the SAP Cloud Connector: example data to set up the new System Mapping: Back-end type “ABAP System”; protocol “HTTPS”, internal host “vhcalnplci”, internal port “44300” (since instance number is “00” then formula for HTTPS port is usually “443xx” where “xx” is the instance number); virtual host “something”, virtual port “44444”; Principal Type “None”, choose “Use Virtual Host in Request headers”.

For this POC, the ping service is under /sap/public/ path in SICF, rather than e.g. under /sap/opu/… like most OData Services. It makes sense to specify resources in CloudConnector in such a way that everything you want to access is allowed – you can either make several entries with more specific paths, or e.g. a generic entry such as /sap/ with “Path and all sub-paths”. Obviously if you are doing this for an organisation you will want to follow the security guidelines of the organisation, but for me I am comfortable with wide generic access by me to my laptop SAP instance.

In the ABAP system using SAPGUI, login and go to tcode SICF, Hierarchy Type is SERVICE, click F8 (Execute), open the tree to the ping node under /sap/public/, and if ping service is not activated, right-click on ping and Activate Service. Then you can also quickly test the service, right-click and Test Service:

Note that the “Test Service” uses HTTP, not HTTPS, but you can easily change the URL to test HTTPS, by changing the protocol part and the port number, e.g.:

http://vhcalnplci:8000/sap/public/ping?sap-client=001  ->

https://vhcalnplci:44300/sap/public/ping?sap-client=001

With the HTTPS URL, you will likely get a warning about the site being untrusted, but click past the warnings unless you have some reason to think that your SAP host is not trustworthy or not who it claims to be etcetera:

The page should show a message like “Server reached.” which is the success message for connectivity in this case.

Now we configure a Destination in the SAP CloudFoundry subaccount. Example configuration:

#Password=<< Existing password/certificate removed on export >> # #Wed Dec 02 14:37:18 UTC 2020 Description=To local machine's SAP Dev Edition Type=HTTP HTML5.Timeout=60000 HTML5.DynamicDestination=true Authentication=BasicAuthentication WebIDEUsage=odata_abap,dev_abap Name=local-machine-sap-1 WebIDEEnabled=true CloudConnectorLocationId=garp ProxyType=OnPremise URL=https\://something\:44444 sap-client=001 User=Developer

As you can see I am using here the “default SAP user ID” called “Developer” that comes with SAP Dev Edition. Now we can switch over to Business Application Studio and we create a new app, similar to the way we created an app previously, only this time my project is called “zarp”… because using “Z” as the first letter of a new object is just an atavistic Abap thing to do. Repeating the project creation advice of Experiment One then somewhat:

… use “Create Project from Template” from the Welcome screen, or we can use menu path File -> New Project from Template. Then choose “SAP Fiori Freestyle Project”, leave the target folder path as “/home/user/projects” (or change it if you prefer), and click Next. Then choose “ABAP” as the Target Runtime Environment, and choose “SAPUI5 Application”, and click Next. Enter a project name, keep or change the other defaults (I kept), and click Next. Keep or change the View Name, and make sure that you keep the answer “No” to the question “Do you want to add a data service?”. Then click Next and your new project will be generated.

Now we modify the existing “xs-app.json” file to specify the path to the ping service on our Abap system:

“xs-app.json” file:

Again, we add in here our target-relevant snippet, inside the “routes” : [] block:

{ "authenticationType": "none", "csrfProtection": false, "source": "^/sap/public/ping/", "destination": "local-machine-sap-1"
},

Then we replace the “webapp/index.html” code with our own code that pings the SAP System…

“webapp/index.html” file:

<!DOCTYPE html>
<html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Zarp!</title>
</head> <body class="sapUiBody"> <script id="myscript"> var zarpy; fetch('../sap/public/ping/') .then(response => response.text()) .then(data => zarpy = data.toString()) .then(zarpy => console.log(zarpy)); </script> Hello Zarpy World!
</body> </html>

Now create a run configuration for this project, like we did for the previous project. Because the xs-app.json file references Destination local-machine-sap-1, so we can see that as the name of the suggested Data Source:

So click on the plug icon and this time we select the relevant Destination, local-machine-sap-1, from the list:

Then we can press play to start the run configuration, and again go to the webpage and see what result we get by checking the console in Developer Tools:

Zooming in, that message is:

That is exactly the html response from our on-prem SAP System, which we were expecting… so let’s end this blog now, while we are still winning!