You are on page 1of 34

12/02/2015 SAPUI5 | … And All That JS

… And All That JS
JavaScript, Web Apps and SharePoint

CA TE G O RY   A RCHI V E S :   S A P UI 5

Node.js on Azure calling
SAP Gateway
Posted on March 21, 2012

It’s hard to miss the growing excitement around Node.js, a server­side JavaScript
environment, especially ever since Microsoft supports the Node.js project and even offers
Node app hosting as a service on Windows Azure.

I was eager to get a first hands­on with Node on Azure, so in this post we are going to
build a Node.js app running on Windows Azure, accessing SAP business data through
SAP Gateway. I decided to go for ‘the Cloud’ all­the­way, so we will develop both a server
and client (i.e. browser) application in JavaScript using Cloud9, a web based IDE. The
browser app is based on SAPUI5. It displays a list of Sales Orders and the user can also
request an overview in Excel, generated on­the­fly on the server. To easily work with the
source code of the project, we will use a repository on GitHub.

Here are screenshots of the end result:

http://allthatjs.com/category/sapui5/ 1/34
12/02/2015 SAPUI5 | … And All That JS

http://allthatjs.com/category/sapui5/ 2/34
12/02/2015 SAPUI5 | … And All That JS

So if you are in for some exposure to cutting edge technologies, read on! 

The players

SAP Gateway is a SAP server add­on that allows you to access  business data in SAP
systems through OData, an open web protocol for querying and updating data, built on
common web technologies like HTTP, XML and REST.

SAPUI5 (officially known as “UI development toolkit for HTML5”) is a JavaScript library,
currently in Beta, to build HTML5 apps.

Node.js is a server platform that is quickly gaining popularity. It is built on Chrome’s V8
JavaScript runtime and allows you to create server applications in JavaScript. Node.js
uses an event­driven, non­blocking I/O model that makes it lightweight and efficient.

Cloud9 is a web­based IDE + node.js runtime environment offered as a service (partially
open sourced). In Cloud9 you can develop, debug and test node.js applications, all from
within your browser. Cloud9 can use a GitHub repository to manage and share the source
code. Once you have completed your application, you can deploy the application to
Windows Azure.

http://allthatjs.com/category/sapui5/ 3/34
12/02/2015 SAPUI5 | … And All That JS

Windows Azure is Microsoft’s cloud platform. One of the services is hosting a Node.js
application in a scalable environment.

GitHub hosts source code repositories,using the Git version control system. GitHub
offers public and private repositories. To work with GitHub, you need to use Git client
software.

The Big Picture

Before we go into the details, let’s sketch how it all fits together:

For development, we’ll create a code repository on GitHub. This way we can add/update
source code and resource files both from our local machine (via Git) and on Cloud9. We
will use the repository to add all SAPUI5 js and css files that are required to our project
files. In Cloud9 we use a clone of the GitHub repository. This way we can push and pull
Cloud9 project files in and out of the GitHub repository.

Cloud9 is a fully web­based development environment: developers use a browser to
access the Cloud9 code editor, system command prompt, debugger, Node.js console
output etc. We can run a Node.js application directly on the Cloud9 environment and use
a special url to access the running server app as a (test) user.

Actually we need 2 applications: a server application which runs on the Node.js server
and acts as middleman to SAP Gateway (and possibly other data sources) and a client
application (HTML5, SAPUI5)  which runs in the browser, but uses html/css/js files
which are hosted on the server. It is important to keep these two apart, even if we develop
both in JavaScript.

The client and server app interact in the following way:

DI S P L A Y   S A L E S   O RDE RS   I N  DA TA   TA B L E

the user starts the app by requesting the server url

http://allthatjs.com/category/sapui5/ 4/34
12/02/2015 SAPUI5 | … And All That JS

the server sends the client application html file (index.html) which instructs the
browser to load additional SAPUI5 resource files and the client js code.
the client app starts up and creates a SAPUI5 OData Model and Data Table to fetch
and display Sales Order data. The data isn’t fetched from the SAP Gateway directly
(not allowed due to the Same Origin Policy). Instead, the request is sent to the
server, which forwards it to SAP Gateway. The server acts as a reverse proxy.
The server passes the OData response from SAP Gateway to the browser. Here,
the OData feed is parsed using SAPUI5’s built in OData support and the extracted
data is shown in the Data Table.

DO WNL O A D  A S   E X CE L

When the user clicks on ‘Download as Excel’ button, the client app requests a
special url from the server.
This will trigger the server to fetch the Sales Order data from SAP Gateway, parse it
(but now on the server side!), convert it into an Excel format and return this to the
user. The user experience is identical to requesting a downloadable file.

Once we have the application working in the Cloud9 environment, we can request
deployment to Windows Azure. Cloud9 will generate configuration files, package the apps,
upload and deploy to Azure.

Caveats:

