1 2 3 28 Previous Next

SMP Developer Center

420 Posts

Hi,

With a little delay – this has changed in 1607.

 

  • Optimized UI for back-end security
  • Logout API
  • Localizations for China and Japan

Optimized UI for back-end security

The admin UI for configuring the security settings of your back-end connection will now automatically adapt to the appropriate properties you need to fill. Even though it is just a convenience update I hope you enjoy the simplified data entry process. Also this introduces so called SSO mechanisms that should make it easier for you to configure back-end security. An SSO mechanism describes the way a request need to be authenticated by your back-end system.

 

 

Logout API

We now expose an API that lets you clear the session on the server in order to provide a clean logout in your device with a simple POST or DELETE operation. A subsequent HEAD request will then trigger the authentication challenge. We introduced this feature to let our customers easily create multi-user applications, switching user context without de- and re-registration.

So in order to logout a user you can send a DELETE to

 

https://{…}.ondemand.com/mobileservices/sessions/logout

 

containing all the cookies relevant for the server to identify your session. Best would be to use the HttpConversionManager to do this.

As a response the server will send you a 204 with no content.

Now, you’d send a HEAD request to your application URL in order to trigger authentication for the user.

Localizations for China and Japan

Following our HANA Cloud Platform data center expansion strategy, the mobile service will be available in a Chinese and Japanese datacenter, hence we provide a UI and documentation translation for these customers.

I just set my browser prefer Japanese language and this is what I got:

Picture1.png

As a big fan of Japanese Anime and Manga this gives me a quite an interesting view, other than that I really don’t understand a single word.

 

If you are bored reading my monthly release blogs – you can also experience the latest and greatest release overview videos here: https://www.youtube.com/watch?v=VKCBKLP2ry0

 

Have fun,

Martin

In this blog we are going to see how to configure Web Dispatcher and its profile parameters to allow X509 certificate via Web Dispatcher.

 

Prerequisite:

 

  1. Ensure you are able to Register & Read data using X509 Certificates with SMP URL & port 8082 in REST Client
  2. You have a working Web Dispatcher setup with Admin access
  3. Root Certificate and corresponding Intermediate certificate if any
  4. SMP Server Certificate signed by CA
  5. Access Web Dispatcher Remote system
  6. PKI for signing the certificates

 

To get X509 working with oData and SMP you may refer to

 

 

By end of this blog we would achieve the following:

10.png

As part of the configurations, we shall follow these sequence below:

 

  1. Importing Certificate into WD
  2. Configure SAPSSLC
  3. Modify Profile Parameters
  4. Configure SMP Impersonator Role

 

Let us being:

 

Importing Certificate into WD

 

Login to web dispatcher admin URL:

Eg:  http://xxxxxxxx/sap/admin/public/default.html

 

Navigate to SSL & Trust Configuration and PSE Management.

 

You should be able to see options Manage PSE, you will have 3 options:

  • SAPSSLA
  • SAPSSLC - SSL client PSE
  • SAPSSLS - SSL server PSE

 

Select SAPSSLC

Under Trusted Certificates, click on “Import Certificate”, Select the Root Certificate and Import it

1.png

 

For security reasons, I have hidden the details. However, the steps are simple and you should be able to continue the confirmations and get them working with this procedure.

 

Click on “Import Certificate” again and select your Intermediate Certificate if you have them

 

Click on “Import Certificate” again and select your SMP Certificate which is signed by Intermediate Certificate / Root Certificate

 

Repeat the same steps for SAPSSLS and import all the three certificates.


Configuring SAPSSLC

  • Select SAPSSLC which is for Client
  • Create CA Request and submit the request to your PKI and download the signed details
  • Import the CA Response and create a certificate .CER format

 

After the import the configurations looks like this:2.png

Where Subject “CN=XXX” is the XXX Certificate which will be used as Impersonator in SMP Server.

 

Modifying the Profile Parameters:

 

Login to WD Remote System and Navigate to the following path:

 

C:\WD Installation Path\sap\WDS\SYS\profile

 

Open the file – WD_FILE_NAME

 

a. Adding Message Server

3.png

b. Adding ICM and Cipher

4.pngc. Modify the “mod_rules” as required according to your setup

 

Configuring SMP Impersonator Role

 

a. Login to SMP Sandbox and Navigate to Settings and Select the X509 Security profile and then click on Role Mapping

5.pngb. Click on Impersonator6.png

c. Import the WD Certificate to Physical Role Mapping, click on Browse and Select the certificate and add the Role to Mapped Role. The detail should like this

7.pngd. Click on Save and Save to get back to Setting Screen.

 

The configurations are completed and you should be able to test X509 with Web Dispatcher.

 

This should help you get the authentication with X509 from Web-Dispatcher.

 

Looking forward for your comments and feedback.

 

Regards,

Nagesh

Hi,

Today I have to apologize that this announcement comes a bit late and the release to preview of 1606 has already been taken place two weeks back. Secondly, the release seems to be small, but this is just an illusion – we are just preparing some awesome features for later releases

 

Nevertheless, here’s the update:

  • Automatic removal of inactive users
  • Apps from other sources are read-only
  • Implementation of product name changes

 

Automatic removal of inactive users

With 1604 we introduced a feature that inactivated unused registrations after a pre-defined period of three months. Now you can customize this time period for automatic removal per app via the Admin UI. This is how it looks like:

Picture1.png

Apps from other sources are read-only

App configurations that are being managed by systems rather than administrators are now managed separately and will be read-only in the administration UI. This is to prevent accidental changes to the configuration. As an administrator you can’t modify these remotely controlled app. You can identify these apps when you want to try to modify them:

Picture2.png

Implementation of product name changes

As already announced the product name has changed to SAP HANA Cloud Platform, mobile service for development and operations. We have now incorporated the new naming in the product itself and in the documentation. As the new name is quite long, we can shorten it in the context of the admin UI.

Picture3.png

 

 

That’s all for this month. Stay tuned, we’ll use the rainy Sommer in Germany to dig in ourselves and develop awesome features that we will disclose after the vacation time.

 

Have Fun,

Martin

With the release of SP11 of the SAP Mobile Platform we introduced a lot of important changes and innovations:

  • MBO Façade
  • SAP Secure Login Server integration
  • Revamped Admin UI
  • Usage Analysis
  • Feature migration from HCP mobile services for development and operations

 

MBO Facade

For the customers who are running MBO-based applications the MBO Façade will come really handy on their journey towards Offline OData based applications.

 

The Façade is an integrated web app in the SMP 3.0 side car that automatically exposes the whole dataset of a given application as delta-token enabled OData service. Your whole MBO data model, which does the change calculation for your, is now accessible as an OData service. There is no need for additional development work, everything works out of the box, no redeploy of packages needed. After your in-place upgrade to SP11, you’ll have immediate access to the data. If you were not accessing it, it will not consume resources either.

 

You’ll find the OData service here:

 

http[s]://supserver:port/mbofacade/{domainName}/{packageName}/{packageVersion}/$metadata

 

In the following table you’ll see how MBO artifacts are mapped to OData artifacts.

MBO Package

MBOFacade OData Service

Attribute

Property

CUD operations

POST/PUT/PATCH/DELETE request

Mobile Business Object

Collection/Entry/Entity

Other Operation

Operation Entity

Relationship

Association and Navigation Property

Synchronization Parameter

Subscription Entity

 

Please also notice that query options like $orderby, $top, $filter are not supported on these sevices, but this is not really a bad thing. You would offline these data on the device using the SAP Mobile Platform SDK and on the device you’ll be able to use all these query options.

 

There’s also a MBO to OData data type mapping. Most of it is obvious, but there is one thing to be noticed: MBO date types are mapped to Edm. DateTime! Know you know it.

 

Here’s how it looks like from an architectural point of view:

Picture1.png

The SMP3 main car does treat the MBO façade a bit special and generates a special header with a unique ID that prevents MBO cache groups to be refreshed to often through the offline component behavior in the main car. This optimization will be later available in HCPms as well, so that you can expose your MBO data to HCP!

 

When should you use this feature:

  • You already have an existing MBO data model
    • You want to leverage the MBO technology to add delta calculation capabilities to non-delta enabled back-ends
    • You want to offload your back-end (staging) and in addition you want to use the more flexible and open development approach of Offline OData
    • You want migrate away from MBO to OData-based mobile app technology. With this, you already have an OData based app. Next step would be to migrate your OData service to SAP Gateway.

