Building a SAP mobile app with Sencha Touch 2

In this tutorial we are going to build a mobile app which connects to SAP systems through SAP Gateway. The app is developed completely in JavaScript using the Sencha Touch 2 framework. Once development is completed we will package the application as a native iOS app using the new Sencha Packager.

In this tutorial we will cover:

  • an outline of the tools we are going to use
  • JavaScript code for basic functional app
  • running the app in a desktop browser
  • packaging and running the app in the iPhone simulator
  • running the app on your iPhone

Introducing the cast…

Sencha Touch is a leading mobile JavaScript framework. It provides an extensive set of UI components which you can use to quickly build mobile apps that can run on many mobile devices. Sencha Touch 2 (ST2) is the latest version, and currently in Beta 3. Download the latest version.

SAP NetWeaver Gateway is a SAP server add-on that allows mobile devices (and other consumers) to connect to SAP systems using OData-based REST services. 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 and many mobile apps provided by SAP and its business partners are using SAP Gateway as well.

At this moment, SAP Gateway (version 2 SP3) only supports OData’s AtomPub XML format.

SAP graciously provides an online demo system where you can test-drive the SAP Gateway and the ERP and CRM systems. Our mobile app is going to connect to this demo system, using the demo user account provided by SAP. On SDN (SAP Developer Network) you will find more information on SAP Gateway and you will also find examples of other integration scenarios.

Same Origin Policy

Our Sencha Touch app will need to contact a remote SAP Gateway server to exchange XML data. In a web application, the browser will enforce the Same Origin Policy (SOP). This implies that the HTML file which contains the application must be served from the same domain, port and protocol as the XHR requests are sent to.

Let’s quickly explore the options:

  • JSONP is not an option: not supported by SAP Gateway. In addition limited to read-only scenarios.
  • Use a reverse proxy, which front-ends both the SAP Gateway and the webserver which serves up the application HTML/JS/CSS files. This way the HTML file and SAP Gateway appear to be on the same server. Good option, but adds a moving part to the solution.
  • Native packaging. In a native app, the SOP does not apply. Say again?  Because the HTML file is called by webkit using the file:// protocol, the SOP does not apply. This means there are no cross domain restrictions.

For our demo app we will opt for native packaging.

A closer look at the SAP data

Before we can start building the app we need to understand the content and structure of the data we will fetch from the server. Our first basic app will fetch Activity data from the SAP CRM demo system. Let’s lookup the activities in the SAP CRM system, so we know what activity data to expect:

image

As you can see, there are 5 open Activities for the demo user. To retrieve the activities from the SAP Gateway as an OData feed, get the following service url:

http://gw.esworkplace.sap.com/sap/opu/sdata/IWCNT/ACTIVITY/ActivityCollection?sap-user=<username>&sap-password=<password>

Visit the SAP Gateway Demo page to find the username and password to use.

The server will respond with XML in OData atom feed format. Each activity is contained in an “entry” element.image

The entry element contains the properties of an Activity:image

Developing the SAP mobile app

Enough talk, time to start coding! Our initial goal is to build a first, very basic mobile app which will show the user’s open Activities in SAP CRM. In Sencha Touch we need the following classes:

  • an Activity model: a class representing an Activity (on the client side!).  Defines the fields we want to use.
  • a Gateway Proxy: responsible for fetching data from the SAP Gateway server. It cleverly uses the field definitions of the Activity model to parse the response into Activity model instances which are handed over to the store.
  • an Activities store: holds a collection of activities in the browser. The store is filled by the output of the Gateway Proxy
  • an ActivityList: a UI component which renders a list of activities contained in the store

Looking at the structure of the OData xml, we can define the Activity model class. The fields configuration tells which properties we want to be extracted from the server response into our activity objects. The fetching and parsing is delegated to the proxy:

// Define the Activity model
Ext.define('App.model.Activity', {

    extend: 'Ext.data.Model',

    // the proxy config requires the sap_gateway
    requires: ['App.proxy.sap_gateway'],
    config: {

        // define the fields which we want to extract from the OData response.
        fields: [
            { name: 'Description', type: 'string' },
            { name: 'ActivityLocation', type: 'string' },
            { name: 'CategoryDescription', type: 'string' },
            { name: 'PriorityDescription', type: 'string' }
        ],

        // provide a proxy configuration
        proxy: {
            // use the special sap_gateway proxy
            type: 'sap_gateway',
            url: "https://gw.esworkplace.sap.com/sap/opu/sdata/iwcnt/activity/ActivityCollection?sap-user=<usern>&sap-password=<passsword>"
        }
    }
});

As you can see, the Activity model uses a special proxy type, identified by ‘sap_gateway’. ST2 will look for classes with an alias of proxy.sap_gateway. Also note that you need to require the proxy class in the Model before you can use it.

The proxy encapsulates the communication with remote SAP Gateway server. Our proxy needs to convert the XML data response to Model instances. Because the response is in XML, we can use an XML reader to extract the data from the server response. The XML reader uses the Activity model field definitions to determine which data to extract. With that, the SAP Gateway proxy is remarkably simple:

Ext.define('App.proxy.sap_gateway', {

    // The SAP Gateway proxy extends the built-in Ajax proxy
    extend: 'Ext.data.proxy.Ajax',

    // It requires an XML reader class to parse the response
    requires: 'Ext.data.reader.Xml',

    // Set an alias, so we can use { type : 'sap_gateway' }
    alias: 'proxy.sap_gateway',

    config: {
        // Disable use of paging params (limit, page, start)
        enablePagingParams: false,

        // Disable cache busting
        noCache: false,

        // Configure a XML reader to process the server response.
        // Each activity is contained in an 'entry' element.
        reader: {
            type: 'xml',
            record: 'entry'
        }
    }
});

Please note:

  • this proxy class is re-usable in many Model/Stores combinations. SAP backend systems provide a vast amount of ‘classes’ (in OData parlance: Entity Types): Activities, Accounts, SalesOrders, Currencies, Invoices, etc.You can re-use this proxy with any of these Entity Types.
  • the proxy is read-only: to fetch data from SAP Gateway. A read-write proxy will require additional code.

With the Activity model and Gateway Proxy in place, we can define the Activities store class:

// An Activity store is just a basic Store,
// with a preconfigured Activity model.
Ext.define('App.store.Activities', {
    extend: 'Ext.data.Store',
    config: {
        model: 'App.model.Activity'
    }
});

This completes the data part of the application. Now let’s turn to the UI. We need a List to show the results when the Store has loaded the data from the SAP Gateway.

Ext.define('App.view.ActivityList', {
    extend: 'Ext.List',
    requires: ['Ext.TitleBar'],
    config: {
        // make sure this view uses the full viewport
        fullscreen: true,

        // item template: for each activity in the list,
        // show the description
        itemTpl: '{Description}',

        // put a titlebar on top of the list
        items: [{
            xtype: 'titlebar',
            docked: 'top',
            title: 'SAP CRM Activities'
        }]
    }
});

The most important part is the itemTpl configuration. The item template determines how to format the activities properties in a list item. We’ll keep it very simple and just output the Description field.

Next, we need to tie all the classes together in an Ext.application and tell the application what to do upon launch.


// Don't let the loader generate unique urls to prevent caching
Ext.Loader.setConfig({
    disableCaching: false
});

// Configure the application
Ext.application({
    name: 'App',
    models: ['Activity'],
    views: ['ActivityList'],
    stores: ['Activities'],
    launch: function () {

        // Create an Activity store
        var activityStore = Ext.create('App.store.Activities');

        // Create an ActivityList which takes its
        // data from the Activity store
        Ext.create('App.view.ActivityList', {
            store: activityStore
        });

        // Instruct the store to load the Activities from the
        // server. After the Activities are received, the activity
        // list is updated automatically.
        activityStore.load();
    }
});