This demo project involves quite some platforms and services. Within the scope of
this blog post it is not feasible to provide a very detailed, click­by­click walk­through.
Instead I will refer to tutorials for the respective services which contain detailed
instructions and I will point out the main route and highlights along the way.
I recommend that you use Safari, Chrome or Firefox on GitHub and Cloud9. IE
support is lagging (GitHub) or non­existent (Cloud9).

Step 1: Create a GitHub repository

First we need to create a repository on GitHub to manage and share our source code
across environments.

1.  Sign­up with a (free) account for GitHub. A free account let’s you create public
repositories.
2.  Follow the instructions on Set up Git to install Git local software and set up SSH
keys
3.  Create a repository on GitHub. We’ll assume it is named: NODEJS_SAPGW
4.  Clone the repository to local machine
5.  Try out pushing and pulling content from your local machine into the repository until
you become familiar with the process

Here are the important Git commands you will need:

http://allthatjs.com/category/sapui5/ 5/34
12/02/2015 SAPUI5 | … And All That JS

// Clone repository
$ git clone git@github.com:[yourname]/NODEJS_SAPGW.git
 
// push content
git add .
git commit ‐m "Commit message"
git push
 
// pull content
git pull

I think GitHub is a great tool for developers, so I encourage you to check out the GitHub
help center to learn more.about the other features of Git and GitHub. For our demo project
the above commands are all we need.

Step 2: Develop on Cloud9

Now we have a repository on GitHub, we can start a project on the Cloud9 IDE.

1.  Signup on http://c9.io. It is very convenient to signup with your GitHub account.
Look for the small GitHub icon.

2.  After signup, you will see your GitHub repository (I blurred out my other
repositories):

http://allthatjs.com/category/sapui5/ 6/34
12/02/2015 SAPUI5 | … And All That JS

3.  Select the repository and click ‘Clone to edit’ and select Shared Development
server.
4.  The Cloud9 environment will make a Clone of the GitHub repository available in your
Cloud9 environment.
5.  Once the Clone is completed, you see the following screen. Click on ‘Start Editing’.

6.  This will bring you into the project environment. Create a folder called ‘Public’. This
folder will contain all the files required for the client application. Add the index.html
and app.js (described below) and push the changes to GitHub and pull to your local
machine. Add the SAPUI5 resources on your local working directory and push to
GitHub and pull from Cloud9. All this pushing and pulling sounds like a workout, but
trust me, you’ll get the hang of it!

Client application

The client application consists of an index.html file and app.js file and uses SAPUI5 to
fetch and parse OData and render a data table widget.

The index.html includes the SAPUI5 core library (which dynamically will load all
dependencies), the application js file and a placeholder for the data table.

01 <!DOCTYPE html>

http://allthatjs.com/category/sapui5/ 7/34
12/02/2015 SAPUI5 | … And All That JS

02 <html>
03     <head>
04         <meta http‐equiv='X‐UA‐Compatible' content='IE=edge' />
05         <title>Node.js calling SAP Gateway</title>
06  
07         <script id="sap‐ui‐bootstrap"
08            src="resources/sap‐ui‐core.js"
09            data‐sap‐ui‐theme="sap_goldreflection"
10            data‐sap‐ui‐libs="sap.ui.commons, sap.ui.table"></script
11  
12         <script src="app.js"></script>
13  
14     </head>
15     <body class="sapUiBody">
16          <img src="images/sap_logo.png" />
17         ​
 <div id="salesorders"></div>
18         ​
 
19     </body>
20 </html>

The app.js contains the client code:

