Working with PowerBuilder synchronization objects

When you run the ASA MobiLink Synchronization wizard from the Database page in the New dialog box, the wizard generates objects that let you initiate and control MobiLink synchronization requests from a PowerBuilder application. These objects let you obtain feedback during the synchronization process, code PowerScript events at specific points during synchronization, and cancel the process programmatically.

For more information about the MobiLink synchronization wizard, see Managing the Database in Users Guide.

Preparing to use the wizard

Before you use the wizard in a production application, you need to complete the following tasks:

What gets generated

The wizard generates two sets of objects.

Objects that initiate and monitor synchronization

The first set of objects lets the end user initiate and monitor synchronization:

  • nvo_appname_mlsync -- a custom class user object that controls the MobiLink client (appname is the name of your application)

  • gf_appname_sync -- a global function that instantiates the user object and calls a function to launch a synchronization request

  • w_appname_syncprogress -- an optional status window that reports the progress of the synchronization process

In the wizard, you can choose whether the application uses the status window. The generated status window includes an OK button that lets the user view the status before dismissing the window, and a Cancel button that lets the user cancel synchronization before it completes. You can also customize the window to fit your application's needs.

Objects that modify synchronization options

The second set of objects is generated only if you select Prompt User for Password and Runtime Changes in the wizard. It lets the end user change synchronization options before initiating synchronization:

  • w_appname_sync_options -- an options window that lets the end user modify the MobiLink user name and password, the host name and port of the MobiLink server, and other options for dbmlsync, and choose how to display status

  • gf_appname_configure_sync -- a global function that opens the options window and, if the user clicked OK, calls gf_appname_sync to initiate synchronization

Most applications that use the options window provide two menu items or command buttons to launch synchronization: one to open the options window so that users can set up or modify dbmlsync options before requesting a synchronization, and one to request a synchronization with the preset options.

Creating an instance of MLSync

You do not have to use the MobiLink Synchronization Wizard to create a nonvisual object that launches Dbmlsync.exe. You can include an MLSync system object in your applications:

  • Programmatically with PowerScript

  • By selecting it from the New dialog box

Adding an MLSync object programatically

The code fragment below creates an instance of an MLSync object and programmatically populates all of the necessary properties as well as some optional properties using an instance of the system SyncParm structure. Then it calls the Synchronize function to start the database synchronization.

SyncParm         Parms
MLSync         mySync
Long         rc
 
mySync = CREATE MLSync
mySync.MLServerVersion = 11      // required property
mySync.Publication = 'salesapi   '// required property
mySync.UseLogFile = TRUE      // optional
mySync.LogFileName = "C:\temp\sync.log   "// optional
mySync.Datasource = 'salesdb_remote   '// required
Parms.MLUser = '50         '// required
Parms.MLPass = 'xyz123         '// required
//The following values are required if they are not 
//set by the DSN
Parms.DBUser = 'dba      '
Parms.DBPass = 'sql      '
 
//  Apply the property values to the sync object
mySync.SetParm(Parms)   
//  Launch the synchronization process
rc = mySync.Synchronize()   
destroy mySync

Adding an MLSync object from the New dialog box

You can add an MLSync object to a target PBL using the New dialog box: from the PowerBuilder menu, choose File>New, go to the PB Object tab, select Standard Class, then MLSync. This opens a new MLSync object in the User Object painter, where you can initialize all or some of the properties. When you are finished, you can save it as a new object in your target PBL.

Since all of the properties are already initialized, including userids and passwords, it is ready for immediate use. To launch a synchronization requires very little coding, as this example for an MLsync object that you save as "nvo_my_mlsync" illustrates:

nvo_my_mlsync       mySync
Long      rc
mySync = CREATE nvo_my_mlsync
mySync.Synchronize()
destroy mySync

You would typically add the above code to the Clicked event for a menu item or a command button on one of the application windows.

For more information

For more information on system objects related to synchronization, and their functions, events, and properties, see MLSynchronization, MLSync, and SyncParm in the section called “MLSynchronization object” in Objects and Controls, the section called “MLSync object” in Objects and Controls, and the section called “SyncParm object” in Objects and Controls.

Auxiliary objects for MobiLink synchronization

