Schema Evolution and Sync Table Reload

Sometimes it is inevitable that new business requirements come up after the system has gone production and you have to change table structure or even drop/add table from/to schemas. Pervasync supports schema evolution so that you don’t have to re-build the whole system from scratch.

Schema Evolution Steps

  1. Shutdown sync server

Before you make any changes to the system, it is recommended to first shut down sync engine and sync servlet using the web admin console. It is also recommended to sync all the clients before the server shutdown so that all client side changes are uploaded to server.

  1. Alter DB table

Then, you make physical changes to the central database schemas/tables, such as create/drop tables, alter tables to add/remove columns or change column data types.

  1. Update sync table

Go to the web admin console and locate the table you just changed. Delete the sync table if you dropped the corresponding DB table. Update the sync table if you altered the corresponding DB table.

  1. Start sync server

Re-start sync engine and re-open sync servlet using the web admin console.

Propagation of Table Definition to Clients and Table Reload

The first sync after the server schema change will propagate the new schema definition to client. If a sync table was removed, the corresponding client DB table will be dropped. Also in general, if a sync table was updated, the corresponding client DB table will be altered.

Some updates to the sync table would cause the client DB table be dropped, re-created and re-populated with data from server. This is called a re-load.

If you change the subsetting query, clients may be assigned a different sub-set of data. Therefore, Pervasync will do a table re-load for all the clients. Altering a table’s primary key will cause the same.

If you change the values of subsetting parameters for a particular client, that client would get a reload for the affected tables. Other tables and clients won’t get a reload.

Advertisements

Data Subsetting Using a SQL Query with Parameters

A Step by Step Example of Data Subsetting

Let’s use the following table EMP of schema SCOTT as an example. Suppose you have your entire employee data stored in the EMP table of your central DB. The EMP table has the following definition. Each employee has an employ ID (column EMPNO) and belongs to a department (column DEPTNO):

CREATE TABLE “SCOTT”.”EMP”

(    “EMPNO” NUMBER(4,0),

    “ENAME” VARCHAR2(10),

    “JOB” VARCHAR2(9),

    “MGR” NUMBER(4,0),

    “HIREDATE” DATE,

    “SAL” NUMBER(7,2),

    “COMM” NUMBER(7,2),

    “DEPTNO” NUMBER(2,0),

     CONSTRAINT “PK_EMP” PRIMARY KEY (“EMPNO”) ENABLE,

     CONSTRAINT “FK_DEPTNO” FOREIGN KEY (“DEPTNO”)

     REFERENCES “SCOTT”.”DEPT” (“DEPTNO”) ENABLE

);

 

Your company has grown very big and become geographically distributed. Employees started to have problems accessing the EMP table because the central DB is under heavy load and the network is not always fast and stable. So you decide to create a local DB for each department. The EMP table in a local DB only contains data for employees belonging to that department. Here we are subsetting by DEPTNO. In real world applications, people may do subsetting by country, region, branch office name/ID, and clinic name/ID etc.

Following are the steps to take to use Pervasync to synchronize the EMP table in a local DB with the EMP table in the central DB.

  1. Prepare the central DB schema.

You may need to make some adjustments to the structure of your existing table to make it ready to be published as a sync table.

Pervasync requires that all sync tables have a primary key. The EMP table already has a primary key: column EMPNO. So, we are fine.

Assume we want to do the subsetting by DEPTNO. Then, we should have a table that defines the association between DEPTNO and EMPNO. One way to do this is to add a DEPTNO column to EMP table. EMP table already has a DEPTNO column, so we don’t need to do anything. Another way is to create a separate table that has two columns EMPNO and DEPTNO with EMPNO being the primary key column. You know what I mean if you learned about table normalization.

Now we have a decision to make: do we want to keep EMPNO as the sole primary key column or do we want to make DEPTNO and EMPNO together a composite primary key? Both have pros and cons. You make the decision based on your business requirements. If we keep EMPNO as the sole primary key column, we have to make sure that local DB do not assign conflicting EMPNO values when adding new employees locally. In Pervasync, you can create a sync sequence for the EMPNO column and draw globally unique values from the sync sequence locally (For more information and explanation of sync sequence, see section 5.5.2 Sync Sequence). If you make DEPTNO and EMPNO together a composite primary key, you only need to make sure EMPNO is locally unique when you add a new employee. If your company does not require every employee to have a company wide unique ID (value of EMPNO), you can choose the latter way.

In summary, to make a table ready to be published as a sync table, it has to have a primary key defined and an association between the primary key and the subsetting column defined.

  1. Publish the sync table and add it to the sync schema

When you define the sync table via the Pervasync web admin console at Sync Schemas-> Sync Tables-> Add new Sync Table, or via the admin Java API using method addSyncTable of class SyncServerAdmin, you have a chance to supply a data subsetting query. If you already have a sync table that you want to use for subsetting, you can click “Update”, and then edit “Subsetting Query”. Data subsetting query determines which rows go to which local database. There is no restriction on the query as long as it returns the Ids of the rows to be synced to a local DB. If we keep EMPNO as the sole primary key column we would use the following query:

SELECT EMPNO FROM SCOTT.EMP WHERE DEPTNO=${DEPTNO_PARAM}

 

If we make DEPTNO and EMPNO together a composite primary key we would use the following query:

SELECT DEPTNO, EMPNO FROM SCOTT.EMP WHERE DEPTNO=${DEPTNO_PARAM}

 

In the above queries, we have a placeholder, ${DEPTNO_PARAM}. The variables enclosed in ${} are subscription parameters. Queries for other tables could share the same parameter names. The collection of unique table level parameters becomes parameters for the published sync schema.

The queries in our example are among the simplest as they have only one parameter and reference only one table. One could have multiple parameters and use table joins in the query. Pervasync employs different algorithms for simple and complex queries to achieve maximum efficiency for both cases. You need to specify a subsetting mode when doing the subsetting: SIMPLE or COMPLEX. Subsetting mode SIMPLE is different from COMPLEX in that a SIMPLE query can select from only one table, which could be the sync table itself or a different table. For more information and explanation of SIMPLE or COMPLEX subsetting modes, see section 5.4.2: “Subsetting Modes: SIMPLE and COMPLEX”.

  1. Subscribe a sync user to a sync schema