1 // Let's define some shortcuts to increase
2 // readability of the code
3 var ODataModel = sap.ui.model.odata.ODataModel,
4     TextView = sap.ui.commons.TextView,
5     Label = sap.ui.commons.Label,
6     DataTable = sap.ui.table.DataTable,
7     Toolbar = sap.ui.commons.Toolbar,
8     Button = sap.ui.commons.Button,
9     Column = sap.ui.table.Column,
10     Right = sap.ui.commons.layout.HAlign.Right,
11     Begin = sap.ui.commons.layout.HAlign.Begin,
12     SelectionMode = sap.ui.table.SelectionMode;
13  
14 // Specify the SAP Gateway SalesOrder service as an OData model.
15 // Please note: we do not connect directly to SAP Gateway (no host specified)
16 // Instead, the calls are made to the Node.js server,
17 // which will proxy the calls to SAP GW
18 // This way, we comply with Same Origin Policy of the browser. 
19 var salesOrderService =
20         "/sap/opu/sdata/IWFND/SALESORDER",
21  
22     // SAP Gateway only supports XML, so don't use JSON
23     asJson = false,
24     salesOrderModel = new ODataModel(salesOrderService, asJson),
25     salesOrderCollection = "SalesOrderCollection";
26  
27 // Create a button to request an Excel workbook from server 
28 var button = new Button({
29     text: "Download as Excel",
30     icon: 'images/excel.png',
31     iconFirst: false,
32     height: '24px',
33     press: function () {
34         window.location = "/workbook"
35     }
36 });
37  
38 var toolbar = new Toolbar({ 
39     items: [button]
40 });
41  
42 // Create a master table with sales orders 
43 var salesOrders = new DataTable({
44     title: "Sales Orders",
45     width: "600px",
http://allthatjs.com/category/sapui5/ 8/34
12/02/2015 SAPUI5 | … And All That JS

46     visibleRowCount: 20,
47     toolbar: toolbar,
48     selectionMode: SelectionMode.None,
49     editable: false
50 });
51  
52 // define the relevant column options
53 var salesOrderColumns = [
54     { header: "Sales Order ID", value: "{SalesOrderID}", width: '100px'
55     { header: "Customer Name", value: "{CustomerName}", width: '100%'
56     { header: "Net", value: "{NetSum}", width: '100px', hAlign: Right },
57     { header: "Tax", value: "{Tax}", width: '100px', hAlign: Right },
58     { header: "Total", value: "{TotalSum}", width: '100px', hAlign: Right }
59 ];
60  
61 // create the columns
62 salesOrderColumns.forEach(function (options) {
63     var label = new Label({ text: options.header }),
64         template = new TextView({ text: options.value }),
65         column = new Column({
66             label: label,
67             template: template,
68             width: options.width,
69             hAlign: options.hAlign || Begin
70         });
71  
72     salesOrders.addColumn(column);
73 });
74  
75 // connect the data table to the SalesOrder service
76 salesOrders.setModel(salesOrderModel);
77  
78 // An OData request for the SalesOrderCollection 
79 // will return the sales orders. 
80 // Each sales order should result in a table row.
81 salesOrders.bindRows(salesOrderCollection);
82  
83 // Put table in the DOM.
84 // placeAt will automatically defer if 
85 // DOM is not ready yet (like in this demo).
86 salesOrders.placeAt("salesorders");

With that, our client application is in place.

Server application

Node.js includes core library functions to create an HTTP server and client. You have
probably seen the famous 6 lines of code to create a ‘Hello world’ http server in Node.js.
The core library is intentionally kept light­weight and (relatively) low­level. But is very easy
to extend the base capabilities of Node by including modules in your code. The Node.js
community has built a wide range of modules that handle common tasks like XML
parsing, static file serving, request routing etc.

To keep our server application compact, we will use 2 of these modules:

express.js: a web application framework on top of Node, to provide request routing
(connecting incoming requests to JS functions) and serving the static files (the html,
js and css files for the client application).
xml2js: to parse the SAP Gateway OData response into a JavaScript object

http://allthatjs.com/category/sapui5/ 9/34
12/02/2015 SAPUI5 | … And All That JS

To install the modules in your Cloud9 project, you can use NPM (Node Package
Manager). Just issue the following commands in the command field:

npm install express
npm install xml2js

This will install the modules (and their dependencies) in the node_modules folder of your
Cloud9 project. Click the refresh button next to Project Files and you can see the results.

Now we have the required modules installed, we can coding our server.js file which
contains the server application code. Based on the code of our client application, the
server application needs to respond to the following requests:

/ : redirect requests without pathname (i.e. server name only) to index.html in the
‘public folder
/sap/*: forward (proxy) all requests for SAP Gateway content and include
authentication
/workbook: generate an Excel workbook on the fly and deliver as download
otherwise: serve static files for the client app if contained in the ‘public’ folder

So here is server.js, the code to implement the server application

1 var http = require('http'),
2     express = require('express'),
3     xml2js = require('xml2js'),
4     app = express.createServer(),
5     port = process.env.PORT;
6  
7 // The SalesOrder service requires authentication
8 // get the username/password from the SCN page. 
9 var username = 'USERNAME',
10     password = 'PASSWORD';
11  

http://allthatjs.com/category/sapui5/ 10/34
12/02/2015 SAPUI5 | … And All That JS

12 var sapgw = {
13   host: 'gw.esworkplace.sap.com',
14  
15   // set up Basic authentication
16   headers: {
17     'Authorization': 'Basic ' + new Buffer(username + ':' + password).toString(
18   }
19 }
20  
21 // Action: Proxy an incoming (ie. from the user's browser) request to the SAP G
22 function proxy(user_request, user_response) {
23  
24   // We're proxying calls,
25   // so copy the path from the user request
26   sapgw.path = user_request.url;
27  
28   // Use a client request to call SAP Gateway
29   http.get(sapgw, function (sapgw_response) {
30  
31     // Include a content type in the response header
32     user_response.header('Content‐Type', 'application/atom+xml;type=feed'
33  
34     // In Node, http responses are streams. You can just
35     // pipe the response data from the Gateway to the user.
36     sapgw_response.pipe(user_response);
37   });
38 }
39  
40 // Action: Generate an Excel workbook containing SalesOrders on the fly  
41 function workbook(req, res) {
42  
43   // We will fetch the SalesOrderCollection from SAP Gateway
44   sapgw.path = '/sap/opu/sdata/IWFND/SALESORDER/SalesOrderCollection'
45  
46   // Kick‐off by fetching the SalesOrderCollection..       
47   http.get(sapgw, function (sapgw_response) {
48     var xml = '';
49  
50     // Every time Node receives a chunk of data
51     // from SAP Gateway, the 'data' event fires.
52     // We just collect all chunks into a string
53     sapgw_response.on("data", function (chunk) {
54       xml += chunk
55     });
56  
57     // The 'end' event fires when the SAP Gateway response is done 
58     // We can start processing the xml string...
59     sapgw_response.on("end", function () {
60  
61       // Node.js doesn't automatically parse the XML (like XmlHttpRequest),
62       // so we need to do that explicitly.
63       // We will use the xml2js module to parse the XML string
64       // into a JavaScript object
65       // Create a parser to convert the XML to JavaScript object
66       var parser = new xml2js.Parser();
67  
68       // The 'end' event fires when the parser is done.
69       // The resulting JS object is passed as parameter.
70       parser.on('end', function (result) {
71         // The result parameter is a complete representation 
72         // of the parsed XML string.
73         // We need to extract the values we need to render the workbook
74         var rows = [],
75  
76         // columns is the subset of properties we want to include
77         // in the Excel list
78         columns = ['SalesOrderID', 'CustomerName', 'NetSum', 'Tax
79  
80         // the value of result['atom:entry'] is an array of objects, 

http://allthatjs.com/category/sapui5/ 11/34
12/02/2015 SAPUI5 | … And All That JS

81         // representing 's in the XML string.
82         // Each entry represents a SalesOrder
83         result['atom:entry'].forEach(function (entry) {
84           var row = {},
85             // properties points to the parsed properties 
86             properties = entry['atom:content']['m:properties'];
87  
88           columns.forEach(function (property) {
89             // get the value for the property
90             row[property] = properties['d:' + property]['#'] || 
91                             properties['d:' + property];
92           });
93  
94           // add it to the rows 
95           rows.push(row)
96  
97         })
98  
99         // We're done processing the response and have extracted all data requi
100         // create the workbook.
101         // First, include the proper HTTP headers
102         res.header('content‐disposition', 'attachment;filename=SalesOrders.xml
103         res.header('Content‐Type', 'application/vnd.ms‐excel');
104  
105         // Next, render the contents of Excel workbook as
106         // Excel 2003 XML format, using the Workbook.ejs template
107         res.render('Workbook.ejs', {
108           layout: false,
109           rows: rows
110         });
111  
112       });
113  
114       // Set the parser in motion with the xml data received
115       // from SAP Gateway. The parser will turn the XML string into
116       // a JS object. When done, the 'end' event will fire
117       // and the 'end' event handler defined above will extract the values
118       // and render the Workbook.
119       parser.parseString(xml);
120     });
121  
122   });
123 };
124  
125 // Action: perform a redirect to the home page (index.html)   
126 function home(req, res) {
127   res.redirect('/index.html')
128 }
129  
130 // Now we will set up the routing for the server...
131 // Look if the request is for a static file in the public directory
132 // this is where the client side html, css, js and SAPUI5 resources are located
133 app.use(express.static(__dirname + '/public'));
134  
135 // If you just call the server (root), redirect to homepage
136 app.get('/', home);
137  
138 // Requests starting '/sap/' are proxied to the SAP Gateway
139 app.get('/sap/*', proxy);
140  
141 // Route for workbook action
142 app.get('/workbook', workbook);
143  
144 // Routes are set up,
145 // Now start the app server...
146 app.listen(port);
147  
148 console.log('Server started on port ' + port);

http://allthatjs.com/category/sapui5/ 12/34
12/02/2015 SAPUI5 | … And All That JS

You can find the username/password for the SAP Gateway demo environment on this
SCN page.

The server application uses an ejs view template to generate the Excel workbook content.
Express expects these views by default in the ‘views’ directory. An ejs template is a text
file interspersed with JavaScript (very similar to classic asp or jsp pages). The view
renderer uses the template and provided parameter to output a text string, in our case the
Excel content. Here’s the relevant part of the view template (rows are passed as a
parameter):

1 <Worksheet ss:Name="Sheet1">
2   <Table ss:ExpandedColumnCount="5"
3          ss:ExpandedRowCount="<%= rows.length+1 %>" 
4           x:FullColumns="1"
5           x:FullRows="1" 
6          ss:DefaultRowHeight="15">
7    <Column ss:AutoFitWidth="0" ss:Width="77.25"/>
8    <Column ss:AutoFitWidth="0" ss:Width="138.75"/>
9    <Column ss:StyleID="s67" ss:AutoFitWidth="0" ss:Width="56.25" 
10     <Row ss:StyleID="s62">  
11             <Cell><Data ss:Type="String">SalesOrderID</Data></Cell
12             <Cell><Data ss:Type="String">CustomerName</Data></Cell
13             <Cell><Data ss:Type="String">Net</Data></Cell>
14             <Cell><Data ss:Type="String">Tax</Data></Cell>
15             <Cell><Data ss:Type="String">Total</Data></Cell>
16     </Row>
17     <% rows.forEach(function(row){ %>
18         <Row>   
19             <Cell><Data ss:Type="String"><%= row.SalesOrderID %></
20             <Cell><Data ss:Type="String"><%= row.CustomerName %></
21             <Cell><Data ss:Type="Number"><%= row.NetSum %></Data></
22             <Cell><Data ss:Type="Number"><%= row.Tax %></Data></Cell
23             <Cell><Data ss:Type="Number"><%= row.TotalSum %></Data
24         </Row>
25     <% }) %>
26 </Table>
27 </Worksheet">

Now, let’s run the application in debugging mode on Cloud9. The Output tab will show the
output from the application initialization and any console.log statements you include in the
code. It also provides the url where you can access the running application.

http://allthatjs.com/category/sapui5/ 13/34
12/02/2015 SAPUI5 | … And All That JS

Click on the server url and our application opens up:

http://allthatjs.com/category/sapui5/ 14/34
12/02/2015 SAPUI5 | … And All That JS

Click on the ‘Download as Excel’ button and Excel workbook with the Sales Orders will
open:

OK, we now have a working application in Cloud9! There’s a lot more to explore in the
IDE. For example, try the debugging options: you can set breakpoints, just like in desktop
IDEs. Code execution on remote server will halt and you can explore variable and
parameter values, etc. You can also push your changes to the central repository on
GitHub.

Here, we will continue our Quick Tour by deploying the application we just completed to
Windows Azure.

Step 3: Deploy to Windows Azure

Cloud9 makes deployment to Windows Azure very easy. This tutorial shows all the steps
in detail. You can skip the first steps because we already have a working app on Cloud9.
Please start at “Create a Windows Azure account’.

After the initial set up, you can request deployment to Azure:

http://allthatjs.com/category/sapui5/ 15/34
12/02/2015 SAPUI5 | … And All That JS

Cloud9 will offer to create default configuration files for you. Please accept.

Deploying can take a few minutes, while the application is packaged, uploaded and
deployed on Azure:

Once deployment is active, you can click on it and see the details 

http://allthatjs.com/category/sapui5/ 16/34
12/02/2015 SAPUI5 | … And All That JS

The Windows Azure management tool provides full details on the deployment:

Our application is now available on Windows Azure:

http://allthatjs.com/category/sapui5/ 17/34
12/02/2015 SAPUI5 | … And All That JS

http://nodesapgw.cloudapp.net

You can try it! It’s live.

You’ll notice that it takes quite some time to load the page. This is mainly caused by
dynamic loading of SAPUI5 resource files. Optimizations are certainly possible, but
outside the scope of this article.

This concludes our demo project to show how you can front­end SAP Gateway using
Node.js on Azure.

‘Just because you can, doesn’t mean you should’

That’s a profound adage, so let’s wrap­up with a number of suggestions  why you may
consider front­ending SAP Gateway in the Cloud:

Provide access to multiple backend systems through a single domain (origin). This
way, you comply with the Same Origin Policy.
Integrate SAP data in an Azure based cloud solution (E.g. a hosted .Net, MS­SQL
solution)
Offload non­business data http traffic of SAP Gateway to a more cost­effective
platform.
Avoid exposing the SAP Gateway end­point to the public internet
Low­latency traffic by using caching to prevent repeatedly asking the same data via
SAP Gateway. E.g. for type­ahead and suggestion/select drop­boxes in HTML5
apps, low­latency response are required. This is becoming more important with
mobile apps where quick selections/suggestion lists are preferred of manual input of
texts
Scale­out on demand
Protocol conversion: you may want to build client applications using other protocols
(e.g. WebSockets) to expose business data. E.g. consider real­time auctions.
Content conversion: for example turning business data into Excel sheet as
demonstrated in our application
Identity conversion: a consumer facing web application may allow consumers to
login with their Facebook or Twitter account using OAuth2. The web application

http://allthatjs.com/category/sapui5/ 18/34
12/02/2015 SAPUI5 | … And All That JS

server can connect to SAP Gateway with a functional account.

Let me know if you have other suggestions/use cases.

Thanks for reading!

Helpful resources

Set up Git
Deploying a Windows Azure App from Cloud9
Getting started with Node.js Web Application: describes a local development
approach for Node.js apps on Azure using the Windows Azure SDK for Node.js.
Cloud9 help pages
Overview of Node modules

Posted in Azure, GitHub, JavaScript, Node.js, OData, SAP Gateway, SAPUI5 |
Tagged Azure, Cloud9, Node.js, SAP Gateway, SAPUI5 | 17 Replies

Installing the SAPUI5
SDK Samples
Posted on February 27, 2012

My previous post “Getting started with SAPUI5” provides the steps required to get the
SAPUI5 SDK documentation installed and ready for use on your local machine using
Visual Studio.

The SAPUI5 SDK documentation also includes lots of live code samples. To get them up
and running requires some additional steps.

Installing the SAPUI5 SDK Samples

unzip HTML5Beta_complete/demokit/WEB­INF/lib/demokit­uilib­1.2.0
inside the unzipped demokit­uilib­1.2.0, copy the META­
INF/resources/sap/ui/demokit folder into the previously created /resources/sap/ui
folder

Your SDK folder should now look like this:

http://allthatjs.com/category/sapui5/ 19/34
12/02/2015 SAPUI5 | … And All That JS

If you open the SAPUI5 documentation and navigate to the Controls > Button page, you
should see:

http://allthatjs.com/category/sapui5/ 20/34
12/02/2015 SAPUI5 | … And All That JS

Via the ‘Show Source’ link you can see and even change/re­run the source code, which
allows you to easily experiment with the configuration settings:

The SDK samples provide a good impression of the look & feel of the SAPUI5 controls.
The screenshots below show some of the available SAPUI5 Controls (using the “gold
reflection” theme).

CheckBox

http://allthatjs.com/category/sapui5/ 21/34
12/02/2015 SAPUI5 | … And All That JS

ComboBox

DatePicker

RadioButtonGroup

RatingIndicator

http://allthatjs.com/category/sapui5/ 22/34
12/02/2015 SAPUI5 | … And All That JS

Slider

SearchField

TabStrip

Menu and MenuButton

http://allthatjs.com/category/sapui5/ 23/34
12/02/2015 SAPUI5 | … And All That JS

Paginator

ProgressIndicator

Tree

RichTooltip

http://allthatjs.com/category/sapui5/ 24/34
12/02/2015 SAPUI5 | … And All That JS

More information

For more information, visit the SAPUI5 SDK developer center on SDN.

Thanks for reading!

Posted in JavaScript, SAPUI5 | 1 Reply

Getting started with SAPUI5
Posted on February 23, 2012

There are some great HTML5 UI frameworks available in the marketplace: Sencha Touch,
KendoUI and Twitter Bootstrap to name just a few. And now SAP has unveiled the Beta
version of SAPUI5, officially known as “UI development toolkit for HTML5”.

As a follow up on my post on Building a SAP mobile app with Sencha Touch 2, I was
keen on having a hands­on with SAPUI5. These helpful posts helped me to get started.

In this post we’ll set up the Beta version of SAPUI5 for use in Visual Studio and create a
demo SAPUI5 app that fetches SAP ERP Sales Orders from SAP Gateway and
combines them with issues tracked in a SharePoint list.

Installing the SAPUI5 SDK on Visual Studio 2010

1.  Visit the homepage for SAPUI5 on SDN and download the trial version (SAPUI5
beta)
2.  Unzip the downloaded file HTML5Beta_complete.zip
3.  Open the folder with extracted content. Unzip ‘sapui5­static.zip’. You will need the
‘resources’ folder for development
4.  Rename demokit.war to demokit.zip and unzip. This archive contains the
documentation which you can install locally.

http://allthatjs.com/category/sapui5/ 25/34
12/02/2015 SAPUI5 | … And All That JS

5.  In Visual Studio, create a solution and within the solution ‘Add a new web site’
6.  Copy the contents of the demokit into the web site
7.  Copy the resource folder of sapui5­static.zip to the web site
8.  Rename index.html to default.html (the VS dev server opens default.html instead of
index.html when browsing a directory).
9.  Your file/folder structure should now look like this:

10.  Now select the web site and ‘View in Browser’

You now have access to the documentation of SAPUI5:

A first test

http://allthatjs.com/category/sapui5/ 26/34
12/02/2015 SAPUI5 | … And All That JS

Now we have the documentation up and running, we create our first test to see if we have
all the required files.

To run this test, setup a new project or website in VS. Copy the ‘resources’ folder from
sapui5­static into the site and create the following test.html file:

1 <!DOCTYPE html>
2 <html>
3     <head>
4         <meta http‐equiv='X‐UA‐Compatible' content='IE=edge'>
5         <title>SAPUI5 test</title>
6         <script id="sap‐ui‐bootstrap"
7            src="resources/sap‐ui‐core.js"
8            data‐sap‐ui‐theme="sap_platinum"
9            data‐sap‐ui‐libs="sap.ui.commons"&gt;&lt;/script&gt;
10         <script>
11             $(function () {
12                 // show an SAPUI5 alert box
13                 sap.ui.commons.MessageBox.alert("SAPUI5 ready for action.");
14             })
15         </script>
16     </head>
17     <body>
18     </body>
19 </html>

The test.html file instructs the browser to load the sap­ui­core.js file which contains jQuery
and also a dynamic loader which will load further required js and css files. To show that
everything loads correctly, we simply create an alert box (one of the SAPUI5 controls)
when the DOM is ready.

View the test.html file in the browser and you see:

http://allthatjs.com/category/sapui5/ 27/34
12/02/2015 SAPUI5 | … And All That JS

OK, we’re all set to do something a little more exciting!

Building a demo app

Consider the following business scenario: a company is managing Sales Orders in SAP
ERP. To improve order fulfillment, they use a issue tracking workflow system in
SharePoint. Their requirement is to see the info from SAP and SharePoint in a single
screen. Let’s build that with SAPUI5!

We will connect to the online SAP Gateway demo system to fetch Sales Orders from
SAP ERP. Using the demo SAP Gateway system, you can try out SAPUI5 without
having to install/configure any server side components.

Our issue tracking list is part of a SharePoint Online site (SharePoint Online is part of
Microsoft’s Office365 offering). Each Issue contains a field Sales Order ID which we will
use to filter. Here’s how the Issues look inside the SharePoint site:

http://allthatjs.com/category/sapui5/ 28/34
12/02/2015 SAPUI5 | … And All That JS

Both SAP Gateway and SharePoint are OData providers, so we will use SAPUI5’s OData
model to connect to the backend systems and parse the responses. Our application page
will present three tables:

Sales Orders: the master table showing the available Sales Orders
Line items: a details table showing the line items belonging to the selected Sales
Order
Issues: a details table showing the issues tracked in SharePoint related to the
selected Sales Order.

This structure is already pre­defined in the body of the index.html file:

1 <!DOCTYPE html>
2 <html>
3     <head>
4         <meta http‐equiv='X‐UA‐Compatible' content='IE=edge'>
5         <title>SAPUI5 demo</title>
6         <script id="sap‐ui‐bootstrap"
7            src="/resources/sap‐ui‐core.js"
8            data‐sap‐ui‐theme="sap_platinum"
9            data‐sap‐ui‐libs="sap.ui.commons, sap.ui.table"></script
10         <script src="app/app.js"></script>
11     </head>
12     <body class="sapUiBody">
13          <img src="images/sap_logo.png" >
14          <div id="salesorders"></div>
15          <div id="lineitems"></div>
16          <img src="images/o365_logo.jpg" style="margin:30px 0 10px 0"
17          <div id="issues"></div>
18     </body>

http://allthatjs.com/category/sapui5/ 29/34
12/02/2015 SAPUI5 | … And All That JS

19 </html>

The JavaScript of our application is contained in app/app.js.

001 // Let's define some shortcuts to increase
002 // readability of the code
003 var ODataModel = sap.ui.model.odata.ODataModel,
004     TextField = sap.ui.commons.TextField,
005     TextView = sap.ui.commons.TextView,
006     Label = sap.ui.commons.Label,
007     DataTable = sap.ui.table.DataTable,
008     Column = sap.ui.table.Column,
009     SelectionMode = sap.ui.table.SelectionMode;
010 // Specify the SAP Gateway SalesOrder service as an OData model
011 var salesOrderService =
012         "https://gw.esworkplace.sap.com/sap/opu/sdata/IWFND/SALESORDER
013     // The SalesOrder service requires authentication
014     // get the username/password from the SDN page.
015     username = "[username]",
016     password = "[password]",
017     // SAP Gateway only supports XML, so don't use JSON
018     asJson = false,
019     salesOrderModel = new ODataModel(salesOrderService, asJson, username, passw
020     salesOrderCollection = "SalesOrderCollection";
021 // specify the SharePoint site containing the Sales Order Issues as an OData mo
022 // we will assume there a SharePoint site called 'demo'
023 // which has an issues list called 'SalesOrderIssues'
024 var issueService =
025         "http://[SharePoint_server]/demo/_vti_bin/ListData.svc",
026     issueCollection = "SalesOrderIssues"  // name of SP List
027     issueModel = new ODataModel(issueService);
028 // Create a master table with sales orders
029 var salesOrders = new DataTable({
030     title: "Sales Orders",
031     width: "100%",
032     visibleRowCount: 5,
033     selectionMode: SelectionMode.Single,
034     editable: false
035 });
036 // define the relevant column properties
037 var salesOrderColumns = [
038     { header: "Sales Order ID", value: "{SalesOrderID}", width: 
039     { header: "Customer Name", value: "{CustomerName}", width: '50%'
040     { header: "Amount", value: "{TotalSum}", width: '50%' }
041 ];
042 // create the columns
043 salesOrderColumns.forEach(function (column) {
044     var label = new Label({ text: column.header }),
045         template = new TextView({ text: column.value }),
046         column = new Column({
047             label: label,
048             template: template,
049             width: column.width
050         });
051     salesOrders.addColumn(column);
052 });
053 // connect the data table to the SalesOrder service
054 salesOrders.setModel(salesOrderModel);
055 // An OData request for the SalesOrderCollection
056 // will return the sales orders.
057 // Each sales order should result in a table row.
058 salesOrders.bindRows(salesOrderCollection);
059 // Put table in the DOM.
060 // placeAt will automatically defer if
061 // DOM is not ready yet (like in this demo).
062 salesOrders.placeAt("salesorders");
063 // At this point the Sales Order master table is done
http://allthatjs.com/category/sapui5/ 30/34
12/02/2015 SAPUI5 | … And All That JS

064 // Creating the lineItems and issues table is very similar
065 // Creating the line items datatable
066 var lineItems = new DataTable({
067     title: "Line items",
068     width: "100%",
069     visibleRowCount: 10,
070     selectionMode: SelectionMode.Single,
071     editable: false
072 });
073 lineItemColumns = [
074     { header: "Line item #", value: "{SalesOrderItem}", width: '100px'
075     { header: "Product Name", value: "{ProductName}", width: '50%'
076     { header: "Amount", value: "{NetSum}", width: '50%' }
077 ]
078 lineItemColumns.forEach(function (column) {
079     var label = new Label({ text: column.header }),
080     template = new TextView({ text: column.value }),
081     column = new Column({
082         label: label,
083         template: template,
084         width: column.width
085     });
086     lineItems.addColumn(column);
087 })
088 lineItems.setModel(salesOrderModel);
089 lineItems.placeAt("lineitems");
090 // Create the issues datatable
091 var issues = new DataTable({
092     title: "Issues",
093     width: "100%",
094     visibleRowCount: 5,
095     selectionMode: SelectionMode.Single,
096     editable: false
097 });
098 issuesColumns = [
099     { header: "Id", value: "{Id}", width: '30px' },
100     { header: "Title", value: "{Title}", width: '40%' },
101     { header: "Status", value: "{IssueStatusValue}", width: '10%'
102     { header: "Comments", value: "{Comments}", width: '50%' }
103 ]
104 issuesColumns.forEach(function (column) {
105     var label = new Label({ text: column.header }),
106         template = new TextView({ text: column.value }),
107         column = new Column({
108             label: label,
109             template: template,
110             width: column.width
111         });
112     issues.addColumn(column);
113 });
114 issues.setModel(issueModel);
115 issues.placeAt("issues");
116 // The three data tables are ready!
117 // Now we need to define what should happen when
118 // the user selects a row in the sales order (master) table
119 salesOrders.attachRowSelect(function (event) {
120     var Filter = sap.ui.model.Filter,
121         FilterOperator = sap.ui.model.FilterOperator,
122         selectedRowContext = event.getParameter("rowContext"),
123         selectedSalesOrderID = salesOrderModel.getProperty("SalesOrderID"
124         selectedSalesOrderLineItems = selectedRowContext + "/salesorderlineitem
125     // load the line items for the selected sales order
126     lineItems.bindRows(selectedSalesOrderLineItems);
127     // create a filter based on sales order ID
128     var filter = new Filter("SalesOrderID", FilterOperator.EQ, 'SO:'
129     // load the issues table using the filter
130     issues.bindRows(issueCollection, null, [filter]);
131 });

http://allthatjs.com/category/sapui5/ 31/34
12/02/2015 SAPUI5 | … And All That JS

Now, fire up your Chrome browser with the “disable­web­security” command line. This will
suppress the Same Origin Policy which normally doesn’t allow you to do XHR request
across domains:

Now you can view index.html in Chrome:

We have just build our first mash­up of SAP ERP and SharePoint data using SAPUI5!
http://allthatjs.com/category/sapui5/ 32/34
12/02/2015 SAPUI5 | … And All That JS

Themes

SAPUI5 provides a number of themes. The theme used in this example is called
‘sap_platinum’. You can find other themes in the /resource/sap/ui/*/themes folders. Here
are screenshots of the same page using the other themes (click the images to enlarge):

Theme:
sap_goldreflection Theme: sap_ux

Theme:
sap_hcb Theme: base

My first impressions on SAPUI5:

Offers a comprehensive set of UI widgets and layouts
Huge code base. Definitely not a micro­framework  .
Amazingly little code is required to get a demo app with OData sources described
above up and running.
Includes jQuery (version 1.4.4. included in sap­core­ui.js)
Includes datajs.js(OData library by Microsoft)
Style and idiom is a bit verbose and seems to be influenced by Java. This may be a
pro or a con, depending on where you are coming from.

Overall SAPUI5 is a very interesting entrant in the marketplace and sure to further boost

http://allthatjs.com/category/sapui5/ 33/34
12/02/2015 SAPUI5 | … And All That JS

the position as HTML5 as UI platform.

I hope this post is helpful in starting to explore the SAPUI5 Beta yourself.

Thanks for reading!

UPDATE (Oct 2012): SAPUI5 now includes mobile controls. See comment below from
Ruben.

Posted in JavaScript, SAP Gateway, SAPUI5 | 33 Replies

http://allthatjs.com/category/sapui5/ 34/34