If you create an instance of MLSync by PowerScript code or from the New dialog box, you should also consider using auxiliary objects that are generated automatically by the wizard that you can customize in the PowerBuilder Window painter.

Using an existing synchronization progress window

After you instantiate an MLSync object and call SetParm to enable an end user to set authentication properties at runtime, you can call a Response! type window to document the progress of a database synchronization. You open the progress window with an OpenWithParm call, using the window name and the MLSync object name as arguments. By default, the wizard generates a progress window named w_appname_syncprogress and adds the OpenWithParm call for you.

In the Properties view for an MLSync object, you can select a customized progress window to document the progress of a synchronization call. If you customize a wizard-generated progress window -- typically to hide some of the fields on its tab pages, or even to hide one or two of the tab pages -- you can select the customized progress window for all of your MobiLink applications.

Changing the connection arguments at runtime

To allow a user to override authentication parameters at runtime, you can call a customized options window or the synchronization options window generated by the wizard. The options window can, in turn, call an instance of the SyncParm object that can be initialized with authentication values from a highly secure persistent store, such as a remote database table. You can choose to make some or all of the authentication values writable, allowing the end user to override them at runtime.

Maintaining property settings in the MLSync object

Normally when you call SetParm(SyncParm) from an MLSync object, you automatically override any authentication values (AuthenticationParms, DBUser, DBPass, EncryptionKey, MLUser, and MLPass) that you set for properties of the MLSync object even when the value of a particular SyncParm property is an empty string. However, if you call SetNull to set a particular property of the SyncParm object to NULL before you call SetParm, the property value in the MLSync object will be used instead.

The default synchronization options window, w_appname_sync_options, returns a SyncParm structure to its caller through the PowerObjectParm property of the Message object. This allows the caller to save the highly sensitive authentication property values in a secure location. It also sets the SyncParm ReturnCode property with an integer value that indicates whether to proceed with the actual synchronization.

Default tab pages of the options window

The default synchronization options window has four tab pages: Subscriptions, SQL Anywhere, MobiLink Server, and Settings.

Subscriptions page

When you used the MobiLink wizard, you selected one or more publications from the list of available publications. The selected publications display on the Subscriptions page, but cannot be edited at runtime.

Each remote user can supply a MobiLink synchronization user name on this page. The name must be associated in a subscription with the publications displayed on the page. If the application is always used by the same MobiLink user, this information never needs to be supplied again. The name is saved in the registry and used by default every time synchronization is launched from the application on this device.

The MobiLink password and authentication parameters are never saved to the user's registry. They can either be entered each time by the user or provided from a secure database.

SQL Anywhere page

Remote users can supply a DSN file name on this page to pass all the arguments needed to connect to a remote database.

If a DSN file is not used, or if the DSN file does not include a user name and password, each remote user can supply a remote database user name. The name is saved in the registry and used by default every time synchronization is launched from the application on this device.

The following figure displays the options window SQL Anywhere tab page with DSN, DBUser, DBPass, and Encryption Key fields. The database password and encryption key are never saved in the registry.

Figure: Synchronization options window

MobiLink Server page

When you create a subscription, you specify a protocol, host, port, and other connection options. For ease of testing, the default protocol is TCP/IP and the default host is localhost. The default port is 2439 for TCP/IP, 80 for HTTP, and 443 for HTTPS.

You might need to change these defaults when you are testing, and your users might need to change them when your application is in use if the server is moved to another host or the port changes. If you did not enter values for the host and port at design time, and the user does not make any changes on this page, dbmlsync uses the values in the subscription.

For more information about subscriptions, see Adding subscriptions.

Settings page

The Settings page displays logging options, and any other dbmlsync options you specified at design time and lets the user change any of these options at runtime. It also gives the user a choice of displaying or not displaying a synchronization progress window.

Extended options

Extended options are added to the dbmlsync command line with the -e switch. You do not need to type the -e switch in the text box.

Using the synchronization objects in your application

Before you use the generated objects, you should examine them in the PowerBuilder painters to understand how they interact. Many of the function and event scripts contain comments that describe their purpose.

All the source code is provided so that you have total control over how your application manages synchronization. You can use the objects as they are, modify them, or use them as templates for your own objects.