For each local DB, you create a sync client – a combination of user and device. When you subscribe a sync client to a sync schema via the Pervasync web admin console at Sync Schemas-> Schema Subscriptions-> Add new Schema Subscription, or via the admin Java API method addSchemaSubscription of class SyncServerAdmin, you have a chance to supply a value for each of the subscription parameters. If you already have a Schema Subscription that you want to use for subsetting, you can click “Update Subscription”, and then enter the value of the parameter, which you specify as a placeholder in subsetting query at step 2. In our case, we will see DEPTNO_PARAM listed as a parameter name and we can assign a value. For example, if we want a sync client to sync data for DEPTNO=1, we put 1 as the value for DEPTNO_PARAM.

  1. Sync

During synchronization for the sync client we just subscribed, effectively the following query is executed:

SELECT EMPNO FROM SCOTT.EMP WHERE DEPTNO=1

 

So that only the rows with DEPTNO=1 are synced to this client.

 

Subsetting Modes: SIMPLE and COMPLEX

The parameterized SQL query is at the heart of data subsetting. There is virtually no restriction to the query as long as it returns the primary key values of the desired data sub-sets. This gives users great flexibilities but at the same time, it poses great challenges to the sync engine, which has to figure out physical and logical changes to the data sub-sets. Algorithms that apply to generic queries may not be scalable. On the other hand, algorithms that perform well for simple queries may not apply for complex queries.

Pervasync asks users to indicate the complexities of their queries via subsetting modes so that different algorithms can be applied to achieve best possible performance and scalability.

Criteria for SIMPLE query

There are two subsetting modes, SIMPLE and COMPLEX. Criteria for SIMPLE query are as follows.

  1. The query can reference only one table. This table can be the table you are subsetting or a different table.

    The query predicates that involve the table columns can use not only “=”, but also other conditional operators like “>”, “<“, and “like” etc. For example, the following queries qualify as SIMPLE queries,

    SELECT EMPNO FROM SCOTT.EMP WHERE DEPTNO=${DEPTNO_PARAM} AND MGR = ${MGR_PARAM}

 

SELECT EMPNO FROM SCOTT.EMP WHERE DEPTNO=${DEPTNO_PARAM} AND SAL < ${SAL_PARAM}

 

SELECT EMPNO FROM SCOTT.EMP WHERE SAL > ${SAL_MIN} AND SAL < ${SAL_MAX}

 

SELECT EMPNO FROM SCOTT.EMP WHERE JOB like ‘%Engineer’

 

  1. The query cannot use functions, expressions, joins, set operations like “union”, “intersect” etc.
  2. Query referenced columns (e.g. DEPTNO, MGR, SAL and JOB in the above examples) cannot have NULL values and the column data type cannot be too long. The reason is that these columns will become part of a primary key for a Pervasync internal table so they have to satisfy primary key column criteria of the database. If you cannot make these columns “NOT NULL” and have shorter length, mark the subsetting query COMPLEX.

Scalability implications

In general, SIMPLE queries are much more scalable than COMPLEX queries in terms of database space and sync engine processing time. For SIMPLE queries, sync engine performance is virtually independent of the number of sync clients you have.

COMPLEX queries can be scalable if a large number of clients share a same set of parameter values. For example, suppose you have 1000 clients and there are only 10 unique values for the subscription parameter DEPTNO_PARAM, the resources needed by sync engine are about the same as 10 clients each having a unique value for the parameter. Still, if at all possible, we recommend you use SIMPLE queries as opposed to COMPLEX queries.

Converting a COMPLEX Query to a SIMPLE Query

If you mark a SIMPLE query as COMPLEX, sync will still work but just not as efficiently. However, if you simply mark a COMPLEX query as SIMPLE, the sync may not work – you may find that client is not getting the changes you expect.

Fortunately, there are ways to convert a COMPLEX query to a SIMPLE query. For example, let’s say you want to sync users’ emails to their mobile devices and you use email recipient as subsetting parameter. The query qualifies as a SIMPLE query:

SELECT EMAIL_ID FROM USER_EMAILS WHERE RECEIPIENT = ${EMAIL_ADDRESS_1} OR RECEIPIENT = ${EMAIL_ADDRESS_2}

 

Now, let’s say you only want to sync last 30 days’ emails to save space on device. The query becomes COMPLEX:

SELECT EMAIL_ID FROM USER_EMAILS WHERE (RECEIPIENT = ${EMAIL_ADDRESS_1} OR RECEIPIENT = ${EMAIL_ADDRESS_2}) AND RECEIVE_DATE > (SYSDATE – INTERVAL ’30’ DAY(5))

 

To convert this query to a SIMPLE query, you can add a column INCLUDE_IN_SYNC, which takes values of “Y” for yes and “N” for no and defaults to “N”. You create a DB job to update the INCLUDE_IN_SYNC values every night:

UPDATE USER_EMAILS SET INCLUDE_IN_SYNC=”Y” WHERE INCLUDE_IN_SYNC=”N” AND RECEIVE_DATE > (SYSDATE – INTERVAL ’30’ DAY(5))

 

With this in place, you would be able to use the following SIMPLE query to achieve the same result as the original COMPLEX query.

SELECT EMAIL_ID FROM USER_EMAILS WHERE (RECEIPIENT = ${EMAIL_ADDRESS_1} OR RECEIPIENT = ${EMAIL_ADDRESS_2}) AND INCLUDE_IN_SYNC=”Y”

Doing Synchronization Using Pervasync Client for Android and Blackberry

We will first show the Pervasync client working in standalone mode and then describe how to embed the client in to your Android or Blackberry app.

Starting Sync Sessions and Viewing Sync History

Once the sync client is installed and setup, you can click on the “Start Sync” button on the Sync screen of the Pervasync client.

During synchronization, the Sync screen will show you the progress. Once completed, the sync history is available on the History screen. For Android, you switch between screens by clicking on the tabs while for Blackberry, you click on the menu items.

NOTE: If you see non-empty “Sent(bytes)” but empty “Received” and sync seems to get stuck, most likely you have a typo in sync URL or the sync server is not up. Use the “Setup” tab to correct the URL. Make sure you have the right IP and port number.

Below are Sync and History screen shots for Android and Blackberry respectively.

Updating Setup Info and Configuring Auto Sync

NOTE: In the following we will only show screen shots for Android. Blackberry screens are similar. The main difference is that instead of tabs, you usually use menu items to navigate to different screens on Blackberry.

The Setup screen allows you to update the setup info. It also allows you to reset the client to pre-setup state.

The Scheduler screen allows you to schedule sync jobs so that you don’t have to manually initiate each sync session. Normally you would turn on the “Repeat” flag to make the sync happen periodically with a preset sync interval. Note that you need to have both the Job Scheduler running and the job enabled for the auto sync to be on.

