Skip to Content

Introduction

I recently came on board with The University of Mississippi Office of Information Technology with the task to deliver an iPad app consuming SAP data via NetWeaver Gateway (NG) in little more than a month. Most of my time was spent getting up to speed on Cocoa (I hadn’t worked directly in Objective-C for over a year) and developing the user interface. The backend was pretty much complete providing data to pre-existing portal (EP) based applications, and other developers were tasked with creating the NG Data and Consumption models. From my perspective as the app developer, NG provided a simple to use mechanism to access data from SAP.

Implementation

Our application is targeted at Admissions Counselors who travel the U.S. to meet with prospective high-school students and others interested in attending The University of Mississippi.

When I came on board they had a prototype application built using proxy classes generated using the SAP NetWeaver Gateway developer tool for Xcode1. Although incomplete this prototype was successfully pulling data from SAP into native Cocoa objects and plugging them into some UITableViews.

In order to quickly deploy our application we wanted to ensure that existing portal-bound applications could also be accessible. Additionally the counselors wanted to be able to search for students by attributes or by the school they were visiting that day. These requirements led me to utilize a tab-based root view (UITabBarController) with four view modes: home view (guide buttons to the other tabs, and various website links), student search, school search, and web view. The UIWebView on the fourth tab would provide a built-in, general purpose web-browser as well as a pre-defined view for the various portal-bound pages linked from the student details.

Authentication

The first major hurdle to tackle was authentication. Much of this was before my role in the project, but we settled on a solution of collecting credentials from the user and submitting them to a post action on our portal server to establish a cookie. Delightfully, all NSURLConnection based operations (UIWebView among them) share browser cookie storage so we were able to seamlessly log the user into our application as well as the portal-bound pages in one operation.

One issue we encountered is that the portal sign-in expects a supported user-agent so we had to set that header manually on the login request since we’re using a raw NSURLConnection. The data service queries also required injecting headers (the portal cookie) but this process was very straight-forward as I’ll cover below.

Data Requests

The proxy classes generated by the SAP NetWeaver Gateway developer tool for Xcode1 utilize the OData Client for Objective-C to consume the gateway provided services. Requesting a collection of data is fairly straightforward: create the proxy for the service, execute the query and store the response. This example collects a list of US states from our ADMISSIONSCOUNSELOR consumption model. Once the response is loaded, the result is fetched as a native NSArray of states:

Figure 1

Other than the fact that the consumption model naming conventions yield “strange” (to Objective-C developers) class and property names, the results are native Objective-C objects ready to be used in your app. Astute readers will recognize that this process is NOT asynchronous, I’ll cover that in the next section.

Filtering a query is also straight-forward:

Figure 2

This example demonstrates several typical argument types you may encounter as well as an example of the properties generated by the tool i.e. selectedStatus.m_value.

OData SDK Shortcomings

OData queries run as synchronous operations and don’t share the application’s NSURLConnection cookie storage. I’m not sure what mechanism the SDK is using but it’s curious that the developers seemingly avoided the readily available asynchronous mechanisms.

In the app prototype, queries were being run on the main thread which resulted in the UI being blocked during query execution. To combat this blocking I utilized multi-threading within the application to spawn the queries off the main thread so the interface could remain responsive. Thankfully Apple provides a very simple multi-threading solution in NSOperationQueue, however despite its simplicity, this approach required me add code to ensure that UI operations (stopping the activity indicator, updating the results table, etc.) would be performed on the main thread.

An additional side-effect of the synchronous query model is that connection errors such as timeouts are thrown as exceptions (as opposed to NSURLConnection’s connection:didFailWithError: method). To address this short-coming I wrapped the query operation in a try block:

Figure 3a
Figure 3b
Figure 3c

Since updating the table view’s data is essentially a UI operation, this needs to be done on the main thread. Originally I updated the data in the loadStates method, however this produced several second delays in updating the interface.

Lastly, the OData SDK query/connection timeout period is set at 30 seconds. For NSURLConnection you can specify a longer timeout, however 30 seconds is reasonable and most of our issues with timeouts ideally need to be addressed in the backend code that’s collecting the data for NG.

Conclusion

Our experience as NetWeaver Gateway early adopters has been very positive. Consuming the services from iOS has been simple and, other than some issues with how the OData SDK is written, it allows fairly quick turn-around for getting data from SAP into Cocoa.

Notes

1Please note that the SAP NetWeaver Gateway developer tool for Xcode is no longer available. You can instead use the generator tool (ODataGen) included with the OData SDK at odataobjc.codeplex.com.

To report this post you need to login first.

6 Comments

You must be Logged on to comment or reply to a post.

  1. Frank Stødle
    Thanks for sharing, Errol, I am impressed that you have a live application up and running using Gateway already — most of are still trying to understand exactly what Gateway is.

    Can I ask you to elaborate a little on the authentication issue? Which components are part of the authentication process? Does the user enter a username and password once in the application, and is this sent to the Netwaver portal and validated there? And is the username and password then stored as a cookie on the device? Is your portal then outside of the firewall?

    I find the whole authentication bit of the puzzle to be the hardest to understand — I would love to see a scheme where we can create HTML5/JS applications using BSP, and also provide secure access without having to install complex middleware such as SUP and event Gateway.

    (0) 
    1. Errol Sayre Post author
      This particular part of the puzzle was solved by another member of our team (setting up authorizations from the portal to the backend). He should be replying at some point, but I can comment on the aspects I’m familiar with.

      My application makes use of a URL on our portal server (EP) to which I post the username and password collected from the user. We modified this login script to return some additional headers for authorizations within the app, but the valid login will return the standard portal cookies. Since I’m using the NSURLConnection class to issue the request all of my UIWebView calls automatically pickup on the session cookie in NSHTTPCookieStorage. This is all automatic.

      For the actual OData service calls I simply add the required cookie as shown in the code examples. When the login response comes in I read this cookie from shared storage like so:

      NSHTTPCookie *cookie;
      NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
      for (cookie in [cookieStorage cookies]) {
           if ([cookie.name isEqualToString: @”MYSAPSSO2″]) {
                return [NSString stringWithFormat: @”%@=%@; Domain=%@; Path=%@”, cookie.name, cookie.value, cookie.domain, cookie.path];
           }
      }

      (0) 
      1. Frank Mathew

        We took advantage of SSO between Enterprise Portal, Netweaver Gateway and the backedn ECC which was setup for us by our basis team. User credentials are collected and sent securely to a location on the portal using a HTTP POST request. Simplified for illustration it would be as follows: This signs in the user and returns the SSO cookie which Errol’s code then uses to consume services via Gateway. If we store the users credentials with the app, When the cookie’s specified time to live duration expires, using the users save credentials we can again get authenticated and carry on.

        (0) 
        1. Thomas Mouritsen
          The shown example is a GET with the password as a part of the URL, which should be avoided in external scenarios. Https does not encrypt the password in a get situation. Use a POST with HTTPS and the solution is elegant.
          (0) 

Leave a Reply