Properties of the user object

The nvo_appname_mlsync user object contains properties that represent specific dbmlsync arguments, including the publication name, the MobiLink server host name and port, and the user name and password for a connection to the remote database.

When you run the wizard, the values that you specify for these properties are set as default values in the script for the constructor event of the user object. They are also set in the Windows registry on the development computer in HKEY_CURRENT_USER\Software\Sybase\PowerBuilder\19.0\appname\MobiLink, where appname is the name of your application.

At runtime, the constructor event script gets the values of the properties from the registry on the remote machine. If they cannot be obtained from the registry, or if you override the registry settings, the default value supplied in the script is used instead and is written to the registry.

You can change the default values in the event script, and you can let the user change the registry values at runtime by providing a menu item that opens the w_appname_sync_options window.

Launching dbmlsync

To enable the user to launch a synchronization process, code a button or menu event script to call the gf_appname_sync global function. This function creates an instance of the nvo_appname_mlsync user object, and the user object's constructor event script sets the appname\MobiLink key in the registry of the remote machine.

If you specified in the wizard that the progress window should display, the global function opens the progress window, whose ue_postopen event calls the nvo_appname_mlsync user object's synchronize function; otherwise, the global function calls the synchronize function. The synchronize function launches dbmlsync as an external process.

Supplying a MobiLink user name and password

The global function takes a structure for its only argument. You can pass a system SyncParm structure that you instantiate. The structure includes six variables with string datatypes (one each for MobiLink and remote database user names and passwords, as well as variables for the authentication parameters and the encryption key) and another variable that takes a long datatype for a return code.

If you assign valid values to the structure that you pass as an argument, the global function passes these values to the user object to enable MobiLink server and remote database connections.

The options window (described in Default tab pages of the options window) provides a mechanism to store certain of these values in the registry the first time a user starts a synchronization. (Sensitive password and encryption information is never saved to the registry.) Subsequent synchronizations can be started without the user having to reenter the information, however, the options window can still be used to override and reset the registry values.

Retrieving data after synchronization

After synchronizing, you would typically test for synchronization errors, then retrieve data from the newly synchronized database. For example:

if gf_myapp_sync(s_opt) <> 0 then
   MessageBox("Error", "MobiLink error")
else
   dw_1.Retrieve()
end if

Capturing dbmlsync messages

The PowerBuilder VM traps messages from the dbmlsync process and triggers events in the user object as the synchronization process runs.

These events are triggered before synchronization begins as the upload stream is prepared:

ue_begin_logscan ( long rescan_log )
ue_progress_info ( long progress_index, long progress_max )
ue_end_logscan ( )

These events correspond to events on the synchronization server, as described in Connection events:

ue_begin_sync ( string user_name, string pub_names)
ue_connect_MobiLink ( )
ue_begin_upload ( )
ue_end_upload ( )
ue_begin_download ( )
ue_end_download ( long upsert_rows, long delete_rows )
ue_disconnect_MobiLink( )
ue_end_sync ( long status_code )

These events are triggered after ue_end_upload and before ue_begin_download:

ue_wait_for_upload_ack ( )
ue_upload_ack ( long upload_status )

These events are triggered when various messages are sent by the server:

ue_error_msg ( string error_msg )
ue_warning_msg ( string warning_msg )
ue_file_msg ( string file_msg )
ue_display_msg ( string display_msg )

The default event scripts created by the wizard trigger corresponding events in the optional progress window, if it exists. The window events write the progress to the multiline edit control in the progress window. Some window events also update a static text control that displays the phase of the synchronization operation that is currently running (log scan, upload, or download) and control a horizontal progress bar showing what percentage of the operation has completed.

You can also add code to the user object or window events that will execute at the point in the synchronization process when the corresponding MobiLink events are triggered. The dbmlsync process sends the event messages to the controlling PowerBuilder application and waits until PowerBuilder event processing is completed before continuing.

Cancelling synchronization

The Cancel button on the progress window calls the cancelsync user object function to cancel the synchronization process. If your application does not use the progress window, you can call this function in an event script elsewhere in your application.

Runtime requirements for synchronization on remote machines