Database and File Browser

The Browser screen allows you to inspect the databases and files that are synced to the device. You may want to hide this functionality from end users after you compose your own user interface to the synced data. However, it’s a great tool to use during development of your application that uses Pervasync for data synchronization.

The Browser screen lists all the schemas/databases and folders. Clicking on a schema will bring up a dialogue with options to show tables or sequences that belong to the schema.

Following are the table list and sequence list.

Click on table to show table definition and table data. The table data screen will by default show 10 rows. You can change the Fetch Limit to show more or less than that. You can also put a predicate in the Where Clause box to show the desired rows, for example:

NAME like ‘%Jonh%’

Click on a row to bring up the row editor screen where you can delete or update the row data. You could also insert a new row using this screen.

Back to the main Browser screen, you can click on a sync folder to show the sub folders and files.

Syncing Data and Files to External Storage

If you run the sync client in standalone mode (as opposed to embedding it into your device app), your app usually won’t be able to access the synced data unless the data is on external storage. To sync data and files to external storage, prefix the client schema name and client folder name with “EXTERNAL;”. Note the trailing semi colon.

Embedding Pervasync Client into Your Android Application on Device

If you run the sync client in standalone mode, your app usually won’t be able to access the synced data unless the data is on external storage. Instead, if you embed the sync client into your own application, both the sync client code and your app code share the same permissions to the data and you would be able to store the data on internal and external storages.

The “android/lib” folder of your Pervasync server home has a Pervasync client library jar that you can easily include into your app.

Let’s assume you created an Android project “my_android_app” in your Eclipse workspace. Your package name is “com.mycorp.myapp” and your main Activity is “MyMainActivity”. The AndroidManifest.xml of your project would look like the following:

<?xml
version=“1.0”
encoding=“utf-8”?>

<manifest package=“com.mycorp.myapp” android:versionCode=“1”

    android:versionName=“1.0” xmlns:android=http://schemas.android.com/apk/res/android&#8221;>

    <application
android:icon=“@drawable/icon”

        android:label=“My Android App”>

        <activity
android:name=“.MyMainActivity”
android:label=“@string/app_name”>

            <intent-filter>

                <action
android:name=“android.intent.action.MAIN” />

                <category
android:name=“android.intent.category.LAUNCHER” />

            </intent-filter>

</application>

    <uses-sdk
android:minSdkVersion=“7”
android:targetSdkVersion=“7” />


</manifest>

Following are the steps to embed Pervasync client.

Add Pervasync Android client library to Java Build Path

Right click on your Eclipse project for your Android app and open the “Properties” window. Click on “Java Build Path” on the left panel and then click the “Libraries” tab on the right panel. Click on “Add External JARs…” button to add Pervasync Android client library “pervasync_android_lib-4.0.0.jar” which is located in the “android/lib” folder of Pervasync server home.

NOTE: If your Pervasync server and your Eclipse IDE are on different hosts, just copy the jar to your Eclipse host.

After adding the jar, click the “Order and Export” tab. Select the check box in front of “pervasync_android_lib-4.0.0.jar”.

Add Pervasync Activities and Permissions to AndroidManifest.xml

Copy-paste the “activity” and “uses-permission” elements from the following sample AndroidManifest.xml (see also android/AndroidManifest_sample.xml) to your AndroidManifest.xml.

NOTE: Don’t copy the grayed-out parts. Your AndroidManifest.xml should already have them.

<?xml version=“1.0” encoding=“utf-8”?>

<manifest package=“com.mycorp.myapp” android:versionCode=“1”

    android:versionName=”1.0″ xmlns:android=”http://schemas.android.com/apk/res/android”&gt;

    <application android:icon=“@drawable/icon”

        android:label=“My Android App”>

        <activity android:name=“.MyMainActivity” android:label=“@string/app_name”>

            <intent-filter>

                <action android:name=“android.intent.action.MAIN” />

                <category android:name=”android.intent.category.LAUNCHER” />

            </intent-filter>

        </activity>

        <activity android:name=“pervasync.ui.android.PervasyncClientActivity”

            android:label=“Pervasync”>

        </activity>


        <service
android:name=“pervasync.ui.android.PervasyncService”>

            <intent-filter>

                <action
android:name=“pervasync.ui.android.PervasyncService” />

            </intent-filter>

        </service>

        <activity android:name=“pervasync.ui.android.PervasyncSyncActivity”

            android:label=“Pervasync Sync”>

        </activity>

        <activity android:name=“pervasync.ui.android.AutoSyncSchedulerActivity”

            android:label=“Pervasync Scheduler”>

        </activity>

        <activity android:name=“pervasync.ui.android.PervasyncHistoryActivity”

            android:label=“Pervasync Sync History”>

        </activity>

        <activity android:name=“pervasync.ui.android.PervasyncSetupActivity”

            android:label=“Pervasync Setup”>

        </activity>

        <activity android:name=“pervasync.ui.android.PervasyncBrowserActivity”

            android:label=“Pervasync Browser”>

        </activity>

        <activity android:name=“pervasync.ui.android.SchemaTablesActivity”

            android:label=“Schema Tables”>

        </activity>


        <activity android:name=“pervasync.ui.android.FolderFilesActivity”

            android:label=“File Browser”>

        </activity>

        <activity android:name=“pervasync.ui.android.SchemaSequencesActivity”

            android:label=“Schema Sequences”>

        </activity>

        <activity android:name=“pervasync.ui.android.TableRowsActivity”

            android:label=“Table Data”>

        </activity>

        <activity android:name=“pervasync.ui.android.TableColumnsActivity”

            android:label=“Table Column Types”>

        </activity>

        <activity android:name=“pervasync.ui.android.RowEditActivity”

            android:label=“Row Edit”>

        </activity>

        <activity android:name=“pervasync.ui.android.ImageFileActivity”

            android:label=“Image File”>

        </activity>

        <activity android:name=“pervasync.ui.android.TextFileActivity”

            android:label=“TextFile”>

        </activity>

        <receiver
android:enabled=“true”
android:name=“pervasync.ui.android.BootUpReceiver”

            android:permission=“android.permission.RECEIVE_BOOT_COMPLETED”>

            <intent-filter>

                <action
android:name=“android.intent.action.BOOT_COMPLETED” />

                <category
android:name=“android.intent.category.DEFAULT” />

            </intent-filter>

        </receiver>

    </application>

    <uses-sdk android:minSdkVersion=“7” android:targetSdkVersion=“7” />

<uses-permission
android:name=“android.permission.RECEIVE_BOOT_COMPLETED” />

    <uses-permission
android:name=“android.permission.ACCESS_NETWORK_STATE”></uses-permission>

    <uses-permission
android:name=“android.permission.ACCESS_WIFI_STATE”></uses-permission>

    <uses-permission
android:name=“android.permission.INTERNET”></uses-permission>

    <uses-permission
android:name=“android.permission.WRITE_EXTERNAL_STORAGE”></uses-permission>

</manifest>

Invoke Pervasync Client from Your App Code

With the inclusion of the library and the additions to the manifest file, Pervasync is now part of your application. You can now invoke Perasync. In the main activity of your app, you should start the Pervasync service so that it can perform auto-sync in the background:

if (!PervasyncService.isStarted()) {

    startService(new Intent(this, PervasyncService.class));

}

To show the Pervasync UI, start the Pervasync client activity:

Intent intent = new Intent(myMainActivity,

PervasyncClientActivity.class);

startActivity(intent);

Following is a sample main activity:

package com.mycorp.myapp;

import pervasync.ui.android.PervasyncService;

import pervasync.ui.android.PervasyncClientActivity;

import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.view.Gravity;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.LinearLayout;

import android.widget.TextView;

import android.widget.LinearLayout.LayoutParams;

/*

* This is the main screen of your app

*/

public
class MyMainActivity extends Activity {

    private
static
final
int
SYNC_CLIENT_ID = 0;

    private
final MyMainActivity myMainActivity = this;

    /** Called when the activity is first created. */

    @Override

    public
void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        // start Pervasync service if not already started.

        if (!PervasyncService.isStarted()) {

            startService(new Intent(this, PervasyncService.class));

        }

        // set title

        setTitle(“Pervasync Sample App”);

        // contentView is a LinearLayout

        LinearLayout contentView = new LinearLayout(this);

        contentView.setOrientation(LinearLayout.VERTICAL);

        this.setContentView(contentView);

        // empty line

        contentView.addView(new TextView(myMainActivity));

        // description

        String description = “This is a place holder main screen for your application. “

                + “You can replace the title, add UI components to the screen and add “

                + “child screens that can be linked from this main screen.\n\n”

                + “We added a button below that invokes the Pervasync Client main screen where users can setup “

                + “Pervasync and perform synchronization.\n\n”

                + “The Pervasync Client also includes a database browser for you to explore the “

                + “synced databases during developemnt time. You could hide the browser in the production “

                + “version of your app.”;

        TextView textView = new TextView(this);

        textView.setText(description);

        contentView.addView(textView);

        // empty line

        contentView.addView(new TextView(myMainActivity));

        // buttonBar

        LinearLayout buttonBar = new LinearLayout(myMainActivity);

        buttonBar.setGravity(Gravity.CENTER); // How button bar aligns its

                                                // children

        buttonBar.setOrientation(LinearLayout.HORIZONTAL);

        contentView.addView(buttonBar, new LinearLayout.LayoutParams(

                LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));

        // Launch Pervasync Client button

        Button pervasyncButton = new Button(this);

        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(

                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

        pervasyncButton.setLayoutParams(params);

        pervasyncButton.setText(“Launch Pervasync Client”);

        pervasyncButton.setTag(“Pervasync”);

        pervasyncButton.setOnClickListener(new OnClickListener() {

            public
void onClick(View view) {

                Button button = (Button) view;

                if (“Pervasync”.equalsIgnoreCase((String) button.getTag())) {

                    Intent intent = new Intent(myMainActivity,

                            PervasyncClientActivity.class);

                    startActivity(intent);

                }

            }

        });

        buttonBar.addView(pervasyncButton);

    }

    @Override

    public
boolean onCreateOptionsMenu(Menu menu) {

        menu.add(Menu.NONE, SYNC_CLIENT_ID, Menu.CATEGORY_CONTAINER,

                “Launch Pervasync Client”);

        return (super.onCreateOptionsMenu(menu));

    }

    @Override

    public
boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {

        case
SYNC_CLIENT_ID:

            startActivity(new Intent(myMainActivity,

                    PervasyncClientActivity.class));

            return (true);

        default:

            ;

        }

        return
super.onOptionsItemSelected(item);

    }

}

You can now build and run your Android app.

Advanced Topics

OTA Deployment

Once you package and sign your app with Android signature tool, you will have an apk file generated. Copy the apk file, e.g. my_android_app.apk, to <Pervasync Server Home>/web/pervasync/download and your users can install the app over-the-air (OTA) by entering the following URL in their mobile browser:

http://<Pervasync_Host&gt;:<port>/pervasync/download/my_android_app.apk

Javadoc

You can find Javadoc of the Pervasync client interface in <Pervasync Server Home>/android/doc. Open the index.html in a browser.

Embedding Pervasync Client into Your Blackberry Application on Device

If you embed the sync client into your own application, both the sync client code and your app code share the same permissions to the data. This allows you to secure the data so that only your app (including sync code) can access the data.

The “blackberry/lib” folder of your Pervasync server home has a Pervasync client library jar that you can easily include into your app.

Let’s assume you created a Blackberry project “my_blackberry_app” in your Eclipse workspace. Your package name is “com.mycorp.myapp” and your UIApplication is “MyBlackberryApp”. You also have a MainScreen called “MyMainScreen”.

Following are the steps to embed Pervasync client.

Add Pervasync Blackberry client library to Java Build Path

Right click on your Eclipse project for your Blackberry app and open the “Properties” window. Click on “Java Build Path” on the left panel and then click the “Libraries” tab on the right panel. Click on “Add External JARs…” button to add Pervasync Blackberry client library “pervasync_blackberry_lib-4.0.0.jar” which is located in the “blackberry/lib” folder of Pervasync server home.

NOTE: If your Pervasync server and your Eclipse IDE are on different hosts, just copy the jar to your Eclipse host.

After adding the jar, click the “Order and Export” tab. Select the check box in front of “pervasync_blackberry_lib-4.0.0.jar”.

Enable Auto-Run

Open Blackberry_App_Descriptor.xml under your app project and select the checkbox “Auto-run on start”. This is to auto start your app after a device re-boot so that your app can do auto-sync in the background.

Invoke Pervasync Client from Your App Code

With the inclusion of the library, Pervasync is now part of your application. In the UIApplication “MyBlackberryApp” of your app, you should start the Pervasync JobScheduler so that it can perform auto-sync in the background:

if(!SyncClient.needSetup()){

SyncClient.restartJobScheduler();

}

To show the Pervasync UI, push PervasyncSyncScreen in your MyMainScreen class:

UiApplication.getUiApplication().pushScreen(

                    new PervasyncSyncScreen());

Following is a sample UIApplication “MyBlackberryApp”:

package com.mycorp.myapp;

import pervasync.client.SyncClient;

import net.rim.device.api.ui.UiApplication;

public
class MyBlackberryApp extends UiApplication {

    /**

     * This is a place holder for your Blackberry application.

     * You could replace the package name and class name.

     * @param args

     * @throws Exception

     */

    public
static
void main(String[] args) throws Exception {

        MyBlackberryApp myBlackberryApp = new MyBlackberryApp();

        myBlackberryApp.enterEventDispatcher();

    }

    /**

     * Constructor. Displays the main screen of your application

     * @throws Exception

     */

    public MyBlackberryApp() throws Exception {

        // start Pervasync job scheduler if you want to have auto sync

        if(!SyncClient.needSetup()){

            SyncClient.restartJobScheduler();

        }


        // show the app main screen

        pushScreen(new MyMainScreen());

    }

}

Following is a sample MainScreen “MyMainScreen”:

package com.mycorp.myapp;

import net.rim.device.api.ui.Font;

import net.rim.device.api.ui.MenuItem;

import net.rim.device.api.ui.UiApplication;

import net.rim.device.api.ui.component.Dialog;

import net.rim.device.api.ui.component.LabelField;

import net.rim.device.api.ui.component.RichTextField;

import net.rim.device.api.ui.component.SeparatorField;

import net.rim.device.api.ui.container.MainScreen;

import pervasync.client.SyncClient;

import pervasync.ui.blackberry.PervasyncSyncScreen;

public
class MyMainScreen extends MainScreen {

    /**

     * Constructor

     */

    public MyMainScreen() {

        // set page title

        LabelField title = new LabelField(“My Blackberry App”,

                LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH);

        setTitle(title);

        // set header

        addHeader(“My Blackberry App Main Screen”);

        // set description

        String description = “This is a place holder main screen for your application. “

            + “You can replace the title, add UI components to the screen and add “

            + “child screens that can be linked from this main screen.\n\n” +

            “We added a menu item that invokes the Pervasync Client main screen where users can setup “+

            “Pervasync and perform synchronization.\n\n” +

            “The Pervasync Client also includes a database browser for you to explore the “+

            “synced databases during developemnt time. You could hide the browser in the production “ +

            “version of your app”;

        RichTextField richTextField = new RichTextField(description,

                RichTextField.READONLY);

        add(richTextField);

    }

    /**

     * Helper to add a bold typed header

     * @param labelStr

     */

    private
void addHeader(String labelStr) {

        LabelField labelField = new LabelField(labelStr,

                LabelField.FIELD_HCENTER);

        labelField.setFont(labelField.getFont().derive(Font.BOLD));

        this.add(labelField);

        this.add(new SeparatorField());

    }

    /**

     * Put the app in the background when closing.

     */

    public
boolean onClose() {

        UiApplication.getUiApplication().requestBackground();

        return
true;

    }

    /**

     * Kill the app on exit

     */

    private
void exit() {

        if (SyncClient.isSynchronizing()) {

            int retVal = Dialog

                    .ask(Dialog.D_YES_NO,

                            “Exiting will kill the on-going sync session. Are you sure you want to exit?”);

            if (retVal == Dialog.YES) {

                System.exit(0);

            }

        } else {

            System.exit(0);

        }

    }

    /**

     * Pervasync Client Menu Item

     */

    private
final
class PervasyncMenuItem extends MenuItem {

        private PervasyncMenuItem() {

            super(“Pervasync Client”, 1, 1);

        }

        public
void run() {

            UiApplication.getUiApplication().pushScreen(

                    new PervasyncSyncScreen());

        }

    }

    /**

     * Exit Menu Item

     */

    private
final
class ExitMenuItem extends MenuItem {

        private ExitMenuItem() {

            super(“Exit”, Integer.MAX_VALUE, 1);

        }

        public
void run() {

            exit();

        }

    }

    /**

     * This is called when user invokes menu

     */

    public
boolean onMenu(int instance) {

        removeAllMenuItems();

        addMenuItems();

        return
super.onMenu(instance);

    }

    private
void addMenuItems() {

            PervasyncMenuItem pervasyncMenuItem = new PervasyncMenuItem();

            this.addMenuItem(pervasyncMenuItem);

        ExitMenuItem exitMenuItem = new ExitMenuItem();

        this.addMenuItem(exitMenuItem);

    }

}

You can now build and run your Blackberry app.

Advanced Topics

Encryption

To encrypt the database, prefix the client schema name with “ENCRYPT;” when you publish the sync schema. If you want it be both encrypted and stored on external storage, use prefix “EXTERNAL; ENCRYPT;”.

Note that other apps on the device can still access the databases when it’s encrypted. To further secure your DB so that only your app can access it, use prefix “PROTECT;”.

OTA Deployment

Once you package and sign your app with Blackberry signature tool, you will have a jad file and some cod files generated (e.g. in <your project root>/deliverables/Web/6.0.0). Copy these files to <Pervasync Server Home>/web/pervasync/download and your users can install the app over-the-air (OTA) by entering the following URL in their mobile browser:

http://<Pervasync_Host&gt;:<port>/pervasync/download/my_blackberry_app.jad

Javadoc

You can find Javadoc of the Pervasync client interface in <Pervasync Server Home>/android/doc. Open the index.html in a browser.

Doing Synchronization Using Pervasync Client for Oracle and MySQL

Locate pvc.bat (for Windows) or pvc.sh (for Linux) in the “bin” folder of Pervasync client home. Invoke it with the “-h” option to show its usage:

C:\pervasync\bin>pvc -h

 

Usage

—–

pvc.bat [{sync|refresh|checkin|auto_sync|sys_tray} [<password>]]

 

Use this command to launch the Pervasync Client Configuration and Sync Utility.

If no arguments are specified, i.e.

 

pvc.bat

 

the sync client GUI will be launched.

 

If “sys_tray” is specified as an argument, i.e.

 

pvc.bat sys_tray

 

the sync client GUI will be launched in system tray (minimized).

 

Otherwise, it will run in non-GUI mode.

Use the “sync” sub-command to do two-way sync, e.g.

 

pvc.bat sync

 