SAP Secure Login Server Integration (with support of Christian Cohrs)

The world of business applications is changing rapidly, and technologies used to support these business applications need to provide a high level of both flexibility and security to cover the many requirements. However, when it comes to secure authentication, customers often find the best and most flexible solution to be a mature and widely used technology that has been the foundation for many security processes for a long time, namely X.509 certificates.

Many SAP customers use Public Key Infrastructure technology to provide X.509 certificates to their end users for secure authentication to desktop applications. It is only natural that these customers also want to rely on certificates for secure authentication on mobile devices.

With the release of SP11 of version 3.0, the SAP Mobile Platform is able to integrate with Secure Login Server (SLS), SAP’s solution for providing X.509 certificates for secure authentication and certificate lifecycle management. This enables the many SLS customers to reuse the existing and proven certificate authority (CA) to also cover mobile scenarios. Even customers using a 3rd party CA can benefit from the integration, as Secure Login Server can be used as a kind of proxy (or registration authority) in front of an existing enterprise PKI. For more information on Secure Login Server, please visit https://scn.sap.com/community/sso

 

The architectural view is as follows:

Picture2.png

The request from the client on the left hand side will be redirected to the Secure Login Server. Once the SLS has authenticated the request, the device can access the back-end servers using the certificate issued by the SLS. This is of course a very simplified view, since the actual certification creation process is not trivial. Good news from SMP administration perspective is that the configuration is really easy:

Picture3.png


Revamped Admin UI

Let’s have a look first:

Picture4.png

Well, that looks very similar to the HANA Cloud Platform mobile service for development and operations UI and actually it is even the same code!

We are really staying true to your mantra “one code line” for on-premise and on-demand versions of our mobile technology stack. With the revamped Admin UI, featuring Fiori-Tec design, we can now easier make innovation released for on-demand first to our on-premise customers. The disadvantage here is that users of SMP will not be familiar with the new UI and you’ll certainly search a lot until you’ll find the screen or option you are looking for – the whole navigation and all the screens have been changed. But the concepts of what you configure stay the same! So, I’m pretty sure you’ll quickly get used to it.

 

 

Usage Analysis

The usage analysis you may know from HCP mobile service for development and operations is now also available on SMP. A very good example of a feature that first appears in HCP mobile service and then will be available on SMP.

We do have the usage upload via the SDK and also the very (release 1605 of the mobile service on HCP) new predefined usage reports in SP11. Of course, your apps need to upload the usage data first in order to generate the reports.

Here’s how it can look like:

Picture5.png

Feature migration from HCP mobile services for development and operations

And finally there are a lot of changes included that have been introduced in mobile service on HCP already:

  • • Automatic Removal of inactive user registrations
  • • Renewed Application Overview screen
  • • Custom URL rewriting
  • • …

 

One last thing I want to mention, even though it is a bit out of line and has not directly something to do with SP11. This year we slowed down release cycle of SMP to two releases instead of four. This is to make sure our on-premise customers do have a chance to keep up with the release cycles.

 

Hope you’ll enjoy the new release.

 

Have Fun,

Martin

With SMP 3.0 latest release SP11, Management cockpit got a new look and feel (similar to mobile service cockpit on HCP) based on SAP FioriTec style. There is an easy navigation, great user interface and of course improved in texting format. 'Home' page got nice tiles view with great 'Toggle Menu' on left side.

 

1.PNG

 

I had a quick look across it hence sharing my findings and suggestions for some existing and new features.

 

1. There is no 'Context sensitive help' guide as FioriTec Style doesn't support it. Click on 'Help' (question icon) on top bar,  -  a direct link to SP11 help documentation

     7.PNG

 

2.. Table view and Tile View on 'Applications' page

 

2.PNG

 

 

 

My PoV: When i switch to 'Tile View', instead of showing App name (like test ap, test), i would prefer to see Application ID since AppID has to be used for all REST API calls.


3. Create a new App:

  • New feature: Enable CSRF protection (Reference)
  • My PoV:
    • There is no apps versioning available, so what is the point of showing 'Version' here?
    • Not much great to have 'Security profile name' option as same thing can/has to be selected from 'AUTHENTICATION' tab

          3.PNG

    • BACKEND: With this SP11, 'User System proxy' checkbox is not available to tell the application to use proxy or not. that means (after upgrade to SP11),  application that doesn't require proxy won't longer work and ping fails. Well, this configuration can be done via 'non proxy hosts'  Settings->System->HTTP Proxy Settings->Non-proxy hosts) Check  SAP Note 2332148

               6.PNG

 

  • New Rewrite Mode: Custom Rewrite URL  (No Reference in the documentation on how to use this feature)

         8.PNG

    • Client Policies:

              My PoV: wish to have 'Export' functionality as sometime we may have to cross check settings to compare with its previous file. It would reduce manual work of copying the whole detailed settings into a file.

          9.PNG

 

4. Registrations and users:

 

My PoV:  Wish to have an EXPORT option that would give an easy way to download registrations list in an excel format (In a support project, there may be a need to share list of registrations for an application for a given period of time as a periodic activity)

 

     10.PNG

 

5. Cluster:

 