As you can see, the App requires the Activity model, the Activities store and the ActivityList. Upon launch, all the application does is create a store, create the view and load data into a store.

To complete our first SAP mobile app, we will need an index.html to contain the ST and app files.

<!DOCTYPE html>
<html>
    <head>
        <title>SAP demo</title>
        <link rel="stylesheet" href="lib/sencha-touch.css" type="text/css">
        <script type="text/javascript" src="lib/sencha-touch-debug.js"></script>
        <script type="text/javascript" src="app/app.js"></script>
    </head>
    <body>
    </body>
</html>

ST2 comes with various builds. I use the sencha-touch-debug.js version, which contains the core library and uses a dynamic script loader to fetch dependencies. I found this worked well in a development setting. However, I disabled cache busting. This prevents the loader from appending unique strings in the url when it fetches the source files. Otherwise you will loose your debugging breakpoints when you refresh your browser.

Running the app in the desktop browser

OK, time to run and test the app in our desktop browser! We’ll use an http server on our local machine to serve the files to our browser. I use the development server built into VS2010, but anything will do. Let’s assume your http server runs on port 35000 and your index.html file is served at http://localhost:35000/index.html .

Remember that we need to overcome the SOP restriction to be able to test the app in our desktop browser? Luckily Chrome provides a command line option which disables the SOP.  (Safari has the same switch but it only takes effect on a Mac, not in Windows).

So, start your Chrome browser with –disable-web-security command line option:

C:\path\to\chrome.exe –disable-web-security

Enter the url for the index.html:

http://localhost:35000/index.html

And lo and behold, we see the Activities that are fetched from the remote SAP CRM system!

SNAGHTML1989016

Let’s look at Network traffic in Chrome Developer tools. You can see all the traffic caused by the dynamic loader. Our call to the SAP Gateway system is indeed allowed by Chrome (try using Chrome without the disable-web-security option and it will throw an error).

SNAGHTML19d1211

Use the XHR option in the bottom toolbar to only show the requests to SAP Gateway.

Extending the app

Now we have this basic app running we can start adding functionality. Next to CRM Activities, the SAP Gateway demo systems offers access to other business data like CRM Accounts and Sales Orders. By adding models, stores, views and navigation we can create a more advanced SAP mobile app. Check out the Sencha Touch 2 guides to see what’s possible. Here are some examples of views and detail screens that you can build:

imageimage

imageimage

Packaging and running the app on iPhone simulator

Now our application development is completed, we are going to package it up as a native app, using the new Sencha packager which is part of ST2. We are going to create a native package for iOS. See this guide for more info.

To use the Sencha Packager you will need a Mac OS X machine with the latest XCode installed. Following the guide, you need to create separate configuration files for each type of deployment. In this tutorial we will create 2 configuration filess:

  • simulator.json: to run the app in the iPhone Simulator
  • development.json: to run the app on your own iPhone

I created the following folders structure to house the demo project. Please note that the www folder contains all the code which we developed earlier. The app folder contains a typical folder layout for a Sencha Touch app.

image

The content of the simulator.json file is:

{
  "applicationName":"SapDemo",
  "applicationId":"com.oxida.sapdemo",
  "outputPath":"~/Projects/SapDemo/simulator",
  "versionString":"1.0",
  "webAppPath":"~/Projects/SapDemo/www/",
  "configuration":"Debug",
  "platform":"iOSSimulator",
  "deviceType":"iPhone",
  "orientations": ["portrait"]
}

This configuration tells the packager to build a version of the app for Simulator and place the SapDemo.app file in the simulator folder.

We have all the files and folders in place. Let’s package and run the app. Open a Terminal window, change to your working directory and run the packager:

image

If all is well, your iPhone simulator will start and run the app:

image

This screencast shows the app in action on the iPhone simulator.

Running the app on an iPhone

Finally, we want to run our app on a real device. To run the app on a real device you need certificates and provisioning profiles, which you can request from the Apple Developers Provisioning Portal (you will need a Apple iOS developer license).