Use “refresh” and “checkin” to do one-way sync.

 

You use “auto_sync” option to start the job scheduler for running sync jobs

at pre-arragned times. Use the “Schedule” tab of the GUI to update job schedules.

 

You can optionally supply the sync user password as a second argument.

Stored password will be used if it is absent.

 

Note that the JDBC jar file (for Oracle) or Java connector jar file

(for MySQL) has to be available in folder ../lib to run this script.

If invoked without any arguments, the client will run in GUI mode. In GUI mode, users can start or schedule sync sessions by pointing and clicking.

 

NOTE: You close the GUI window to terminate the client. When you do that, you will be given an option to run the client in system tray. There is also a command-line option “sys_tray” to “pvc.bat” that you can use to launch the client to run directly in system tray. You may want to create a Windows task to do this upon system re-boot. This is useful to run scheduled sync tasks in background.

 

The Sync Tab of the Pervasync Client GUI

Go to the “bin” folder and invoke “pvc.bat” for Windows or “pvc.sh” for Linux. A GUI window will pop up. There are five tabs, Setup, Sync, Schedule, Export and Import. Setup tab is used for setup and reset. Click on Sync tab you will see the following.

Listed below are the GUI settings that need some explanations:

Sync Direction: By default, it’s TWO_WAY sync. You can use “REFRESH_ONLY” and “CHECK_IN_ONLY” to do one-way sync.

Sync User Password: You can optionally supply the sync user password. Stored password will be used if it is absent. You can have the password saved using the setup tab, or use the sync tab and click on the “Save Password” checkbox.

Single Session: When there are sync definition changes in a sync session, Pervasync will only download the definition changes and leave data changes to next sync session. By default, Pervasync will do two sync sessions with one “Sync” button click when there are sync definition changes to make sure both sync definition and data changes are synced. Check this checkbox to perform only one sync session with one click.

NOTE: If sync client resides inside a firewall and sync server resides outside the firewall, you need to set the HTTP proxy host and port using the setup tab with “Advanced Mode” turned on.

You can change the default settings if you need to. Then, click “Sync” to invoke the Sync Agent to do synchronization.

Once the sync session is completed you will see an alert box telling you whether the session succeeded or failed. The “Sync History” panel on the “Sync” tab will also show you a summary of completed sessions.

If the sync fails, first check the error stack trace on the “Sync History” panel. For more detailed debugging info, check the log files under <Pervasync Client Home>/log. If you cannot resolve the issue yourself, send the log file to Pervasync support at support@pervasync.com.

The Schedule Tab of the Pervasync Client GUI

The Schedule tab enables you to schedule up to three sync jobs that do background synchronization at a pre-determined time. In addition to the start time, you also can specify the sync direction and optionally, the sync interval.

Before you schedule background sync jobs, make sure you have the sync user password saved using the “Setup” or the “Sync” tabs.

Click “Schedule” button to start a job and click on “Cancel” button to stop a job. A scheduled sync will be skipped if there is already a sync going on at the scheduled sync start time. Sync history is available on the sync tab.

NOTE: All sync jobs will be cancelled if you exit the sync client.

Creating Publications and Subscriptions Using the Web Admin Console

Pervasync enables you to synchronize distributed local databases with a central database without writing a single line of code. You start with a central DB with existing schemas and schema objects. The local DB should be initially empty. You use the web based admin console to publish central database objects and subscribe clients to the publications. Then on the client machine you use a shell script (pvc.sh or pvc.bat) to invoke the sync agent to initiate a sync session. The very first sync session will create the subscribed sync schemas and schema objects in local DB. The second sync will copy the central DB schema data to client schemas. After that, synchronization will be incremental – only changes on client and server will be exchanged.

Alternatively you can use the server and client side Java API to do publication, subscription and synchronization from your Java application.

You use the web based sync server admin console to publish sync objects and create subscriptions. Besides publications and subscriptions, the admin console is also used to monitor and control the sync servlet and sync engine, manage devices, users and groups.

Logging in to the Admin Console

Once the Pervasync web application is deployed in the J2EE servlet container, the admin console will be available at http://<server>:<port>/pervasync, e.g. http://localhost:8080/pervasync. The following is the login page.

Use the admin user name and password you specified when you setup the Pervasync server to login.

Admin Console Home

Once logged in, you will see the admin console home page.

The admin console allows you to check the status of the sync servlet and the sync engine as well as startup/shutdown them.

The Sync Engine helps preparing server side logical transactions to be used to refresh client side databases and folders to new states. Sync Servlet serves sync clients receiving transactions (Check-Ins) from clients and sending transactions to clients. You need to have both Sync Servlet and Sync Engine up for synchronization to work. However, when you are creating publications and subscriptions, it is better to temporally shutdown both.

The Publish and Subscribe Model

Pervasync employs a publish and subscribe model. You first define sync schemas and sync folders as publications. Then you subscribe sync clients or groups to a set of publications. Publications may have parameters defined. At subscription time, you supply values to the parameters to customize the subscription. For example, you may define “region” as a parameter of your publications. Then at subscription time, you assign a value to region for subscribers so that they get data related to a specific region.

Click on the Publications tab to show all available publications. There are two types of publications: sync schemas and sync folders. A sync schema is a container for database tables and other objects while a sync folder is a container for files.

Publishing Sync Schemas

A sync schema corresponds to a physical DB schema. You may create multiple sync schemas for a single DB schema. However, one table can only belong to one sync schema.

On the Publications page click on “Add Sync Schema” button under Sync Schemas header to add a schema.

Move mouse cursor over the fields for tooltips.

The No-Init-Sync Networks and No-Sync Networks fields are for the “sync based on network characteristics” feature. This enables you to automatically skip (initial or all) synchronization of a publication if certain network card is used (for reasons such as being too expensive or too slow etc.). If you do not need to use this feature, just keep the default value, which is “NONE”, unchanged.

To use “sync based on network characteristics” feature, first, you need to gather information about network characteristics of your client machines. After you setup Pervasync client, you can use the utility listnetworks.bat (or listnetworks.sh for Linux) in the bin folder of Pervasync client home to list the display names, hardware addresses and IP addresses of your network cards on client machines. Then, on Pervasync admin console, you need to change the value of the No-Init-Sync Networks and No-Sync Networks fields from the default value “NONE” into a value which contain matching strings that identify the network cards. You may use full strings or sub-strings of the following network card attributes: display name, hardware address and IP address. You may also have “&&” and/or “||” between the strings to indicate whether it’s “match all” or “match any” respectively. Here when you add new sync schema, you specify global values of the no-sync lists that apply to all user devices. At subscription time you have a chance to overwrite the values for a specific user device or group. For more information and explanation regarding “sync based on network characteristics” feature, refer to chapter 5, section 13, i.e., 5.13, “Sync Based on Network Characteristics”.

After the schema is created, you go back to the Publications page and click on the “Tables” link under “Schema Objects” to find the published tables of the schema.

Initially there is no sync table. Click on “Add Sync Table” to select a table and specify columns and rows to sync.

In the above screen shot, we selected table “employees” and chose to sync all columns and rows to clients that subscribe to the schema “schema_1”.

Note: Table names and column names cannot contain spaces. For example, table name “xxxx table” is not supported. We suggest you replace spaces with underscores. For example, use “xxxx_table” instead of “xxxx table”.

Rank is used to indicate the referential relationship among the sync tables. Parent tables should have a smaller rank number than child tables. When you insert new records, you would insert first to a parent table and then to a child table as the child table records reference columns in the parent table.

If “Allow Refresh” is checked, Pervasync server will refresh changes to the table to Pervasync clients. If “Allow CheckIn” is checked, sync clients can check in client changes to this table on server. “CheckIn SuperUsers” takes a comma-separated list of users who are allowed to check in even when “Allow CheckIn” is not checked.

Subsetting mode and query are used to identify the rows of the table to be synced to clients. Use subsetting query to specify the primary key query as row filters. The query should return the set of the primary key values of the selected rows. The query can have parameters enclosed in “${}”. The parameter values are set at subscription time.

Subsetting mode SIMPLE is different from COMPLEX in that a SIMPLE query can select from only one table, which could be the sync table itself or a different table.

“Query Referenced Tables” takes a comma-separated list of tables that are referenced in the subsetting query. This is only for subsetting mode COMPLEX.

Note: Subsetting is an advanced and complicated topic. If you are confused, you can leave all fields with default values. To further understand data subsetting, see section 5.3.1 A Step by Step Example of Data Subsetting and section 5.3.2 Subsetting Modes: SIMPLE and COMPLEX.

Publishing Sync Folders

If you need to sync files in a folder, you can achieve it by publishing sync folders, which is what this section is about. If you do not need to do this, you can skip this section.

On the Publications page click on “Add Sync Folder” button under “Sync Folders” header to add a folder for synchronization.

Move mouse cursor over the fields for tooltips.

Sync Folder Name: A unique name for the sync folder, e.g., “folder_1”.

Server Folder Path: The server side folder path, e.g., “c:\ server_folder”. If not starting with “/” or drive letter and “:”, it will be treated as relative to Pervasync server root folder.

 

Client Folder Path: The sync client side folder path, e.g., “c:\ client_folder”. It can have parameters to bind to values at subscription time. Parameters are enclosed by “${}”. If not starting with “/” or drive letter and “:”, it will be treated as relative to Pervasync client root folder. You can also have env variables in client folder path. These env variables should be enclosed in a pair of % signs. They will be substituted with env variable values on client side.

 

NOTE: Use % pairs instead of ${} for env variables regardless of whether your client machine is Windows or Linux.

 

Prefix Filters: Filters on file relative paths. All files in the server root folder have a relative path. For example, “c:\ server_folder\user_1\ images\file1.gif” has a relative path of “user_1\images\file1.gif”. The prefix filters apply to the file relative path. For example, if the value of prefix filter is set to “user_1\images\”, any file whose relative path starts with “user_1\images\” will be synced. Multiple filters can be supplied using comma as separator. A file would pass this “starts with” test if it passes any one of the prefix filters. However, a file has to pass both the “starts with” (Prefix Filter) and the “ends with” (Suffix Filter – see below) tests to be selected. It can have parameters to bind to values at subscription time. Parameters are enclosed by “${}”. If you do not need to use this, simply leave the field empty.

 

Suffix Filters: File filter by filename suffix or extension, which corresponds to what filename ends with. These are comma (“,”) separated file filters by file name suffix. For example: if “.gif,.jpeg,.png,.PNG,.doc” is set, any file whose name ends with “.gif” , “.jpeg”, “.png”, “.PNG”, or “.doc” will be synced. If you do not need to use this, simply leave the field empty.

 

Check In Super Users: Comma (“,”) separated list of users who are allowed to check in even when “Allow Check In” is set to false. If you do not need to use this, simply leave the field empty.

 

No-Init-Sync Networks: Refer to last section (Publishing Sync Schemas) for explanations.

No-Sync Networks: Refer to last section (Publishing Sync Schemas) for explanations.

You can publish a server folder by specifying its path. The folder will be synced to client machine. The client folder name does not have to be the same as the server’s. You can even put parameters in the client folder path so that different clients could have a different folder. Parameters should be enclosed in ${}, just as in table subsetting query. These parameters should be assigned a value at subscription time.

Once a folder is published, you can associate it with one or more clients by creating a folder subscription.

Managing Groups

Publications can be subscribed in two ways. One is direct subscription by sync clients on user devices (See section 5.1.7 and 5.1.8); the other is indirect subscription through groups. In this section, we are going to discuss the latter, i.e., managing groups.

Very often you have a group of clients that share the same set of publications and even subscription parameters. In this case it is more convenient to create groups and group subscriptions first and then add/remove clients to/from the groups. Clients will inherit group subscriptions.

You can choose either indirect or direct subscription based on your situation. If you do not need to manage groups, you can skip this section and go ahead to read section 5.1.7 and 5.1.8 for direct subscription by sync clients.

Click on Groups tab to view existing groups.

When you delete a group, you have an option to keep the group members (sync clients). The clients’ group will be set to NULL if you choose “Delete Group Only”.

Initially you may not have any groups. Click on “Add Client Group” to add one.

Go back to Groups page, find the group and click on button “Subscriptions”.

The Group Subscriptions page lists all the available publications, subscribed or not. Subscribed publications (including sync schemas and sync folders) have their name bold-typed and you can select and un-subscribe them. For publications that are currently not subscribed, you can click on the “Add” button to add them to the group’s subscriptions.

Before you click the Add button, fill in the values for the parameters to customize the subscription. These values will be shared by all clients that will later be added to this group.

Refer to section 5.1.4 Publishing Sync Schemas for explanations of fields “No-Init-Sync Networks” and No-Sync Networks”. Note that you can set the no-sync list values at three levels: publication, group subscription and client subscription. Publication level values are inherited and can be overridden by group subscription values, which in turn are inherited and can be overridden by client subscription values.

Similarly, you can add sync folder publications to a group subscription.

If you un-subscribe a group from a publication, all clients that belong to the group would lose the subscription.

In the following we will create a user-device (client) and do the subscription.

Managing Sync Clients

Click on the “Clients” tab.

Initially you may not have any sync clients. Click on “Add New Sync Client”.

Here we create user “john.doe” and add device “DEFAULT”. We put in a password and check “Create User” to create the user in Pervasync repository. Alternatively, you could choose to manage users and their passwords yourself. See javadoc for interface pervasync.server.UserManager for details. In that case you need and only need to specify User Name and Device name to add the sync client.

When you create a client you can assign it to a group.

Creating Subscriptions

Click on “Subscriptions” button on the row of the sync client on the Clients page.

If you have assigned a group for the client, you would see the client has all the group subscriptions. Click on Update (or Add if not subscribed) button on the row of the publication.

A subscription is an association of a client with a publication, in our case, user john.doe’s DEFAULT device and schema “schema1”. Edit the parameter values if needed and click button “Update” to update the client subscription.

Once you have successfully created publications, user-devices and subscriptions using the web admin console, you are ready to execute synchronizations using a sync client as described in 5.2.

Checking Client Sync History

On the admin console Home click on link “Sync Session History” under section “Sync Servlet”. This page is useful for admin to identify client sync issues in the field and track user synchronization trends.

The “Clients” page also shows each client’s last sync status and provides a link to sync history for a specific client.

Installing Pervasync Client for SQLite on Android and Blackberry

Pervasync clients for Android and Blackberry synchronize the on device native SQLite databases with your central database. The installation process includes downloading and setting up.

 

NOTE: Pervasync supports Android version 1.5 and newer, Blackberry version 5.0 and newer.

 

Download and Install the Binaries

Enter the following URL to the web browser on your mobile device.

 

http://<sync server name>:<port>/pervasync

 

You will be presented with the Pervasync start page where you can find the links to the Pervasync client apk file for Android and jad file for Blackberry. Click to download and install.

 

NOTE: If you are using a Blackberry device simulator, you will need to start the MDS simulator in order for the Blackberry browser to work. Also, on devices with Blackberry OS 5.0, the Pervasync start page may not be rendered properly. In that case, enter the following URL of the jad file directly to the browser on your Blackberry.

 

http://<sync server name>:<port>/pervasync/download/pervasync.jad

 

Below are screen shots for installation of Pervasync on Android devices.

 


 

On Blackberry devices you will see the following.

 



 

After a successful installation, you can find Pervasync app icon among other installed apps. Click to launch the client app.

 

Setup Pervasync Client

The first time you launch the Pervasync client, you will be presented with the sync client setup screen, which has the following fields to fill in.

 

  • Server Url – Pervaync server url. Use the name/IP of the host that has the sync servlet deployed. Don’t forget the port number if it’s not 80.
  • Sync User Name – Pervasync user name. The user and device should be created on sync server using server admin API or the web-based admin console. This can be done before or after client setup. The user name, device name and user password that are set here have to match those that are created on server so that the client can sync with the server.
  • Device Name – Pervasync user device name. By default, it’s DEFAULT.
  • User Password – Pervasync user password.

 

Optionally you can change the sync direction and log level.

 

Following are screen shots for Android and Blackberry devices respectively.

 



 



 

Click “Setup” button to start the setup process. Once you are done with the setup, Pervasync client will be re-launched displaying the “Sync” tab for Android and “Sync” screen for Blackberry. You are now ready to start a sync session. Jump to section 5.3 to learn how to do synchronization, browse synced tables and files and how to embed the sync client into your on-device application.

Cloning Pervasync Client to Avoid Costly Initial Sync

Initial sync could take a long time if you have Gigabytes of application data or files to sync. If a lot of the data or files are shared by all or groups of your clients, you could use cloning to avoid doing an initial sync for each client.

NOTE: “Sharing the same data or files” means that clients subscribe to a schema table or a sync folder with the same parameter values. This includes no parameter subscriptions.

Let’s call the client to clone from the “seed client” and the client to clone to the “target client”. The idea is to sync the data and files to the seed client, make a copy of the seed client and change the client ID and user name to those of the target client. Following are the cloning steps.

  1. Create publications, clients and subscriptions on Pervasync Admin Console.
  2. Install and sync the seed client. For fast synchronization, install the client on the same host or network as the Pervasync server.
  3. Copy the seed client to target client hosts. Includes Pervasync client home folder, local database and folders synced to client. Refer to documentation of the specific database type (Oracle, MySQL) on how to clone the database schemas to another host. Remember to include both Pervasync admin schema (default “pvcadmin”) and the application schema(s) when you clone the databases.
  4. On Pervasync Admin Console, click on the “Clients” tab and find the client ID, user name and device name of the target client. Also create subscriptions for the target client if you haven’t done so.
  5. On the target client host, connect to the Pervasync admin schema (default “pvcadmin”) of the local database. Change the client ID, user name and device name in table pvc$sync_client_properties from seed client to target client. Assuming your target client ID is 12, client name is “user_2” and device name is “DEFAULT”, do the following:

    update pvcadmin.pvc$sync_client_properties set value=’12’ where name = ‘pervasync.client.id’;

    update pvcadmin.pvc$sync_client_properties set value=’user_2′ where name = ‘pervasync.user.name’;

    update pvcadmin.pvc$sync_client_properties set value=’DEFAULT’ where name = ‘pervasync.device.name’;

  6. On the target client host, open file <Pervasync Client Home>/config/pervasync_install.dat. You may need to change some parameter values. For example, if the database is on a different host than the sync client host, you will need to correct values of pervasync.client.db.url and pervasync.client.host.

    NOTE: If Pervasync client and DB are on the same host, you should use “localhost” in the values when you setup the seed client. Then you don’t need to update the pervasync_install.dat file.

  7. On the target client host, launch the sync client (pvc.bat or pvc.sh). You will find that the new values are reflected on the “Setup” tab. Use the same tab to update sync user password if needed.
  8. Start a sync session. You will see that shared data/files are not re-synced while client specific data/file subscriptions are synced to client.

NOTE: Make sure you have all the sync folder files on the target host. Any missing files will cause delete operations sent to server during synchronization. To avoid accidental deletions, consider using REFRESH-ONLY sync or setting the server config parameter “pervasync.policy.check.in.deletes” to “DISCARD” depending on your business logic.