Manual Synchronization Code Sample

Manual synchronization can be set as the Syncrhonization criteria for SD Offline Apps with the Data Receive Criteria property.

Note: This document aims to explain how to perform a full manual synchronization between the device and the server tables, that means, avoiding the synchronizations programs automatically generated by GeneXus (first bits of GeneXus Tilo does not include this option). So, before continue with this approach, consider using Automatic Sync or Manual sync with automatically generated programs.

To explain how to do this synchronization some code example was taken from the Sales with manual synch example.

The following are the main actions to complete the synchronization.

  1. Master Tables Service Layer.
  2. Invoke Master Services.
  3. Triggering of the Synchronization process.
  4. Event Tables Service Layer
  5. Send Events to the Server.

1. Master Table Service Layer

This are the Rest services exposed on the web Server so that the devices can get the Master data they need to start working.
For example, to expose the Customer Master table the following is needed:

  1. SDT based on the Customer Transaction.
  2. Data Provider which will return all or a part of the registers of this TRN
SDTCustomer
{
      CustomerId
      CustomerName
      CustomerAddress
      CustomerPhone
      CustomerLocation
      CustomerDistanceToMe
}


This Data Provider will return a collection of SDTCustomers; in this case returns all the registers of the Customers.
To enable this data provider to be exposed as a Rest service it is needed to set a property explained here. Lastly set the Web Service Protocol to REST Protocol.

2. Invoke Master Services

These are the Objects needed to execute the services of the Master data service layer and insert the data on the device. This code will be executed 100% on the device.
A procedure with the following code can be created.

For each CustomerId
   delete
Endfor

Delete all the Customers on the local database.  Other strategies may vary and can do incremental synchronizations, in this case the tables are deleted before the Master Synchronizations.

GetParameters.Call(&serverprotocol, &serverHost, &serverBaseURL, &serverRestBaseURL, &serverPort)

(GetParameters retrieves the parameters of the HttpClient data type. The values can be as the following:

&serverprotocol = http
&serverHost = apps3.genexusx.com
&serverBaseURL= "/Idfe4nFfdfFwf4jf442nvanaf4r3rn904Faf/"
&serverRestBaseURL = "/Idfe4nFfdfFwf4jf442nvanaf4r3rn904Faf/rest/"
&serverPort = 80

)

&httpclient.Host = &serverHost.Trim()
&httpclient.Port = &serverPort
&httpclient.BaseUrl = &serverRestBaseURL.Trim()
&httpclient.AddHeader(!'Content-type',!'application/json')

Initial set up of the HTTPClient Object in order to consume rest services from the service layer.

&httpclient.Execute(!'GET', !'GetAllCustomers?fmt=json')

The Rest Service is invoked, GET method is used to retrieve the resource GetAllCustomers created in step 1. The String returned, in json format, is going to be stored on the &httpclient variable.

&customerslist.FromJson(&httpclient.ToString())

&customerlist is a variable based on the SDT created on 1.a. The FromJson method will load the variable with all the registers brought by the server, this can only be done because the rest service returns a json representation of the same SDT.

For &Customer in &CustomersList
  &CustomerBC = new()
  &CustomerBC.CustomerId = &Customer.CustomerId
  &CustomerBC.CustomerName = &Customer.CustomerName
  &CustomerBC. CustomerAddress = &Customer.CustomerAddress
  &CustomerBCCustomerPhone = &Customer.CustomerPhone
  &CustomerBC.CustomerLocation = &Customer.CustomerLocation
  &CustomerBC.CustomerDistanceToMe = &customer.CustomerDistanceToMe
  &CustomerBCCustomerVisited = False
  &CustomerBC.Save()
endfor

Iterate through the &CustomersList and insert via BusinessComponent all the Customers on the local database.
The reasons of using Business Component can be seen on the Best Practices for Manual Synchronization.

commit

The final instruction to commit the changes of the insertion on the local database.

3. Trigger The Synchronization

As seen before the synchronization is always started by the device. The developer has to choose wether the user can consciously trigger this action (for example by tapping on a Load Data or Synchronize button) or unconsciously  (for example by entering to a screen the synchronization is triggered). Either way there this code is triggered on the Smart Device (the client side).
The User Event to Load Data can be like the following:

Event 'Load Master Data'
Composite
  ProgressIndicator.Title = "Data synchronization..."
  ProgressIndicator.Description = "Checking connectivity..."
  ProgressIndicator.Type = 0
  ProgressIndicator.Show()
  &server = getServerFromParameters()

( getServerFromParameters() returns the url of the server host where the synchronization is going to be made.)

  &IsConnected = NetWorkAPI.IsServerAvailable(&server)
  if &isConnected
      ProgressIndicator.Description = "Retrieving data from server..."
     &result = SyncReceive()

Note: If the device is connected to the server then the synchronization can be done. In some scenarios you will also want to check which connection is used to see if there are synchronizations which need or not wifi or 3g, etc. This can be done using NetworkAPI external object (X Evolution 3).

  else
   &result = "No connection detected"
  endif
  ProgressIndicator.Hide()
  msg(&result)
endcomposite
Endevent

4. Event Tables Service Layer

The Transactions that generate the Event Tables are also going to be on the web server application. So the easiest way to generate the service to insert/update registers online is the Transaction itself. This is done with the expose as web service property of the Transaction which will expose the Transaction's CRUD services for the REST protocol. 

The insert service for PurchaseOrder will be:

<host>/<baseUrl>/rest/PurchaseOrder/0

example:

http://apps3.genexusx.com/Idfe4nFfdfFwf4ja42nvanaf4r3rn904Faf/rest/PurchaseOrder/0

5. Send Events to the Server

This step is going to send to the web server (and insert there ) the data saved locally to the Event Tables. Following the sample and in order to do that, a POST to the PurchaseOrder REST service has to be exectued for each record of that transaction.

After the &httpclient variable is initialized like in step 2, code the following:

&ServerPOrder = LoadPurchaseOrder()

Load all the Purchases Orders that were added on the offline database. &ServerPOrder is based on an SDT based on the Transaction ServerPOrder.

For &ServerPOrderItem in &ServerPOrder

Iterate through the Purchase Orders loaded from the local database.

&body = &ServerPOrderItem.ToJson()

Get the JSON representation of the Purchase Orders.

&httpclient.AddString(&body)

Attach this as the body of the http POST that is going to insert the pruchase order on the server.

&httpclient.Execute(!'POST', !'PurchaseOrderSrv/0')

Execute the Post to insert.

If &httpclient.StatusCode = 201 or  &httpclient.StatusCode = 200  
//Succesfull Post
else
//Error in Post
endif
Endfor

 

The rest of the code can be found on -> Sales with manual synch example
Note: Sales Force Offline Example also shows how to synch Multimedia, specifically Image data type fields.