The use of certificates and profiles is,… well …, non-trivial. So if you are new to this, check out some tutorials which explain the concepts in more detail. For those of you who are already familiar with certificates and profiles, here’s a high-level reminder.

You want to… Certificate needed Provisioning profile needed
Run app in iPhone simulator none none
Run app on your own device Development certificate Development
Send app to selected group of users (e..g. beta tester) Distribution certificate Ad Hoc Distribution
Send app to the App Store Distribution certificate App Store Distribution

Now, back to the Sencha Packager!

To create a version of the app that can run on a real device, we need to set the configuration option to “Release”. The Sencha packager will by default use your distribution certificate and App Store distribution profile. For a deployment to your own device, you have to explicitly specify your developer certificate, using the certificateAlias option.

So the development.json  configuration file contains:

{
  "applicationName":"SapDemo",
  "applicationId":"com.oxida.sapdemo",
  "outputPath":"development",
  "versionString":"1.0",
  "webAppPath":"~/Projects/SapDemo/www/",
  "configuration":"Release",
  "platform":"iOS",
  "deviceType":"iPhone",
  "certificateAlias":"iPhone Developer: Your Name",
  "orientations": ["portrait"]
}

Please note: at this moment (Feb 16, 2012) this requires you to install a patch described in this forum post. This patch will be included a future update of Sencha SDK tools versions and I will update this tutorial when the patch is not required anymore.

We can now run the Sencha Packager using development.json as configuration file and build the app. This will create an app version which is code-signed with your developer certificate. As a last step, transfer the Development provisioning profile and the app file to your device. You can use this using iTunes, Organizer in xCode or (my preference) the iPhone Configuration Utility.

Now you should be able to start your app from your device. This is a screenshot from my iPhone:

IMG_0783[1]

Phew..! It’s been a long way but we have our SAP mobile app running on an iPhone!

Where to go from here

We gone through the steps to create a basic app and deliver a development version to our iPhone device. As next steps you can:

  • Further extend the app
  • Create a production build from your Javascript sources (concat source files, change the ST lib build)
  • Create an AdHoc distribution and distribute to up to 100 testers

For final deployment you can consider the Apple AppStore, Enterprise deployments or SAP Mobile App Store, which offers and sells mobile apps build by SAP and its partners.

I hope this post has inspired you to further explore the exciting opportunities of using Sencha Touch 2 to create custom mobile experiences for users of SAP systems.

Thanks for reading!

Advertisement

Building SharePoint Web Apps using Sencha Touch

In this post we will explore how to build a SharePoint mobile web app using Sencha Touch, a great mobile JavaScript framework.

SharePoint 2010 is a very comprehensive platform, but mobile support is fairly limited. Although it is technically possible to customize the mobile user interface on the server side, this is not allowed in cloud based SharePoint (e.g. in Office365).

An alternative  approach is to build a web app where the UI is generated in the browser and connects to one of the SharePoint APIs to access data stored in SharePoint. SharePoint 2010 offers three data APIs which can be used in web apps:

  • SP Web Services (SOAP)
  • REST (ListData.svc)
  • CSOM (Client Side Object Model)

Although each of the APIs offer a distinct set of capabilities, the REST interface is simple and lightweight and I prefer this for mobile use. The SharePoint REST interface offers full CRUD access to items in SharePoint lists and libraries, which might be all that you need for your mobile web app.

Getting started

Because of the Same Origin Policy, your html file must be served from the same domain as the SharePoint site you want to access. You can place your html file containing your app on the server file system or in a SharePoint document library (e.g. site assets).

If you are using SharePoint Online (Office365), you will notice that when you select a .html file in a doc library, it is presented as a download, not opened in the browser. This is due to SharePoint settings which you are not allowed to change in SharePoint Online. As a workaround, simply use an .aspx file extension, instead of .html. This way, you can start your single page SharePoint application from a file in an asset library.

So, to get going, you need to create a app.aspx file to include all the css and js for your Sencha Touch app.