In a typical organization, DELETE/RESTART of an SMP instance has to be done by BASIS team and it should be done from the file system. When there are mutiple projects going on, SMP Admin role may have to be assigned to someone from project team, As a user having Admin role, i would not like to see such options (it's a danger when someone restarts SMP node from Admin UI and you have to spend time in checking in logs who has done it). In short, this 'Actions' tab shouldn't be there.

 

11.png

 

 

6. Reporting: Server Log Data

 

     Probably a wrong label. Should be SMP instead of HCPms

 

12.png

7.  LOGS ->LOG FILES

 

Here, whenever I have to look into latest server logs, I need to download that file. Max size of that file could be 20 MB (default size) and then I need a tool like notepad++ to view this file. Imagine if I look into logs for every 30 mins over a day that means at least 20 times I have to download those files. This would be unnecessary of data storage on my machine.

 

I remember in previous SP, whenever I used to click on any log files, it used to open in the browser. For any latest entries, I could just refresh the browser and see the updated logs. I heard, few customers didn’t like this option for some reasons and that feature was taken away.

 

My PoV:  give us a choice (maybe an Action icon in front of the file name) on every log file, either download it or open in a browser.

     13.png

My PoV: Agentry Logs should be arranged in a Collapse/Expand node (like it is there in SP10 and previous versions)

     14.PNG

 

 

9. SETTINGS ->CERTIFICATES

 

   My Pov:  Again, similar concern as mentioned in step#6, DELETION of a certificate shouldn't be permitted via Admin UI

17.PNG

Note: Above points have been suggested based on our current project requirement, i am sure there will be more PoVs from others as well. Please do share it via blogs or in the comments section. #HappyLearning #HappySharing

Release Notes: SAP Mobile Platform Server - SAP Library

cc: Martin Grasshoff

Make Sure Your Offline Works Right

 

Developing an offline mobile app is not always as straightforward as initially thought. During the various stages of app development there is sometimes a time to step back and take a close look into a system behaviour. Often we call this “debugging”. Debugging code is pretty well known for all the supported platform of the SAP Mobile Platform SDK – it is just code. But in an offline application you also want to check the data transferred to your device as well as the configuration you set on the server.

The SAP Mobile Platform SDK provides a simple command line tool, which is able to simulate an offline application, perform the initial sync, refresh and flush as well as the usual data operations like POST, PUT, MERGE and so on. With the help of this tool you can easily make sure that your OData service is performing correctly, that your server settings are correct and you can simulate client data modifications without using app code to do the same.

Wow, this sounds great, but where is this tool and how can I use it?

Once you have installed the SAP Mobile Platform SDK you can find it in

 

$ ~/SAP/MobileSDK3/Tools/bin

and it is called ilodata.

If you have installed the SDK into another path, you’ll need to search accordingly. Oh, and on Windows it called ilodata.exe.

On your Mac you would first make it an executable by typing:

 

$ chmod +x ./ilodata

For your convenience I’d recommend to create a symlink in /usr/local/bin by

 

$ sudo ln -s ~/SAP/MobileSDK3/Tools/bin/ilodata /usr/local/bin/ilodata

Now navigate your user’s directory and create a new folder or create the directory wherever you think would it would be appropriate. Here create an empty working directory and navigate into it and start ilodata:

 

 

$ mkdir offlinedebug

$ cd offlinedebug

$ ilodata

Oh what was that… I can’t read that fast. So let’s scroll up again and read the text together:

 

Interactive Local OData Tool Version 17.0.3.4520

USAGE:

   ilodata.exe -?|--help|[option=name [option=name ...]]

Interactive Local OData (ILOData) lets you execute OData queries against an UL database.If the database exists, ILOData will just use it. If not, it will do a refresh to create the database. To do a refresh, at least defining_request and serviceRoot must be set. If no defining requests are specified on the command line and no store exists, the user will be prompted to enter defining requests before ILOData opens the store.

Many of the options correspond to settings in the Offline Store Options.

Please see the Offline OData SDK API documentation for additional details

Ok, now we know that ilodata stands for Interactive OData. That sounds promising, but how to get started?

In order to use ilodata you need to provide exactly the same configuration parameter we use for creating an offline store (Don’t worry if you don’t know the parameters, we’ll come to them in a minute).

But the text above holds some valuable information. First, it explains how to add options to the command line by using the option=name syntax. Second, it tells us that it is using version 17 and this has a deeper meaning, that I’ll explain later. And finally it points us to the documentation and to make it more comfortable for you here’s the direct link to SAP Help

 

Don’t click it now, just stay with me a bit longer, please.

 

Before we can use ilodata we need to have a proper server setting in place – you may know that the offline capabilities are mainly managed by the server and therefore we can’t leave him behind. A minimal App setting in your HANA Cloud Platform mobile service for development and operations should suffice. So open the mobile service Admin Cockpit and create an app config with the name OfflineApp and point its primary connection to http://services.odata.org/V2/northwind/Northwind.svc/ and set Proxy Type to Internet. It does not matter if you have chosen a native or hybrid app in this case. Please choose None as the security configuration. (ilodata works with credential-based authentication as well as with certification based security, but for debugging purposes we can often turn off the security)

 

APPID

OfflineApp

                                                      Primary Back-end URL

http://services.odata.org/V2/northwind/Northwind.svc/

Proxy Type

Internet

Security Configuration

None

 

This is how your App overview screen should look like:

Picture1.png

Now that we have a server configuration we need to create an APPCID (Application Connection) for this app. We can do this with curl (you may want to use Postman for Google Chrome or use any other tool that can create HTTP request for you)

 

$ curl -X POST https://hcpms-{SCNUSER}trial.hanatrial.ondemand.com/odata/applications/v4/OfflineApp/Connections -d '{}' -c hcpmscookie.txt -v -H "Content-Type: application/json"

You need to substitute your SCN username into {SCNUSER} above.

Once you execute this, you’ll get a lot of xml back, but for now we can just ignore this and just have a look into the hcpmscookie.txt file:

 

$ cat hcpmscookie.txt

Copy the APPCID GUID value into another text file or keep in your clipboard. Of course, if you are really really smart, you just can just memorize it. We need it now.

 

In a typical debugging situation, you don’t need to do all the steps, you would probably already have an APPCID and an app configuration on mobile services for development and operations.

 

Now, let’s use ilodata:

 

$ ilodata service_root=OfflineApp host=hcpms-{SCNUSER}trial.hanatrial.ondemand.com store_name=products defining_request=Products port=443 enable_https=yes appcid={APPCID} enable_debug_logging=true

Uh, that’s not trivial. Let’s quickly discuss all the options:

 

First, service_root should point to the OData Service Document. It does by being the APPID we defined earlier.

The host is pretty straightforward, it’s the server URL. Please make sure you substitute {SCNUSER} with you SCN username.

The store_name will reference your local UltraLite database.

You can have more than one defining_request, just use the option defining_request again to have more than one. The parameter itself refers to an OData collection name, no slashes.

Port is the server port of the host, on HCP it’s always 443.

When the port is 443, you should set enable_https to yes as seen above. Appcid defines the registration id we just found in the hcpmscookie.txt, I’m pretty sure you remember.

The last option enable_debug_logging is set to true, it’s self-explanatory.

 

If you execute the command, you’ll see a lot of things going on (well, only if you are not behind a proxy – make sure you have “unproxied” internet access to use ilodata), but the last lines should look like this:

 

 

 

Perform the reapply ...

Commit the download ...

Refresh complete.

Store state: Open

 

ILOData >

 

That’s it. Now you have created an offline store which you can query and modify.

 

Try :

 

 

ILOData > get Products

ILOData > help

ILOData > exit


Not bad, but this is not the end of the story. In your directory you’ll find to .db files:

 

  1. products.rq.udb and products.udb. The first holds all modifications from CUD operations, which you can “flush” to the server, while the later holds all the “refresh” data – everything you read from the server. Of course you can copy your devices db files into the folder and check their content with ilodata (in case of encrypted stores you need to somehow know the secret key and pass it as store_key parameter).

 

 

I hope this tool will help you in times where you really need to dig into your data and get a better understanding of what’s going on under the hood.

 

Now, it’s time to check the help document.

 

Have Fun,

Martin

Unleash the Power of Mobile with Swift and the SAP Mobile Platform SDK

 

Attention: This is not an article about the announces SAP HANA Cloud Platform SDK for iOS, which is part of the Apple SAP partnership. This article refers to the already existing SAP Mobile Platform SDK that supports SAP Mobile Platform and SAP HANA Cloud Platform mobile service for development and operations (previously: SAP HANA Cloud Platform mobile services)

 

Using Apples new and modern programming language Swift can really improve developer efficiency. SAP has the SAP Mobile Platform SDK that let you consume SAP Mobile Platform or SAP HANA Cloud Platform mobile service for development and operations features, like on-boarding, push notifications, client log upload and of course it enables you to create heavy weight offline applications.

The next steps show you how you combine Apples powerful Swift language with the SAP Mobile Platform SDK and start a blank iOS project from scratch. It’s easier than you may think.

 

Prerequisites

 

Please make sure your system mets the following requirements:

 

Getting Started

Well, I don’t think that I need to explain much about how to install Xcode.

 

To install pod use this command on your Terminal

 

$ sudo gem install cocoapods

Try

 

$ pod --version

on your Terminal to validate your installation.

 

The SAP Mobile SDK is a download on https://www.sapstore.com/solutions/701697/SAP-Mobile-Platform

Unzip the downloaded file and

 

 

$ chmod +x installSDK.command

$ ./installSDK.command

I assume that you chose the default installation path ~/SAP/MobileSDK3.

In your Terminal navigate to your folder ~/SAP/MobileSDK3/NativeSDK.

There is a file called “NativeSDK.podspec”. This file describes the Native SDK as a dependency for cocoapod. We need to modify the file and append a bit more information. Open the file in your favorite text editor and add:

 

s.authors = ['Yourname']

s.homepage = "http://www.yourwebsite.com"

s.source = { :path => '~/SAP/MobileSDK3/NativeSDK/OdataFramework/*'}


just between the lines to the other attributes.

 

Save your file.

 

Now start XCode and create a new Swift project:

 

Picture1.png

Make sure you select Swift as a Language.

Well, now close the project. Serious, just close XCode.

 

In your Terminal navigate to your freshly create XCode project. Type

 

$ pod init

 

Now you will see a file called “Podfile”, without extension.

Open it in your favorite text editor and include the following line

 

$ pod 'NativeSDK', :path => "~/SAP/MobileSDK3/NativeSDK/"

 

before the closing “end” statement. Then just close the file.

This concludes the preparations, now to the last step.

Back in your project path, just type in your Terminal:

 

 

$ pod install

 

In your project folder the you’ll find now the file {Projectname}.xcworkspace. This is the file you will now open in Xcode and use whenever you want to work on your project.

 

Your project should now look like this:

Picture2.png

Your project – in my case it’s “OfflineSwiftSDK12” and it references “Pods” which holds all your NativeSDK files.

 

You may notice the file “OfflineSwiftSDK12-Bridging-Header.h”. This is a very important file since it defines the communication between Objective-C resources and Swift. Whenever you want to reference an object that is provided by the SAP Mobile SDK you need to specify the relevant header files. You need to create the file manually. Just go to “File” > “New” > “File…”, then choose “Header File”, name it: {PROJECTNAME}-Bridging-Header.h

This is how your bridging file could look like:

//

//  OfflineSwiftSDK12-Bridging-Header.h

//  OfflineSwiftSDK12

//

//  Created by Grasshoff, Martin on 08/06/16.

//  Copyright © 2016 Grasshoff, Martin. All rights reserved.

//

 

#ifndef OfflineSwiftSDK12_Bridging_Header_h

#define OfflineSwiftSDK12_Bridging_Header_h

 

#import "SODataOfflineStore.h"

#import "SODataOfflineStoreOptions.h"

#import "HttpConversationManager.h"

#import "UsernamePasswordProviderProtocol.h"

#import "CommonAuthenticationConfigurator.h"

 

#endif /* OfflineSwiftSDK12_Bridging_Header_h */

 

You don’t need to import all header files of the SDK, only the files which references the Objects you want to use in your code.

The last step is to tell your build that it should use the bridging header. Select your project in the project inspector, select your Target and finally select your “Build Settings”. Now scroll down in the list until you find the section “Swift Compiler Code Generation”, here point your Objective-c bridging header property to ${SRCROOT}/OfflineSwiftSDK12-Bridging-Header.h

 

That’s it, now you can build your app and all the NativeSDK is at your fingertips.

 

Next action item for you is to actually use the SDK.

I’m looking forward to see your Swift-based projects.

 

 

Have Fun,

Martin Grasshoff

Hi,

I’m running late this month, but this is because we are preparing great new things for mobile at the moment. Some we small appetizers we released with 1605

 

  • Cross-origin resource sharing
  • Username propagation to back-end systems
  • Reports based on client usage data
  • Sharing of SCIM destinations

 

Cross-origin Resource Sharing

This new feature let you set CORS headers via configuration. Available settings are:

Picture1.png


Read more about CORS here:
http://www.w3.org/TR/cors

 

Username propagation to back-end systems

 

This particular feature is one of my favorites this release. It’s a pretty simple thing, once select “Propagate User Name” it means that to each back-end request there will be a “X-SMP-ENDUSERNAME” header added, which contains the username, which was retrieved by the selected authentication channel (e.g. SAML).

And what is it good for? Well, your back-end system can now add this user information to apply additional filters on the data to retrieve. The client can’t manipulate this header and impersonate another user with a valid authorization.

For instance, I could send the following request:

 

GET /userprofiles/ABC

 

even though my own user is “XYZ”. The back-end know can make sure that a use XYZ is not allowed to call resources belonging to ABC.

And you would use this features whenever, for any reason, you do not propagate the actual user context to the back-end and use a technical user.

Picture2.png

Reports Based on Client Usage Data

 

With our SDK you can measure the usage of your app, until now we just provided you the information as raw data for further processing with SAP Lumira, or other tools.

With this release we also provide five different pre-defined reports:

Picture3.png

 

Once you upload your usage data to the service, you can just navigate to “Reporting” and select “Client Log Data”, then select the timeframe and report you want to see.

And here is an example:

Picture4.png

Sharing of SCIM destinations

 

Well, that’s simple. Rather than specifying a new Connection for each app-specific SCIM destination, you simply select one of the associated Connections you already have.

The workflow is simple. Just click “Override Global HCPms SCIM Configuration”, then select one of the connections you want to reuse for SCIM.

Typically, you would just re-use your OData Service Document already defined at the top of the screen – unless you have a helpful ping-service – so, click on “Save” first, then the list is populated.

Picture5.png

That’s it for now.

 

Have fun,

Martin Grasshoff

It is possible to start/stop SMP services via Task Scheduler. I followed this discussion to try this out. Wanted to share my findings on this:


Note:

  • This was done just to test how SMP start/stop services could be planned for a given schedule.
  • If you are using a custom database with SAP Mobile Platform, starting and stopping SAP Mobile Platform Server has no effect on the database. Only the

default SAP SQL Anywhere database is automatically stopped and started in sync with SAP Mobile Platform Server (Ref. help.sap.com)

 

Pre-requisite: 1. SMP runtime should be installed on your machine (or should have remote access to the system)

                       2. Local Administrator role

                       3. SMP services should not be running and their Startup Type should be set to manual. (CTRL+R->services.msc)

 

1.png

 

Steps:

 

1. open 'Task Scheduler' (OR CTRL+R ->taskschd.msc )

     2.png

 

2. Action->Create Basic Task

3.png

 

 

3. Since i just wanted to test how this would work, i triggered it with 'One time' option

6.PNG

 

4. Here, i had to give date-time to run this task (it may vary for the options selected in step# 3)

 

7.PNG

5. No more choice here, just select first option

24.PNG

 

6. Point to go-service.bat batch command SMP installation path)

 

26.PNG

7. Make sure to select checkbox

28.PNG

 

8. As you click on 'Finish', properties dialog box appears. Make sure to select 'Run with highest privileges' option

11.PNG

 

9. I could see command window appearing on my machine on the time as set during Step# 4 . It took a while to start SMP services.

 

 

30.PNG

 

Note: verify SMP Services again in services.msc

 

21.PNG

 

Note: There is a way to delete this schedule task, search your task under 'Active Tasks' list, double click on it ->Delete

(for modify schedule timing, look under Actions)

13.PNG

10. Same way, task can be created to STOP SMP services. Point to stop.bat file.

 

14.PNG

 

 

29.PNG

 

To confirm this, open services.msc->

 

23.PNG

 

 

 

Hope this helps.

 

Thanks Wayne Smith for your inputs.

 

Regards,

JK

Are you using SAML authentication flow in your SMP 3.0 application? Is that generated certificate self-signed one (by SMP itself) ? Did you already know its expiration date? Or has it already expired? And now, user can't be on-boarded on SMP.

 

(we had same situation. So hereby, i am sharing what all we did to get rid of it)

 

There are many blogs on how SAML Flow works and how to configure it. I am not going to explain it here.

 

In order SAML flow to work, initially, metadata file of Local service provider (here its SMP) needs to be shared with Identity provider team. You provide a LSP name, Base URL (e.g. https://server:port).

Next, what about values for signing key and signing certificate?

 

Option A: Either you can go with by just clicking on 'Generate key pair' option to get these values filled automatically (SMP does this work) Not recommended for productive environment

Option B: Generate these values from a Certificate Authority (recommended for productive environment)

LSP1.png

 

Option A:

 

In this case, from where SMP takes default inputs and generate self signed certificate?

 

To check this, Go to Settings > System > scroll down > SAML SERVICE PROVIDER CERTIFICATE GENERATOR SETTINGS

 

certificatesettings.PNG

Here you can see that, there are default values for the subject, certificate is valid only for 1 year

 

(you still not sure when that generated certificate is going to be expired, here is a quick way to check. Copy the 'Signing certificate' content in a notepad and save it as .cer , double click on certificate file)

 

We were told by IdP team that they are seeing error with the SMP LSP metadata file.

 

Unable to validate SAML2 Trusted Service Provider. The trusted relationship with this entity will not be functional!
Error Validating X509 Certificate of Trusted Provider
Trusted Provider Type: SAML2 Trusted Service Provider
Trusted Provider Id: SAMLTEST
Error Validating X509 Signing Certificate
X509 Certificate Version: 3
X509 Certificate Subject: C=DE L=Walldorf O=SAP SE
X509 Certificate Issuer: C=DE L=Walldorf O=SAP SE
X509 Certificate Serial Number: xxxxx
X509 Certificate Start Date: 2015-05-20 10:18:28
X509 Certificate Expiration Date: 2016-05-20 10:18:28

X509 Certificate Validation Root Exception: com.novell.nidp.NIDPException: Certification path could not be validated. Could not validate certificate: NotAfter: Fri May 20 10:18:28 CEST 2016 Root Cause: java.security.cert.CertPathBuilderException: Certification path could not be validated.

Then we figured out the issue (already highlighted above) that generated certificate had expired.

 

How to renew it?

 

  1. Increase number of years to 1 or 2 or as much as you want
  2. Save it
  3. Generate new keypair
  4. download new metadata file
  5. share it with IdP team

 

Note: Even you can provide your company specific subject also (we went with default parameters)

certificatesettings1.png

 

Before step#4, download new metadata file, you can validate above settings:

    • Copy signing  certificate content in a notepad
    • save it with .cer extension
    • double click on it and confirm

 

     cert.PNG

Here, everything looks fine and now you can share new metadata file with IdP team.

 

Option B: Talk to your CA team.

 

Hope this helps.

 

Thanks Andreas Wegmann for your inputs.

 

Regards,

JK

Hi,

In March we present the following additions to Mobile Services

 

  • New Name!
  • New push features
  • Custom push provider
  • HANA Cloud integration services integration
  • Custom URL rewrite rules
  • Removal of inactive users – save your licenses!

New Name

Going forward you will see HANA Cloud Platform mobile services to become the umbrella term for all mobile related services on SAP HANA Cloud Platform. Therefore, HCP mobile services needs to be renamed. The new official product name is

“SAP HANA Cloud Platform mobile service for development and operations”

while the consumer edition is called:

“SAP HANA Cloud Platform mobile service for development and operations, consumer edition”.

 

We will gradually roll out this name in the product and in the documentation, so please don't be surprised. This is how it looks like now in HCP Cockpit (HCPms is now "Development & Operations"-tile:

 

HCPms_NewName.png

 

New Push Features

All native notification venders improve their services all the time and so do we.

In this release we have included support for:

Google Notifications:

  • Resend Messages – allows to automatically resend messages under certain conditions when a message could not be delivered
  • Logging GCM error codes in the event log

Apple Push Notifications:

  • Support for title, title-loc-key and other additional attributes to better control notifications on iOS devices

WNS:

  • Custom payload handling for individual WNS notifications

 

Custom Push Provider

The custom push provider substitutes the HCP mobile services implementation for push services with custom coding.

While configuring your app definition, you can multi-select your custom push provider URL for each device platform. For example, you can define a custom push provider URL for Android. Once you do this, HCP mobile services disables the the Android specific configuration for Android notifications. All Android related push events will then be forwarded to your provided URL – which is typically an HCP provided java application that handles the push for you.

This feature is very suitable, when you want to substitute the native push provides of the device venders.

This is how it looks like:


Picture1.png


HANA Cloud Integration services integration

SAP HANA Cloud integration services integration – sounds funny and is an unlucky wording, but it describes best what has happened. Last month, our colleagues of HANA Cloud Integration services have released their new feature set to allow to transform non OData services into OData feeds. In order to consume those published OData services, we have built a small, but shiny integration to your HANA Cloud Integration content:

Picture2.png

Once you have done all your integration work and published your service, just click the “Add…” button and select your service from the list. Provide the necessary authentication information and you will be able to access your service from your mobile app.

 

Custom URL Rewrite Rules

With this version we allow you to provide your own custom http payload rewrite rules. Typically, we rewrite URLs that appear in an OData service to an HCPms URL. In a given OData feed, each URL would be rewritten from “http://services.odata.org/V2/northwind/Northwind.svc/Regions(1)” to

https://hcpms-dXXXXXXtrial.hanatrial.ondemand.com/PMAPP/Regions(1)</id>”. with the new custom URL rewrite rules, you can completely control the way URLs in the payload should be rewritten.

Just select “Custom Rewrite URL” as Rewrite Mode.

Picture3.png

Then click “Configure URLs” to manage your custom rules:

Picture4.png

 

You can even provide regular expressions and test them online:

 

Picture5.png

 

This is clearly for the advanced user.

 

Removal of Inactive Users

After a period of three months, unused APPCID (registered users) will be inactivated, saving user licenses. No more to say about this feature.

 

 

Have fun,

Martin Grasshoff

The contents of this tutorial were based on another blog post: „SAP OData SDK Android for absolute beginners – Part 1” written by Peter Csontos, available on the following link: http://scn.sap.com/community/developer-center/mobility-platform/blog/2015/11/11/sap-odata-sdk-android-for-absolute-beginners-part-1

 

My post will help you to learn about the following in the least advanced way possible:

     -SAP Mobile Platform SDK for iOS

     -How to use the OData API to create an online store

     -Using Cocoapods to install dependencies for your project

 

You can think of my tutorial as an environment kickstarter for the OData SDK on iOS. If you feel like learning about the use of OData SDK itself would be more appropriate, I highly recommend you to check out the posts of Kenichi Unnai who has already written a series of posts on that topic, suitable for both beginners and more advanced. You can start with the one below:

http://scn.sap.com/community/developer-center/mobility-platform/blog/2014/09/16/smp3-odata-sdk-for-ios--tips-tricks-01

 

 

After you have finished following my instructions in this tutorial, you will end up with a project similar to a „Hello World” for OData on iOS, if there was such a thing. In order to start, you only need basic knowledge of programming in Objective-C or Swift, using Xcode, RESTful web services and the OData protocol. You also need an Xcode installed on your Mac. If I managed to keep you interested, let's start!

 

 

Step 1: Install SAP Mobile Platform SDK for iOS

In case you don't have an SMP SDK already installed on your computer, this link will give you what you need to know: https://help.sap.com/smpsdk_re . The download and install process may provide you enough time to continue with the next two steps.

 

 

Step 2: Create a new iOS project in Xcode

Fortunately, you can choose between Swift and Objective-C languages for your project, because this tutorial covers both. Since Swift language is the future and the number of developers actively using it is highly growing, so despite its early problems it should be practiced in new projects as much as possible. Of course, you may need to (or want to) write your code in Objective-C. As a template, I used a single-view application for my project, but you can choose another for yours as you prefer. In the next steps I will refer to your project location as $PROJECTLOCATION, which by default  contains the project file with extension .xcodeproj.

 

 

Step 3: Disable App Transport Security

When building iOS apps using iOS 9 SDK, App Transport Security is enabled by default. ATS uses the TLSv1.2 protocol which converts all HTTP requests to HTTPS. Any attempts to connect to a server which does not support HTTPS protocol, or only supports TLS protocol older than v1.2 will fail. Since the reference services located at odata.org (and perhaps the service you want to use) only support HTTP, you have to disable ATS.

 

In the $PROJECTLOCATION/$PROJECTNAME folder an Info.plist file was automatically generated. Open it and add a new dictionary called "App Transport Security Settings" and create a new entry with key "Allow Arbitrary Loads" and value "YES". Here's a screenshot of how it should look:

 

Screen Shot 2016-03-24 at 11.30.12 AM.png

 

Please note: disabling ATS is not recommended in most cases, so if you only connect to servers capable of using HTTPS protocol, leave it enabled.

 

Step 4: Setup project dependencies

I used Cocoapods to configure dependencies, but in case you don't want to use Cocoapods or something didn't work out with my steps, you can find another and more detailed tutorial here: http://help.sap.com/saphelp_smp3010sdk/helpdata/en/49/cc45e254f4492393801fc17391602f/content.htm

 

Here is how to do it with Cocoapods:

  -Close your project.

  -If not present, install Cocoapods by using the "gem install cocoapods" command in Terminal. Use "sudo" if needed and also note: some firewalls won't let gem to download. If you encounter any problems, connect to another network and try again.

  -In your terminal navigate to the $PROJECTLOCATION directory (or the location of your project file with extension .xcodeproj if not present by your settings) and use command "pod init". This will create a Podfile which you could have created yourself, but this way it will contain a template instead of being empty.

  -Open that Podfile in a text editor and you should create a content equivalent to the snippet below, or you can just copy-paste it. Note that $SMPSDKLOCATION is the path to your installation folder of the SAP Mobile Platform SDK and $PROJECTNAME is your project name which you should overwrite according to your environment.

 

##################################

platform :ios, "8.0"

target "$PROJECTNAME" do

inhibit_all_warnings!

pod 'NativeSDK/ODataOnline', :path => "$SMPSDKLOCATION/SAP/MobileSDK3/NativeSDK"

pod 'NativeSDK/ODataAPI', :path => "$SMPSDKLOCATION/SAP/MobileSDK3/NativeSDK"

end

##################################

 

 

  -Save the Podfile, run "pod setup" from Terminal.

  -If it succeeded, run "pod install"

 

If you encountered network related problems while executing the commands above, connect to another network and try again. If both have succeeded, the new file with the .xcworkspace extension is now your working area instead of the .xcodeproj file.

 

 

Step 5: Write your code

Now we only need some code to try if the OData SDK is working as intended. Open the .xcworkspace you have just created with Cocoapods. I suggest you to create a new file for the tester class and use a button to allocate and execute the test. In my example I pasted the code into the view controller class, which should always be avoided, but it helps to simplify my code snippet here. So let's start!

 

 

A: The Swift way

The SMP SDK for iOS was written in Objective-C which means you have to create a bridging header to import the files you need. If you are unsure how to do so, you can follow the official Apple tutorial.

Now import these headers in your new bridging header:

 

#import "SODataRequestParamSingleDefault.h"

#import "SODataResponseSingleDefault.h"

#import "SOData.h"

#import "SODataEntitySetDefault.h"

#import "SODataEntityDefault.h"

#import "SODataPropertyDefault.h"

#import "SODataOnlineStore.h"

 

 

Open the Swift file you want your OData online store to run from. For me it was ViewController.swift, but you should create your own empty class. Now start with the following definition:

 

var store : SODataOnlineStore!

 

 

Thanks to this first line, we can make sure both the pods and the bridging header were set up correctly. Jump to the definition of SODataOnlineStore (command-click by default). If you only see a big question mark, something went wrong. If it works, you can follow it with an optional UITextView object referenced from your storyboard and a String as its buffer. We will use them to inform ourselves on the screen if we managed to open the online store and it also displays the first entity to confirm our success in a more satisfying way. Error messages will also appear here if there were any. However, you can use NSLog for this purpose if you want to, but an UITextView object is easy to implement while being more elegant, plus you can drop your NSError right into it. So here go my two lines:

 

@IBOutlet var logDisplay: UITextView!

var log : String = ""


 

Our first method which opens the OData online store, needs a HttpConversationManager object in order to manage data traffic via the internet, since OData transfers data via HTTP or HTTPS as you may already know. Thanks to this manager, we don't have to worry about the details of these protocols after initializing it. Authentication is also not needed, since we will use a public reference service provided by odata.org. If you need to add authentication for services with such requirement, I suggest you to check out Kenichi Unnai's tutorials mentioned at the beginning of this post. The initialization of HttpConversationManager is as simple as this:

 

func openStore() {

     let manager = HttpConversationManager()


 

You need to specify the URL where the service is located. We will use one of the OData V4 reference services located at odata.org, but you will find other available services there, if you need to test your program with different, more advanced OData properties.

 

let url = NSURL(string: "http://services.odata.org/V4/OData/(S(readwrite))/OData.svc/")


 

Now we can initialize the online store with all its settings:

 

store = SODataOnlineStore(URL: url, httpConversationManager: manager)

 

 

The online store is initialized, it is ready to be opened. We will invoke the completion block version of the openStore method:

 

store.openStore { (store, error) -> Void in


 

Now that it's finished and we are in the completion block, we can invoke the method containing our first request in it. But before doing so, I suggest we  check if there was any error, and inform the user about it:

 

    if(error == nil){

        self.testREAD()

    } else {

        self.log = "FAILED TO OPEN STORE. ERROR: " + String(error)

        self.logDisplay.text = self.log

    }

}

}

 

 

At this point our online store is open, if there was no issue with connecting to the OData service. Let's implement the new testREAD method invoked in the code snippet above with a READ request in it.

 

func testREAD(){

 

Before executing the READ request, we have two essential arguments to set: the type of the request (READ, CREATE, etc.)  and the path of the resource we want access to:

 

let requestParam = SODataRequestParamSingleDefault(mode: SODataRequestModeRead, resourcePath: "Suppliers")


 

Thanks to the convenient interface, we only needed this line above to perform necessary initialization before actually making the request:

 

store.scheduleRequest(requestParam, completion: { (requestExecution, error) -> Void in


 

As you noticed, we use a completion block again to confirm the success of our request. Now we expect not only an error, but also a response with a payload which may or may not contain an entity set. But if an error has occurred, we may not even have a response or a payload. We should be cautious about these cases and everything should be checked in the right order. Thanks to the Swift language, setting the entity set and checking it's only one line:

 

if(error == nil){

    let responseSingle = requestExecution.response as! SODataResponseSingle

    if let entitySet = responseSingle.payload as? SODataEntitySet{

 

 

If both if-s evaluated to true, everything must be in order. But we like to see some result, so let's display what our entity set contains! The "Address" property is complex type, which needs some extra work to display properly:

 

self.log += "\nREAD SUCCEEDED.\n\nFirst entity in entityset \"Suppliers\":"

let readEntity = entitySet.entities[0] as! SODataEntityDefault

var readProperty = readEntity.properties["ID"] as! SODataPropertyDefault

self.log += "\n" + String(readProperty.name) + ": " + String(readProperty.value)

readProperty = readEntity.properties["Name"] as! SODataPropertyDefault

self.log += "\n" + String(readProperty.name) + ": " + String(readProperty.value)

readProperty = readEntity.properties["Concurrency"] as! SODataPropertyDefault

self.log += "\n" + String(readProperty.name) + ": " + String(readProperty.value)

readProperty = readEntity.properties["Address"] as! SODataPropertyDefault

self.log += "\n" + String(readProperty.name) + ": {"

let complexProperty = readProperty.value as! NSDictionary

for ( key, innerProperty ) in complexProperty {

     if let propertyValue = (innerProperty as? SODataProperty)?.value {

          self.log += "\n\t" + String(key) + ": " + String(propertyValue)}

     }

self.log += "\n}"

}

 

The buffer is now ready to be sent to display, but remember that we still have else branches left to implement for both if-s: in the inner else payload is not an entity set, in the outer one error is not nil.

 

  } else {

                    self.log = "\nERROR IN READ: RESPONSE NOT AN ENTITY SET"

                }

        } else {

            self.log = "\n\nERROR IN READ: " + String(error)

        }

        self.logDisplay.text = self.log

    } )//Completion block ends here

}//testREAD ends here

 

Finally, make sure to invoke the openStore method to start your test. I created a button and sent an action:

@IBAction func buttonPressed() {

    self.openStore()

}

 

That's all we needed to do to test the minimal OData online store. To make copy-pasting easier for you, here are the imports, declarations and the two methods without the need of formatting:

 

For your bridging header:

#import "SODataRequestParamSingleDefault.h"

#import "SODataResponseSingleDefault.h"

#import "SOData.h"

#import "SODataEntitySetDefault.h"

#import "SODataEntityDefault.h"

#import "SODataPropertyDefault.h"

#import "SODataOnlineStore.h"

 

 

For your new class or view controller:

var store : SODataOnlineStore!

@IBOutlet var logDisplay: UITextView!

var log : String = ""

 

func openStore(){

    let manager = HttpConversationManager()

    let url = NSURL(string: "http://services.odata.org/V4/OData/(S(readwrite))/OData.svc/")

    store = SODataOnlineStore(URL: url, httpConversationManager: manager)

    store.openStore { (store, error) -> Void in

        if(error == nil){

            self.testREAD()

        } else {

            self.log = "FAILED TO OPEN STORE. ERROR: " + String(error)

            self.logDisplay.text = self.log

        }

    }

}

 

func testREAD() {

    let requestParam = SODataRequestParamSingleDefault(mode: SODataRequestModeRead, resourcePath: "Suppliers")

    store.scheduleRequest(requestParam, completion: { (requestExecution, error) -> Void in

    if(error == nil) {

        let responseSingle = requestExecution.response as! SODataResponseSingle

        if let entitySet = responseSingle.payload as? SODataEntitySet {

            self.log += "\nREAD SUCCEEDED.\n\nFirst entity in entityset \"Suppliers\":"

            let readEntity = entitySet.entities[0] as! SODataEntityDefault

            var readProperty = readEntity.properties["ID"] as! SODataPropertyDefault

            self.log += "\n" + String(readProperty.name) + ": " + String(readProperty.value)

            readProperty = readEntity.properties["Name"] as! SODataPropertyDefault

            self.log += "\n" + String(readProperty.name) + ": " + String(readProperty.value)

            readProperty = readEntity.properties["Concurrency"] as! SODataPropertyDefault

            self.log += "\n" + String(readProperty.name) + ": " + String(readProperty.value)

            readProperty = readEntity.properties["Address"] as! SODataPropertyDefault

            self.log += "\n" + String(readProperty.name) + ": {"

            let complexProperty = readProperty.value as! NSDictionary

            for ( key, innerProperty ) in complexProperty {

                if let propertyValue = (innerProperty as? SODataProperty)?.value {

                    self.log += "\n\t" + String(key) + ": " + String(propertyValue)

                }

            }

            self.log += "\n}"

        } else {

            self.log = "\nERROR IN READ: RESPONSE NOT AN ENTITY SET"

        }

    } else {

        self.log = "\n\nERROR IN READ: " + String(error)

    }

        self.logDisplay.text = self.log

    } )//Completion block ends here

}//testREAD ends here

 

 

B: The Objective-C way

Open the Objective-C file you want your OData online store to run from (for me it was ViewController.m, but you should create your own empty class).

First you need to import several headers:

 

#import "SODataRequestParamSingleDefault.h"

#import "SODataResponseSingleDefault.h"

#import "SOData.h"

#import "SODataEntitySetDefault.h"

#import "SODataEntityDefault.h"

#import "SODataPropertyDefault.h"

#import "SODataOnlineStore.h"

 

 

We will also need the following properties:

 

@property (nonatomic, strong) SODataOnlineStore* store; //Online store as an object

@property (nonatomic, strong) id<SODataEntitySet> entitySet; //We will check the data we acquired by the READ request

@property (nonatomic, strong) NSMutableString *log; //We will append log messages to this object

@property (nonatomic, strong) IBOutlet UITextView *logDisplay; //Display the log (occasional refresh needed)

 

 

The UITextView object above is optional: we use it to inform us on the screen if we managed to open the online store. It also displays the first entity to confirm the success in a more satisfying way. Error messages will also appear here if there were any. However, you can use NSLog for this purpose if you want to, but an UITextView object is easy to implement while being more elegant, plus you can drop your NSError right into it. I also @synthesize-d all properties for a more pleasant code.

With the headers imported and the declarations in place, let's start implementing the first method which opens the OData online store:

 

- (void)openStore{

 

 

We need to init our log, because the first place to be accessed from is uncertain.

 

log = [[NSMutableString alloc] init];


 

Now we will use HttpConversationManager in order to manage data traffic via the internet, since OData transfers data via HTTP or HTTPS as you may already know. Thanks to this manager, we don't have to worry about the details of these protocols after initializing it. Authentication is also not needed, since we will use a public reference service provided by odata.org. If you need to add authentication for services with requirement such this, I suggest you to check out Kenichi Unnai's tutorials mentioned at the beginning of this post. The initialization of HttpConversationManager is simple as this:

 

HttpConversationManager* manager = [[HttpConversationManager alloc] init];


 

You need to specify the URL where the service is located. We will use the V4 reference service located at odata.org, but you can find several other reference services there, if you need to test your program with different, more advanced OData properties.

 

NSURL* url = [NSURL URLWithString:@"http://services.odata.org/V4/OData/(S(readwrite))/OData.svc/"];


 

Now we can initialize the online store with all its settings:

 

store = [[SODataOnlineStore alloc] initWithURL:url httpConversationManager:manager];


 

The online store is initialized, it is ready to open. We will invoke the completion block version of the openStore method:

 

[store openStore:^(id<SODataStoreAsync> store, NSError *error) {

 

 

Now that it's finished and we are in the completion block, we can invoke the method containing our first request in it. But before doing so I suggest we should check if there was any error and inform the user about it:

 

if(!error) {

  [self testREAD];

} else {

  [log appendString:[NSString stringWithFormat: @"\nFAILED TO OPEN STORE: %@",(id)error]];

  logDisplay.text = log;

}

}];

}

 

 

At this point our online store is open, if there was no issue with connecting to the OData service. Let's implement the testREAD method invoked in the code snippet above with a READ request in it:

 

- (void)testREAD {

 

Before executing the READ request, we have two essential arguments to set: the type of the request (READ, CREATE, etc.)  and the path of the resource we want access to:

 

SODataRequestParamSingleDefault *requestParam = [[SODataRequestParamSingleDefault alloc] initWithMode:SODataRequestModeRead resourcePath:@"Suppliers"];

 

Thanks to the convenient interface, we only needed this line above to initialize every essential data to actually make the request:

 

[store scheduleRequest:requestParam completion:^(id<SODataRequestExecution> requestExecution, NSError *error) {

 

 

As you noticed, we use a completion block again to confirm the success of our request. Now we expect not only an error, but also a response with a payload which may or may not contain an entity set. But if an error has occurred, we may not even have a response or a payload. We should be cautious about these cases and everything should be checked in the right order.

 

if(!error){

        id<SODataResponseSingle> responseSingle = (id<SODataResponseSingle>)requestExecution.response;

        if ([responseSingle.payload conformsToProtocol:@protocol(SODataEntitySet)]){

 

 

If both if-s evaluated to true, everything must be in order. But we like to see some result, so let's display what that entity set contains! The payload contains the entity set and we only want to see the first object in it. Here we can also inform ourselves about the success of the READ request, but for now we only need it in our buffer:

 

[log appendString:@"\nREAD SUCCEEDED.\nFirst entity in entity set \"Suppliers\":"];

entitySet = (id)responseSingle.payload;

SODataEntityDefault* readEntity = (SODataEntityDefault *)entitySet.entities[0];

 

 

Now the properties of our entity are ready to be displayed. The "Address" property is complex type, which needs some extra work to display properly:

 

SODataPropertyDefault* readProperty = (id)readEntity.properties[@"ID"];

[log appendString:[NSString stringWithFormat: @"\n%@: %@", readProperty.name, readProperty.value]];

readProperty = (id)readEntity.properties[@"Name"];

[log appendString:[NSString stringWithFormat: @"\n%@: %@", readProperty.name, readProperty.value]];

readProperty = (id)readEntity.properties[@"Concurrency"];

[log appendString:[NSString stringWithFormat: @"\n%@: %@", readProperty.name, readProperty.value]];

readProperty = (id)readEntity.properties[@"Address"];

[log appendString:[NSString stringWithFormat: @"\n%@: {", readProperty.name]];

NSDictionary *complexProperty = (id)[readProperty value];

[complexProperty enumerateKeysAndObjectsUsingBlock:^(id key, id innerProperty, BOOL *stop) {

       [log appendString:[NSString stringWithFormat: @"\n\t%@: %@", key, [[(id<SODataProperty>)innerProperty value] description]]];

}];

[log appendString:@"\n}"];

 

The buffer is now ready to be sent to display, but remember that we still have else branches left to implement for both if-s: in the inner else payload is not an entity set, in the outer one error is not nil.

 

        } else {

                [log appendString:@"\nERROR IN READ: RESPONSE NOT AN ENTITY SET"];

        }

} else {

            [log appendString:[NSString stringWithFormat: @"\nERROR IN READ: %@",(id)error]];

}

logDisplay.text = log;

}];//Completion block ends here

}//Method testREAD ends here

 

 

Finally, make sure to invoke the openStore method to start your test. I created a button and sent an action:

- (IBAction)buttonPressed{

    [self openStore];

}

 

That's all we needed to do to test the minimal OData online store. To make copy-pasting easier for you, here are the imports, declarations and the two methods:

 

#import "SODataRequestParamSingleDefault.h"

#import "SODataResponseSingleDefault.h"

#import "SOData.h"

#import "SODataEntitySetDefault.h"

#import "SODataEntityDefault.h"

#import "SODataPropertyDefault.h"

#import "SODataOnlineStore.h"

 

@property (nonatomic, strong) SODataOnlineStore* store; //Online store

@property (nonatomic, strong) id<SODataEntitySet> entitySet; //We will check the data we acquired with the response

@property (nonatomic, strong) NSMutableString *log; //We will append log messages to this object

@property (nonatomic, strong) IBOutlet UITextView *logDisplay; //Display the log (occasional refresh needed)

 

@synthesize store;

@synthesize entitySet;

@synthesize log;

@synthesize logDisplay;

 

- (void)openStore{

    log = [[NSMutableString alloc] init];

    HttpConversationManager* manager = [[HttpConversationManager alloc] init];

    NSURL* url = [NSURL URLWithString:@"http://services.odata.org/V4/OData/(S(readwrite))/OData.svc/"];

    store = [[SODataOnlineStore alloc] initWithURL:url httpConversationManager:manager];

    [store openStore:^(id<SODataStoreAsync> store, NSError *error) {

        if(!error) {

            [self testRead];

        } else {

            [log appendString:[NSString stringWithFormat: @"\nFAILED TO OPEN STORE: %@",(id)error]];

            logDisplay.text = log;

        }

    }];

}

 

- (void)testRead {

    SODataRequestParamSingleDefault *requestParam = [[SODataRequestParamSingleDefault alloc] initWithMode:SODataRequestModeRead resourcePath:@"Suppliers"];

    [store scheduleRequest:requestParam completion:^(id<SODataRequestExecution> requestExecution, NSError *error) {

        if(!error){

            id<SODataResponseSingle> responseSingle = (id<SODataResponseSingle>)requestExecution.response;

            if ([responseSingle.payload conformsToProtocol:@protocol(SODataEntitySet)]){

                entitySet = (id)responseSingle.payload;

                [log appendString:@"\nREAD SUCCEEDED.\nFirst entity in entity set \"Suppliers\":"];

                SODataEntityDefault* readEntity = (id)entitySet.entities[0];

                SODataPropertyDefault* readProperty = (id)readEntity.properties[@"ID"];

                [log appendString:[NSString stringWithFormat: @"\n%@: %@", readProperty.name, readProperty.value]];

                readProperty = (id)readEntity.properties[@"Name"];

                [log appendString:[NSString stringWithFormat: @"\n%@: %@", readProperty.name, readProperty.value]];

                readProperty = (id)readEntity.properties[@"Concurrency"];

                [log appendString:[NSString stringWithFormat: @"\n%@: %@", readProperty.name, readProperty.value]];

                readProperty = (id)readEntity.properties[@"Address"];

                [log appendString:[NSString stringWithFormat: @"\n%@: {", readProperty.name]];

                NSDictionary *complexProperty = (id)[readProperty value];

                [complexProperty enumerateKeysAndObjectsUsingBlock:^(id key, id innerProperty, BOOL *stop) {

                    [log appendString:[NSString stringWithFormat: @"\n\t%@: %@", key, [[(id<SODataProperty>)innerProperty value] description]]];

                }];

                [log appendString:@"\n}"];

            } else {

                [log appendString:@"\nERROR IN READ: RESPONSE NOT AN ENTITY SET"];

            }

        } else {

            [log appendString:[NSString stringWithFormat: @"\nERROR IN READ: %@",(id)error]];

        }

        logDisplay.text = log;

    }];//Completion block ends here

}//testREAD ends here

 

 

Step 6: Run your code

 

If you managed to build your project successfully and run it, you should see something like this:

 

Simulator Screen Shot Apr 26, 2016, 2.10.07 PM.png

 

If something didn't work, make sure you have connected to a network with your device or emulator and make sure the firewall on your network lets the service through. Either you have questions about this tutorial, or you have valuable additional information or corrections, feel free to share your thoughts in the comment section below. Thank you!

Hello SMP Developers, Administrators

 

I would like to share my experience on current requirement for my project. There was already one OData native application available on SMP (with offline functionality).

Previous requirement: one offline application (with its ini file imported in Admin cockpit) connecting to one back-end URL. Things were fine.


New requirement: For next release of this mobile app, there should be a new backend URL but old one should also be there in the same app configration. It sounded like accessing more than one OData services in one application

 

So where was the problem?

 

You might have noticed that to make your app to work in offline mode, you have to import its .ini file that has information like how OData producer should be processed by mobile platform and store the offline data, offline DB pre-population, client index, defining requests and so on.

Our first impression was, if there are 2 back-end URLs, there would be 2 .ini files to be imported. But when we try to import second file (one ini file was already there containing info regarding first back-end url) , status of first ini file changes to 'No Custom Settings'

 

1.jpg

 

Then, we realized and concluded that information from both files should be combined into a single one and that the one should be imported. Now for both connection names' status is showing 'Configured'

 

2.png

 

Tips:

 

1. Sequence in.ini file should be:

     [endpoint]  <<could be either backend connection name>>

     [defining request]

     [defining request]

     .

     .

     .

     .

      [endpoint]

     [defining request]

     [defining request]

     .

     .

     .

 

2. name=com.test.test

     name=com.secondary.endpoint

     should be the same names as connection names for backend URLs (already explained here)

3. Before importing the new .ini file, make sure you have back-up file for old ini.

4. To retrieving data from 1st back-end URL,

  • On-board user on SMP
  • GET call: http(s)://smp:port/com.test.test 

 

5. To retrieving data from 2nd back-end URL,

  • On-board user on SMP
  • GET call: http(s)://smp:port/com.secondary.endpoint

 

Regards,

Jitendra

OData Provisioning feature in HANA Cloud Integration (HCI) converts non OData protocols to OData, hence HCPMS applications can consume it. This feature is similar to what Integration Gateway do in SMP 3.

 

2016-04-15_14-08-17.jpg

 

In this blog I am explaining how to create HCPMS mobile app using OData service I created from an existing SOAP service as mentioned in my blog.

Business Scenario

Data from backend is exposed as SOAP service. It is possible to define backend of HCPMS application with SOAP service, but the application will not get all the benefits of HCPMS, ex. Offline.

So, to create a mobile app with all features of HCPMS, SOAP has to be converted into OData. To convert SOAP to OData we need to use HCI.

 

Step to Step Procedure

As mentioned in this blog OData service was created, it will be used as backend in HCPMS application.

The following steps will guide you through creating an HCPMS application, and testing it on a simulator.

 

Web IDE is used to create the hybrid app.

 

Configure app on HCPMS

  • Logon to HCPMS cockpit. Click on Applications tile.

      2016-04-17_20-25-32.jpg

  • Press the + icon to create a new application.

      2016-04-17_21-59-04.jpg

  • In the create application screen enter below details. Click Save. Note: Security configuration as Basic means it require Basic Authentication.

      2016-04-17_22-13-57.jpg

  • Click on Configure. Then click on Backend.

      2016-04-17_22-22-12.jpg

  • Fill in the details as given below. Then click Save to complete your configuration.

     2016-04-17_22-24-28.jpg2016-04-17_22-31-51.jpg

Create Mobile App using Web IDE

  • Logon to SAP Web IDE select Local root and open the context menu by right clicking.
  • Choose New > Project from Template to open the new project creation wizard.

      Untitled.png

  • On Template Selection page click on SAPUI5 Master Detail Kapsel Application. Click Next.

      2016-04-17_22-46-40.jpg

  • Enter a name for your project and click Next.

      2016-04-17_22-49-11.jpg

  • Next, choose the backend and provide details to complete the base URL as given below. Click  “Load Service Metadata” button, it will list the OData collections of the OData service. Click Next.

      2016-04-17_22-51-14.jpg

  • Note: I have configured a destination with the details of my HCI system as given below. This backend was used in the above step.

     2016-04-17_23-19-16.jpg

  • Fill out the Project Namespace, Master Section, Master Data Fields and Detail Section as displayed in the screenshot.

     2016-04-18_11-45-49.jpg2016-04-18_12-50-12.jpg

  • Click Next.
  • Click Finish to create the project.

      2016-04-18_12-54-53.jpg

  • To run this app as a hybrid app, right click on the project > Project Settings.

      2016-04-18_12-58-27.jpg

  • Under Device Configuration provide below details. Click Save. Note: I am going to test this app on iOS simulator hence chose iOS as the mobile platform. Logon plugin is used to login to HCPMS from the app.

     2016-04-18_13-03-51.jpg      2016-04-18_13-10-33.jpg

  • Finally, to test the app on a simulator right click on the project > Run > Run On > iOS Simulator. Note: To use this feature you need HAT configured.

     2016-04-18_13-13-20.jpg

  • The application will be installed on the iOS simulator. Backend credentials has to be provided to login to the app. Note: In the background Web IDE is creating a cordova project with the plugins and platforms we chose during device configuration.

      2016-04-18_13-21-57.jpg2016-04-18_13-22-36.jpg

CC:

SAP for Mobile

 

Regards, Midhun

SAP Technology RIG

Actions

Filter Blog

By author:
By date:
By tag: