Tuesday, May 7, 2013

Integrate SUP 2.1.3 with iOS


1.    Introduction:
Sybase first released Sybase Unwired Platform in 2008. Written in C and Java, the product is currently in its 2.1.3 release. Sybase unwired platform is a mobile enterprise application platform designed to simplify the task of creating applications that connect business data to mobile devices for workflow management.
Sybase Unwired Platform provides a layer of middleware between heterogeneous back-end data sources and the mobile devices. Application developers write the business logic of a mobile application using the development tools in Sybase Unwired Platform. The product automatically does the translation required to create customized versions of the new application for a wide variety of mobile devices and operating systems. The intent is to make it easier and faster to create complex applications that use multiple data sources and will work on many different mobile devices.
The following diagram shows how Sybase Unwired Platform supports the various mobilization patterns using mobile business objects (MBOs).

2. Adding Resources, Libraries and Source Code Files to the XcodeProject


2.2. Adding Resources:

A. Go to Targets build phases and expand Link Binary with Libraries and add the following frameworks
·      AddressBook.framework
·       CoreFoundation.framework
·       libicucore.A.dylib
·       libstdc++.dylib
·       libz.dylib
·       libz1.2.5.dylib
·       QuartzCore.framework
·       Security.framework
·       CFNetwork.framework
·       MobileCoreServices.framework
·       SystemConfiguration.framework

2.2 Adding Libraries:

                                A. Copy the \UnwiredPlatform\MobileSDK213\ObjectAPI\iOS folder from the Unwired Platform installation directory in your windows system to your Mac.This folder contains Header files,Libraries,Settings Bundle, etc. .
