The whole idea of App Studio is to make complex things for mobile devices easy. When someone asked us if App Studio could interface with SAP, we knew it would be interesting.
SAP is one of the top business automation vendors. With more than 180,000 companies using their software (and 55,000 employees of their own), they’re a giant. They have created some of the most advanced and comprehensive software for corporations.
So far, however, it’s been difficult to integrate mobile applications with their software. Hopefully, after this blog post, the world will be a bit easier.
Here’s how we did it:
The first thing we need is some sort of interface to SAP. NetWeaver Gateway is a SAP server add-on that allows mobile devices to connect to SAP systems using AJAX. The SAP Gateway front-ends SAP systems like ERP, CRM, SRM and enables controlled read/write access to business data using HTTP(S) and OData. SAP Gateway is a centerpiece of SAP’s mobile strategy. We’ll connect to that.
Next, we needed an SAP server to connect to. Most companies keep their SAP system carefully behind firewalls so we cannot use them for testing. However, SAP does make a public server available.
Now, it’s simply a matter of placing the request to the server and getting the results back. Given that we’re working with sophisticated software like SAP, it won’t be as simple as some of the other AJAX samples we have done, though the principles will be the same.
We need to get data from the SAP site into our app. Due to our old friend, the Same Origin Policy, we cannot simply request the web page from the SAP server and use the data. Since PHP programs do not have this restriction, we will ask a short PHP app on our server to get the information for us. How short?
<?php $ch = curl_init($_GET['urlToGet']); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $data = curl_exec($ch); curl_close($ch); echo $data ?>
This script takes the urlToGet in our request string, gets that page and echoes it back to us.
Now, let’s format the request. Here’s the critical code:
user="GW@ESW" password="ESW4GW" URL="http://gw.esworkplace.sap.com/sap/opu/sdata/IWCNT/ACTIVITY/ActivityCollection" auth=encodeURIComponent("?sap-user=" & user & "&sap-password=" & password) s=URL & auth req=Ajax("ajaxGetURL.php/?urlToGet=" & s, "", "", displayResults)
The user, password and URL are all specified in the docs on SAP’s public server. We encode the user and password so they can be passed over the web, append it to the URL we want to get, and pass it as a parameter to ajaxGetURL.php.
A few seconds later, about 47k of data is returned. Here’s how a bit of it looks:
<?xml version="1.0" encoding="utf-8"?><atom:feed
xml:base="HTTP://GW.ESWORKPLACE.SAP.COM:80/sap/opu/sdata/IWCNT/ACTIVITY/"
sap:creatable="true" sap:updatable="true" sap:deletable="true"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns:sap="http://www.sap.com/Protocols/SAPData">
<atom:id>HTTP://GW.ESWORKPLACE.SAP.COM:80/sap/opu/sdata/IWCNT/ACTIVITY/
ActivityCollection<atom:link href="ActivityCollection" rel="self"...
It’s not exactly human readable, but it is XML. Rather than attempting to parse this ourselves, we can use a library to convert this to a data object we can use in our app.
data=$.xml2json(req.responseText)
App Studio includes the handy xm2json() library from Fyneworks. In Project Properties, select this library from the ToolBox. The xml2json() function will then convert the XML string to a data structure that can be addressed directly. For example:
MsgBox data.entry[0].title
will show the title of the first activity returned: “Project Closure Meeting”.
Now that we have the data, we can display it. The data returned is a list of activities. Let’s create an app with two forms: the first puts up a list of the activities. Once the user selects an activity, a second form displays with the details.
Form1 just needs a List control. We’ll leave the list empty when we create it in the IDE: it will get filled at runtime, after we get the data back. Put this code in Form1:
Function fillList() Dim activity lstActivity.deleteItem("all") For i=0 To UBound(data.entry) activity=data.entry[i] lstActivity.addItem(activity.title) Next End Function
We need to take action when the user clicks on the list. Put this code in Form1, too:
Function lstActivity_onclick(i) If TypeName(i)="object" Then Exit Function ChangeForm(Form2) showActivity(data.entry[i].content.properties) End Function
We change to Form2 and call the showActivity function to fill in the form.
Form2 is very simple. Add a title and 4 labels to it, along with a button to go back. Paste this code into Form2:
Function showActivity(activity) Description.Caption=activity.Description Loc.Caption="Location: " & activity.ActivityLocation Priority.Caption="Priority: " & activity.PriorityDescription Category.Caption="Category: " & activity.CategoryDescription StartTime.Caption="Start Time: " & formatTime(activity.PlannedStartTime) End Function Function formatTime(s) formatTime=Mid(s,3,2) & ":" & Mid(s,6,2) & " " & Mid(s,1,2) End Function Function Button1_onclick() ChangeForm(Form1) End Function
Ready to give the app a try? Here it is:
This app will run on all iOS and Android devices, by entering nsbasic.com/i/SAP into your browser. The code in this sample is compatible with Visual Basic, but would work just as well if you wanted to used JavaScript instead.