Support files required on remote machine

If you do not install PowerBuilder or SQL Anywhere on remote machines, you must copy the files listed in the following table to use MobiLink synchronization with a PowerBuilder application. These files must be copied to the system path on the remote machine or the directory where you copy your PowerBuilder applications.

Required files

Description

PBDPL190.dll, PBVM190.dll, PBDWE190.dll, PBSHR190.dll, PBODB190.dll, PBODB190.ini, LIBJCC.DLL, LIBJUTILS.DLL, LIBJTML.DLL, NLWNSCK.DLL

PowerBuilder files that you can copy from the %Appeon%\Shared\PowerBuilder directory of the development machine.

GDIPLUS.DLL, MSVCP100.DLL, MSVCR100.DLL

Microsoft files that ship with PowerBuilder. For restrictions on distributing these files with client applications, see Microsoft files.

DBENG11.EXE, DBMLSYNC.EXE, DBSERV11.DLL, DBTOOL11.DLL, DBODBC11.DLL, DBLIB11.DLL, DBLGEN11.DLL, DBCON11.DLL, DBCTRS11.DLL, DBICU11.DLL, DBICUDT11.DLL

SQL Anywhere and MobiLink files that you can copy from the SAP\SQL Anywhere 12\bin32 (or bins64) directory of the development machine. You should copy these files to a "bin32" subdirectory of the location where you copy the PowerBuilder application and supporting runtime files.


Registry requirements for a remote machine

If you install SQL Anywhere on all remote machines that you use with MobiLink synchronization, the required registry entries are assigned automatically. If you copy SQL Anywhere and MobiLink files to a remote machine, you must create the HKEY_CURRENT_USER\SOFTWARE\Sybase\SQL Anywhere\16.0 registry key and add a "Location" string value that points to the parent directory of the bin32 or bin64 subdirectory where you copied SQL Anywhere and MobiLink files. (The code in the uf_runsync function of the nvo_appname_sync user object appends "\bin32\dbmlsync.exe" to the path that you assign to this registry value.)

Objects generated by the MobiLink Synchronization wizard also require registry entries to define the ODBC data source for a remote SQL Anywhere connection. The following table lists the required registry entries. You can create a REG file that installs these registry entries.

Registry key

Name of string value and data to assign it

HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\SQL Anywhere 16.0

Driver = full path to DBODBC11.DLL

Setup = full path to DBODBC11.DLL

HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers

SQL Anywhere 16.0 = "Installed"

HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\ODBC Data Sources

dataSourceName = "SQL Anywhere 16.0"

HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\dataSourceName

Driver = full path to DBODBC11.DLL

Userid = user name for remote database

Password = password for remote database

DatabaseName = remoteDatabaseName

DatabaseFile = full path to remote database

ServerName = remoteDatabaseName

Start = "dbeng16 -c 8M"

CommLinks = "shmem"


Using a file DSN instead of a registry DSN

You can use a file DSN or a registry DSN for your remote database connections. To avoid having to specify a fully qualified path, you can copy file DSNs to a path specified by the ODBC registry key (typically c:\program files\common files\ODBC\data sources).

The following is an example of the contents of a valid file DSN:

[ODBC]
DRIVER=SQL Anywhere 16.0
UID=dba
Compress=NO
AutoStop=YES
Start=dbeng16 -c 8M -zl -ti 0
EngineName=SalesDB_Remote
DBN=SalesDB_Remote
DatabaseFile=C:\work\salesdb\salesdb_remote.db
DatabaseName=SalesDB_remote

The Datasource property of the MLSync object distinguishes a file DSN from a registry DSN using these rules:

  • If the Datasource name ends with a .dsn file extension, it is a file DSN

  • If the Datasource name begins with "drive:\" prefix where drive is any alphabetic character, then it is a file DSN

File DSN location before EBFs are applied to older DBMS versions

If you have not applied the latest EBFs to SQL Anywhere 10.0.0 or Adaptive Server Anywhere 9, dbmlsync looks in the current directory for file DSNs when a full path is not specified -- not in the path specified by the ODBC registry key. The registry key is used by SQL Anywhere 10.0.1 and later to locate file DSNs when their paths are not fully qualified.