B. The libraries folder contains different set of libraries for Device (Debug and Release) and Simulator (Debug and Release) Select the appropriate folder and add these in your Xcode project.
·       libclientrt.a
·       libSUPObj.a
·       libMO.a`
·       libsupcore.a
·       libAfariaSLL.a
·       libDatavault.a
·       libsupUltralite.a

C. Go toTargets Build Settings, Library Search Paths and enter the path of the libraries added for debug and release
D. Header folder contains internal and public .Add these folders in your Xcode project.
E. Go toTargets Build Settings, Header Search Paths and enter the path and check recursive option

2.3. Adding Source Code:


A. Get the Generated Code from the SUP team and add in in your project.
B. Disable ARC in Generated code. If you have enabled ARC in project.
C. Now clean build and compile your Xcode project, it should compile successfully.


3. Connection set up in Sybase Control Center:

3.1. Connection Properties:


A.     Save the Connection properties in plist or Dictionary as per requirement to establish connection with SUP. You can get theConnection properties from your server team who configured Sybase control Centre. ForE.g.:

·       User name – supAdmin
·       Server name – <localhost.sybase.com>
·       Port – the Unwired Server port, 5001.
·       Farm ID – 0
·       Manual Registration – Yes or NO
·       Activation code – 123
Note: Activation code is required only,when you go for manual registration.

B. If you use Automatic Registration, connection profiles will be created automatically in SCC else you have to create manually in SCC.This can be controlled in Manual Registration YES or NO option.

4. Registrations and Synchronization Code in Client Side:


4.1.  Add Callbackhandler Class:


Add Callbackhandler class from sup101 sample code from Sybase for event handling process in your application.

4.2. Add GeneralSupConnection Class:



Step 2: Create a separate class (GeneralSupConnection) for SUP application registration and connection process and read from plist file as below. Check whether app running for the first time, if means check for required settings. Here we implemented automatic registration, saved the server settings in local dictionary and retrieve the encrypted username and password from plist.

- (BOOL)testForRequiredSettings{

if([self.userNamelength] <=0||[self.passwordlength]<=0){
NSString *name =[selfselectUserName];
self.userName =name.length?name:[[NMPEUserInfosharedUserInfo]  strCurrentUser];
self.password =[[NMPEUserInfosharedUserInfo]  strPassword];
    }

NSMutableDictionary *dictionary=[[NSMutableDictionaryalloc]init];
if(isProduction){
        [dictionarysetObject:PRDSERVERNAMEforKey:@"supservername_preference"];
    }
else{
        [dictionarysetObject:CRDSERVERNAMEforKey:@"supservername_preference"];
    }

    [dictionarysetObject:@"5001"forKey:@"supserverport_preference"];
    [dictionarysetObject:self.userNameforKey:@"supusername_preference"];
    [dictionarysetObject:@"0"forKey:@"supfarmid_preference"];

self.SUPServerName = [dictionary valueForKey:@"supservername_preference"];
self.SUPServerPort = [dictionary valueForKey:@"supserverport_preference"];
if(self.SUPServerPort == nil)
self.SUPServerPort = @"5001";

self.SUPUserName = [dictionary valueForKey:@"supusername_preference"];
self.SUPFarmID = [dictionary valueForKey:@"supfarmid_preference"];
if(self.SUPFarmID == nil)
self.SUPFarmID = @"0";

self.SUPManualRegistration=NO;
if(self.SUPManualRegistration){
self.SUPConnectionName = [dictionary valueForKey:@"connectionname_preference"];
self.SUPActivationCode = [dictionary valueForKey:@"activationcode_preference"];
    }

    [dictionaryrelease];

if(self.SUPServerName == nil ||
self.SUPUserName == nil ||
self.SUPFarmID == nil){
returnNO;
    }

if(self.SUPManualRegistration&& (self.SUPConnectionName == nil || self.SUPActivationCode == nil)){
returnNO;
    }

returnYES;
}

4.3. App Registration and Start Connection:


Step 1: Create a method "InitializeSUP " which is to be called in connectsup method. We implemented the following stuffs in InitializeSUP.

Note:Connectsup method gets called in onclick of login.


1) Set app identifier
 2) Set app connection properties
3) Set DB for connection profile
 4) Register or start connection
5) Exception Handling.

- (void)initializeSUP101{
SUPApplication* app =[SUPApplicationgetInstance];
@try {
sup101vault = [SUPDataVaultgetVault:kSUP101DataVaultID];
        [sup101vaultunlock:self.pinwithSalt:kSUP101DataVaultSalt];

// make sure to have the applicationIdentifer same as the project name. This is case sensetive.

if([SUPApplicationmessageClientStatus]== MC_STATUS_NOT_INITIALIZED){

Note: Set app identifier- Which is available in SCC.

app.applicationIdentifier = @"Appidentifier";
        }
CallbackHandler *ch = [CallbackHandlergetInstance];
        [selfsetCallbackHandler:ch];

        [appsetApplicationCallback:[selfcallbackHandler]];

// Register a callback handler. This should be done before any other SUP code is called.
        [PEPortalNMPECareDBregisterCallbackHandler:self.callbackHandler];

        [selfregisterCallBackHandler:appforVault:sup101vault];


if(![PEPortalNMPECareDBdatabaseExists]){
            [PEPortalNMPECareDBcreateDatabase];
        }
Note:Set app connection properties –Here we set the domain name and connection profile(Available in MBO).
        [selfgetConnectionProfileForVault:sup101vault];

Note: Set DB for connection profile –Set the app which contains connection properties in DB for connection.

        [PEPortalNMPECareDBsetApplication:app];

Note: Register and start connection –Implemented Automatic registration here.

if (![[NSUserDefaultsstandardUserDefaults]objectForKey:IS_APP_REGISTERED]) {
if(!app.isRegistered){
                [appregisterApplication:600];
                [[NSUserDefaultsstandardUserDefaults]setBool:YESforKey:IS_APP_REGISTERED];
            }
else{
                [appstartConnection:600];
            }
while([app registrationStatus] != SUPRegistrationStatus_REGISTERED){

NSAutoreleasePool * pool = [[NSAutoreleasePoolalloc] init];
                [[NSRunLoopcurrentRunLoop] runUntilDate:[NSDatedateWithTimeIntervalSinceNow:1]];
                [poolrelease];
            }
while([app connectionStatus] != SUPConnectionStatus_CONNECTED){

NSAutoreleasePool * pool = [[NSAutoreleasePoolalloc] init];
                [[NSRunLoopcurrentRunLoop] runUntilDate:[NSDatedateWithTimeIntervalSinceNow:1]];
                [poolrelease];
            }
       }
else{
            [appsetRegistrationStatus:SUPRegistrationStatus_REGISTERED];
        }

        [selfonConnectSuccess];

    }
Note: Exception Handling
@catch(SUPPersistenceException *pe){
if ([[pemessage] rangeOfString:@"loginFail,Sync failed"options:NSRegularExpressionSearch].location != NSNotFound) {
            [selfshowNoTransportAlert:@"login fail"];
        }
else{
            [selfshowNoTransportAlert:@"No Internet Connection"];
        }
        [DataControllersharedDataController].syncErrorMsg = [pemessage];
return;
    }

@catch (SUPSynchronizeException *se) {
        [selfshowNoTransportAlert:@"Sync Error"];
        [DataControllersharedDataController].syncErrorMsg = [se message];
return;
    }
@catch (SUPConnectionPropertyException *cpe) {
        [selfshowNoTransportAlert:@"Error in connection"];
        [DataControllersharedDataController].syncErrorMsg = [cpemessage];
return;
    }
@catch (SUPApplicationRuntimeException *re) {
 [DataControllersharedDataController].syncErrorMsg = [re message];
if ([[re message] rangeOfString:@"REGISTRATION_WRONG_USER_FOR_DEVICE"options:NSRegularExpressionSearch].location != NSNotFound) {
            [selfshowNoTransportAlert:@"login fail"];
        }
elseif ([[re message] rangeOfString:@"UNKNOWN"options:NSRegularExpressionSearch].location != NSNotFound){
            [selfshowNoTransportAlert:@"server down"];
        }
elseif([[re message] rangeOfString:@"AUTHENTICATION_FAILURE"options:NSRegularExpressionSearch].location != NSNotFound){
            [selfshowNoTransportAlert:@"Invalid Login"];
        }
else {
            [selfshowNoTransportAlert:@"Invalid Login"];
        }
return;
    }
@catch (NSException *e) {
        [selfshowNoTransportAlert:@"Connection Timed out"];
return;
    }
@finally{
        [sup101vaultlock];
    }
if([delegaterespondsToSelector:@selector(loginSuccess)])
        [delegateloginSuccess];

}

Note: Get connection properties –setting domain name and connection profile

- (void)getConnectionProfileForVault:(SUPDataVault *)sup101vault{
SUPConnectionProfile *cp = [PEPortalNMPECareDBgetConnectionProfile];
if(isProduction){
        [cp.syncProfilesetDomainName:PRD_DOMAIN];
    }
elseif(isTest){
        [cp.syncProfilesetDomainName:CRQ_DOMAIN];
    }
else{
        [cp.syncProfilesetDomainName:CRD_DOMAIN];
    }

    [cpenableTrace:NO];
    [cp.syncProfileenableTrace:YES];

// Generate an encryption key for the database.
// Store the encryption key in the data vault for future use.
    [sup101vaultsetString:@"encryptionkey"withValue:[cpgetEncryptionKey]];
}


1) Set RBS (Relay Based Synchronization) synchronization properties

-(void)onConnectSuccess{
// Connection to the server was made, so log in.
// See [CallbackHandleronLoginSuccess] and [CallbackHandleronLoginFailure]. One of those
// callbacks will be called at some point in the future.

NSString *supuser = nil;
NSString *suppass = nil;
SUPDataVault *sup101vault = nil;
@try {
sup101vault = [SUPDataVaultgetVault:kSUP101DataVaultID];
 [sup101vaultunlock:self.pinwithSalt:kSUP101DataVaultSalt];
supuser = self.SUPUserName;
suppass = [sup101vault getString:@"password"];
    }
@catch (NSException *exception) {
          [selfshowExceptionAlert];
    }
@finally {
        [sup101vaultlock];
    }

@try{
SUPConnectionProfile *sp = [PEPortalNMPECareDBgetSynchronizationProfile];
    [spsetNetworkStreamParams:@"timeout=30"];
    [spsetAsyncReplay:NO];
    [spsetUser:supuser];
    [spsetPassword:suppass];
    [spsetServerName:self.SUPServerName];
    [spsyncProfile];
    [selfsetPersonalisationParameters];
    }@catch (NSException *exception) {
 [selfshowExceptionAlert];
return;
    }
}

4.4. Set Personalization parameters And Call synchronize:


Step 1:We called setPersonalisationParameters method on connect success. In that method we implemented the following.

Note: Connectsup method gets called in on click of login. Check whether the app run for the first time or not in that method. If not means we directly call setPersonalisationParameters.

1) Set Personalization parameters for Authentication purpose
2) Call synchronize


- (void)setPersonalisationParameters{
PEPortalPersonalizationParameters *personalisationParam = [PEPortalNMPECareDBgetPersonalizationParameters];

AppDelegate *objAppdelegate = (AppDelegate *)[[UIApplicationsharedApplication]delegate];
NSDictionary *dict = [objAppdelegategetPlistDict];

NSString *userName =[[dictobjectForKey:@"supusername"] AES256DecryptWithKeyy:kUSERKEY];
NSString *password =[[dictobjectForKey:@"suppassword"] AES256DecryptWithKeyy:kPASSKEY];
if(!userName)
        [personalisationParamsetUsername:self.SUPUserName];
else
        [personalisationParamsetUsername:userName];
if(!password)
        [personalisationParamsetPassword:self.SUPPassword];
else
        [personalisationParamsetPassword:password];
    [personalisationParamsetInitialLoad:@"X"];

if([strSyncTypeisEqualToString:@"attachment"]||[strSyncTypeisEqualToString:@"attachmentupdate"]){
personalisationParam.FileName=[DataControllersharedDataController].strFileName;
personalisationParam.ProcessType=[DataControllersharedDataController].strProcessType;
personalisationParam.PatientGuid=[DataControllersharedDataController].strPatientGUID;
    }
    [personalisationParamsave];
while ([PEPortalNMPECareDBhasPendingOperations])
        [NSThreadsleepForTimeInterval:1];

[PEPortalNMPECareDBsynchronize:@"SyncGroup"withListener:(id)self];
}

 

5. Summary:

            Sybase Unwired Platform presents a common method of looking at all enterprise data. The developers can have a common view of all these data sources in what we call Mobile Business Objects, which is a very key, patented component from Sybase that really reduces the complexity of developing mobile application.  It provides a common robust mobility infrastructure for IT to deploy, manage and support mobile applications once they are already deployed. It provides all of these capabilities integrated into a single server and a single mobility platform SUP helps companies to address mobility as a holistic, strategic initiative rather than a point solution.

6. References:                                            

















No comments:

Post a Comment