<!DOCTYPE html>
<html>
    <head>
    <title>SharePoint web app example</title>
       <link rel="stylesheet" href="sencha-touch.css" type="text/css" />
       <link rel="stylesheet" href="app.css" type="text/css" />
       <script src="sencha-touch.js"></script>
       <script src="app.js"></script>
    </head>
    <body>
    </body>
</html>

The app.js file contains the basic Sencha Touch start-up and shows an alert:

new Ext.Application({
  launch: function () {
    Ext.Msg.alert('Hello world', 'Ready for action!')
  }
});

You can put these files  in any SP doc library. Let’s assume you have put this file in the Site Assets library of a SP site called demo:

image

Now you can open up the following url on your iPhone or Android device:

http://<SPserver>/demo/siteassets/app.aspx

After logon, you will see the following result:

IMG_0724

Not quite what we expected… SharePoint has detected that we access the page with a mobile device and responds with the default mobile UI. You can suppress the default mobile UI by appending ?mobile=0 to the url.

So, let’s try: http://<SPserver>/demo/siteassets/app.aspx?mobile=0

IMG_0725

Yes! We now have a Sencha Touch web app running of a SharePoint server.

OData proxy

The next step is to connect Sencha Touch models and stores to SharePoint items and lists through the REST interface using the OData protocol. For this you will need an OData proxy. I developed an OData proxy as a Ext user extension. It is designed to access SharePoint data using the SharePoint ListData.svc REST service which is based on OData. You may use it for other OData sources.

The OData SharePoint proxy is on GitHub: https://github.com/lstak/SharePoint-proxy-for-Sencha-Touch

Ext.ux.ODataProxy features:

  • create, read, update and delete SharePoint items as Sencha Touch models
  • fetch multiple items from a SharePoint list in a Sencha Touch store
  • JSON payloads
  • partial updates: only changed attributes are sent to the server during an update
  • fixes issues in Sencha Touch data Model implementation (e.g. missing destroy() method)

Let’s look at some examples how you can use the SharePoint proxy. In these examples we will assume you have a subsite ‘/teamsite’ in which you have created a Contacts list based on the standard Contacts list template.

First we need to define the Model.

var Contact = Ext.regModel('Contact', {
  fields: [
      // please note CamelCase convention for SharePoint column names
      { name: 'Id', type: 'int' },
      'LastName',
      'FirstName'
    ],

  idProperty: 'Id',

  proxy: {
    // use the special odata proxy defined in odataproxy.js
    type: 'odata',

    // the proxy will connect to the List
    // named 'Contacts' in the /teamsite subsite
    url: '/teamsite/_vti_bin/ListData.svc/Contacts'
  }
});

We can now use the following CRUD operations on the Contact data model:

// Create an instance
var contact = new Contact({ LastName: 'Johnson', FirstName: 'Al' })
contact.save();
...

// Read an instance from the server by id
var id = 200;
Contact.load(id);
...

// Update an instance, loaded from the server
Contact.load(id, {
    success: function (contact) {
        contact.set("LastName", "Maxwell");
        contact.save();
    }
});
...

// Delete an instance
Contact.load(id, {
    success: function (contact) {
        contact.destroy()
    }
});
...

Using the Contact model you can now easily define a Store to fetch multiple items:

var store = new Ext.data.Store({
    model: 'Contact'
});

store.load()

Build your application

Using the odata proxy to configure your Models and Stores that connect to the SharePoint server, you can develop your app further just like any other Sencha Touch app. Check out the tutorials on the Sencha site for more info.

I will conclude with an example of a contact list through the normal SharePoint UI and through a Sencha Touch app:

image

IMG_0743[1]

Just as easily, you can expose the content of document libraries:

image

IMG_0744[1]

Live demo

A live demo is available at http://oxida.sharepoint.com/demo. You can open the mobile web app and also explore the content of the SharePoint site with a desktop browser.

image

Sencha Touch and SharePoint are a great combination and open up exciting new opportunities for companies using SharePoint. Give it a try!